Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 27b2685

Browse files
livecodeianrunrevmark
authored andcommitted
[[ Bug 12557 ]] Force the use of anti-aliasing when the context has a non-integer transform
1 parent 341ea7d commit 27b2685

File tree

3 files changed

+67
-5
lines changed

3 files changed

+67
-5
lines changed

engine/src/graphicscontext.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,23 @@ static MCGPathRef MCGPathFromMCPath(MCPath *p_path)
124124

125125
////////////////////////////////////////////////////////////////////////////////
126126

127+
bool MCGFloatIsInteger(MCGFloat p_float)
128+
{
129+
return floorf(p_float) == p_float;
130+
}
131+
132+
bool MCGAffineTransformIsInteger(const MCGAffineTransform &p_transform)
133+
{
134+
return MCGFloatIsInteger(p_transform.a) &&
135+
MCGFloatIsInteger(p_transform.b) &&
136+
MCGFloatIsInteger(p_transform.c) &&
137+
MCGFloatIsInteger(p_transform.d) &&
138+
MCGFloatIsInteger(p_transform.tx) &&
139+
MCGFloatIsInteger(p_transform.ty);
140+
}
141+
142+
//////////
143+
127144
void MCGraphicsContext::init(MCGContextRef p_context)
128145
{
129146
m_gcontext = MCGContextRetain(p_context);
@@ -142,6 +159,11 @@ void MCGraphicsContext::init(MCGContextRef p_context)
142159
m_dash_lengths = nil;
143160
m_dash_count = 0;
144161

162+
// IM-2014-06-19: [[ Bug 12557 ]] Force antialiasing if the underlying context has a non-integer transform set
163+
m_force_antialiasing = !MCGAffineTransformIsInteger(MCGContextGetDeviceTransform(p_context));
164+
if (m_force_antialiasing)
165+
MCGContextSetShouldAntialias(p_context, true);
166+
145167
MCGContextSetFlatness(p_context, 1 / 16.0f);
146168
}
147169

@@ -317,7 +339,8 @@ void MCGraphicsContext::clearorigin(void)
317339

318340
void MCGraphicsContext::setquality(uint1 p_quality)
319341
{
320-
MCGContextSetShouldAntialias(m_gcontext, p_quality == QUALITY_SMOOTH);
342+
if (!m_force_antialiasing)
343+
MCGContextSetShouldAntialias(m_gcontext, p_quality == QUALITY_SMOOTH);
321344
}
322345

323346
void MCGraphicsContext::setfunction(uint1 p_function)

engine/src/graphicscontext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class MCGraphicsContext : public MCContext
113113
MCGFloat m_dash_phase;
114114
MCGFloat *m_dash_lengths;
115115
uint32_t m_dash_count;
116+
117+
// IM-2014-06-19: [[ Bug 12557 ]] Override for the antialias setting
118+
bool m_force_antialiasing;
116119
};
117120

118121
// MW-2014-01-07: [[ Bug 11632 ]] The player object distinguishes between 'screen' and 'offscreen' - in the

libgraphics/src/context.cpp

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,10 +2386,46 @@ static bool MCGContextDrawSkBitmap(MCGContextRef self, const SkBitmap &p_bitmap,
23862386
{
23872387
// MM-2014-03-12: [[ Bug 11892 ]] If we are not transforming the image, there's no need to apply any filtering.
23882388
// Was causing issues in Skia with non null blend modes.
2389-
SkMatrix::TypeMask t_transform_type;
2390-
t_transform_type = self -> layer -> canvas -> getTotalMatrix() . getType();
2391-
if ((t_transform_type == SkMatrix::kIdentity_Mask || t_transform_type == SkMatrix::kTranslate_Mask) &&
2392-
p_bitmap . width() == p_dst . size . width && p_bitmap . height() == p_dst . size . height)
2389+
2390+
// IM-2014-06-19: [[ Bug 12557 ]] More rigourous check to see if we need a filter - Skia will complain if a filter
2391+
// is used for translation-only transforms or scaling transforms close to the identity.
2392+
SkMatrix t_matrix;
2393+
t_matrix = self->layer->canvas->getTotalMatrix();
2394+
2395+
MCGRectangle t_tmp_src;
2396+
MCGFloat t_src_width, t_src_height;
2397+
if (p_src != nil)
2398+
t_tmp_src = *p_src;
2399+
else
2400+
t_tmp_src = MCGRectangleMake(0, 0, p_bitmap.width(), p_bitmap.height());
2401+
2402+
// preconcat the current transform with the transformation from source -> dest rect to obtain the total transformation.
2403+
SkMatrix t_rect_to_rect;
2404+
t_rect_to_rect.setRectToRect(MCGRectangleToSkRect(t_tmp_src), MCGRectangleToSkRect(p_dst), SkMatrix::kFill_ScaleToFit);
2405+
2406+
t_matrix.preConcat(t_rect_to_rect);
2407+
2408+
bool t_no_filter = false;
2409+
2410+
// Translation only - no filter
2411+
if ((t_matrix.getType() & ~SkMatrix::kTranslate_Mask) == 0)
2412+
t_no_filter = true;
2413+
else if ((t_matrix.getType() & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0)
2414+
{
2415+
// Translate and scale - if the transformed & rounded destination is the same size as the source then don't filter
2416+
SkRect src, dst;
2417+
src.setXYWH(t_tmp_src.origin.x, t_tmp_src.origin.y, t_tmp_src.size.width, t_tmp_src.size.height);
2418+
2419+
t_matrix.mapPoints(SkTCast<SkPoint*>(&dst),
2420+
SkTCast<const SkPoint*>(&src),
2421+
2);
2422+
2423+
SkIRect idst;
2424+
dst.round(&idst);
2425+
t_no_filter = idst.width() == t_tmp_src.size.width && idst.height() == t_tmp_src.size.height;
2426+
}
2427+
2428+
if (t_no_filter)
23932429
{
23942430
t_paint . setAntiAlias(false);
23952431
t_paint . setFilterLevel(SkPaint::kNone_FilterLevel);

0 commit comments

Comments
 (0)