@@ -44,13 +44,25 @@ static inline MCGRectangle MCGRectangleFromPangoRectangle(const PangoRectangle &
4444 return MCGRectangleMake (p_rect.x / (MCGFloat)PANGO_SCALE, p_rect.y / (MCGFloat)PANGO_SCALE, p_rect.width / (MCGFloat)PANGO_SCALE, p_rect.height / (MCGFloat)PANGO_SCALE);
4545}
4646
47+ static inline PangoMatrix MCGAffineTransformToPangoMatrix (const MCGAffineTransform &p_transform)
48+ {
49+ PangoMatrix t_matrix;
50+ t_matrix . xx = p_transform . a;
51+ t_matrix . yx = p_transform . b;
52+ t_matrix . xy = p_transform . c;
53+ t_matrix . yy = p_transform . d;
54+ t_matrix . x0 = p_transform . tx;
55+ t_matrix . y0 = p_transform . ty;
56+ return t_matrix;
57+ }
58+
4759// //////////////////////////////////////////////////////////////////////////////
4860
4961static PangoFontMap *s_font_map = NULL ;
5062static PangoContext *s_pango = NULL ;
5163static PangoLayout *s_layout = NULL ;
5264
53- static bool lnx_pango_objects_intialize ()
65+ static bool lnx_pango_objects_initialize ()
5466{
5567 bool t_success;
5668 t_success = true ;
@@ -91,7 +103,7 @@ static bool lnx_pango_initialize(void)
91103
92104
93105 if (t_success)
94- t_success = lnx_pango_objects_intialize ();
106+ t_success = lnx_pango_objects_initialize ();
95107
96108 return t_success;
97109}
@@ -141,25 +153,19 @@ void MCGContextDrawPlatformText(MCGContextRef self, const unichar_t *p_text, uin
141153 t_success = MCCStringFromUnicodeSubstring (p_text, p_length / 2 , t_text);
142154
143155 MCGAffineTransform t_transform;
144- MCGPoint t_device_location;
156+ t_transform = MCGContextGetDeviceTransform (self);
157+
145158 PangoLayoutLine *t_line;
146159 t_line = nil;
147160 if (t_success)
148161 {
149- t_transform = MCGContextGetDeviceTransform (self);
150- t_device_location = MCGPointApplyAffineTransform (p_location, t_transform);
151- t_transform . tx = modff (t_device_location . x, &t_device_location . x);
152- t_transform . ty = modff (t_device_location . y, &t_device_location . y);
153-
154- PangoMatrix t_ptransform;
155- t_ptransform . xx = t_transform . a;
156- t_ptransform . xy = t_transform . b;
157- t_ptransform . yx = t_transform . c;
158- t_ptransform . yy = t_transform . d;
159- t_ptransform . x0 = t_transform . tx;
160- t_ptransform . y0 = t_transform . ty;
162+ // The transform needs to be applied before setting the text + font,
163+ // otherwise the glyph orientation will be incorrectly set from the
164+ // previous transform.
165+ PangoMatrix t_ptransform;
166+ t_ptransform = MCGAffineTransformToPangoMatrix (t_transform);
161167 pango_context_set_matrix (s_pango, &t_ptransform);
162-
168+
163169 pango_layout_set_font_description (s_layout, (PangoFontDescription *) p_font . fid);
164170 pango_layout_set_text (s_layout, t_text, -1 );
165171 MCCStringFree (t_text);
@@ -172,7 +178,7 @@ void MCGContextDrawPlatformText(MCGContextRef self, const unichar_t *p_text, uin
172178 t_success = t_line != nil;
173179 }
174180
175- MCGIntRectangle t_text_bounds, t_clipped_bounds ;
181+ MCGIntegerRectangle t_bitmap_bounds ;
176182 if (t_success)
177183 {
178184 PangoRectangle t_pbounds;
@@ -181,45 +187,52 @@ void MCGContextDrawPlatformText(MCGContextRef self, const unichar_t *p_text, uin
181187 MCGRectangle t_float_text_bounds;
182188 t_float_text_bounds = MCGRectangleFromPangoRectangle (t_pbounds);
183189
190+ // Apply translation to put target location at the origin
191+ t_transform = MCGAffineTransformPostTranslate (t_transform, p_location.x , p_location.y );
192+
193+ MCGRectangle t_device_text_bounds;
194+ t_device_text_bounds = MCGRectangleApplyAffineTransform (t_float_text_bounds, t_transform);
195+
184196 MCGRectangle t_device_clip;
185197 t_device_clip = MCGContextGetDeviceClipBounds (self);
186- t_device_clip . origin . x -= t_device_location . x;
187- t_device_clip . origin . y -= t_device_location . y;
188-
189- MCGRectangle t_float_clipped_bounds;
190- t_float_clipped_bounds = MCGRectangleIntersection (t_float_text_bounds, t_device_clip);
191-
192- t_text_bounds = MCGRectangleIntegerBounds (t_float_text_bounds);
193- t_clipped_bounds = MCGRectangleIntegerBounds (t_float_clipped_bounds);
198+
199+ t_bitmap_bounds = MCGRectangleGetBounds (MCGRectangleIntersection (t_device_text_bounds, t_device_clip));
194200
195- if (t_clipped_bounds . width == 0 || t_clipped_bounds . height == 0 )
201+ if (t_bitmap_bounds. size . width == 0 || t_bitmap_bounds. size . height == 0 )
196202 return ;
197203 }
198204
199205 void *t_data;
200206 t_data = nil;
201207 if (t_success)
202- t_success = MCMemoryNew (t_clipped_bounds . width * t_clipped_bounds . height, t_data);
208+ t_success = MCMemoryNew (t_bitmap_bounds. size . width * t_bitmap_bounds. size . height , t_data);
203209
204210 if (t_success)
205211 {
206212 FT_Bitmap t_ftbitmap;
207- t_ftbitmap . rows = t_clipped_bounds . height;
208- t_ftbitmap . width = t_clipped_bounds . width;
209- t_ftbitmap . pitch = t_clipped_bounds . width;
213+ t_ftbitmap . rows = t_bitmap_bounds. size . height ;
214+ t_ftbitmap . width = t_bitmap_bounds. size . width ;
215+ t_ftbitmap . pitch = t_bitmap_bounds. size . width ;
210216 t_ftbitmap . buffer = (unsigned char *) t_data;
211217 t_ftbitmap . num_grays = 256 ;
212218 t_ftbitmap . pixel_mode = FT_PIXEL_MODE_GRAY;
213219 t_ftbitmap . palette_mode = 0 ;
214220 t_ftbitmap . palette = nil;
221+
222+ // Apply translation to offset drawing into the bitmap
223+ t_transform = MCGAffineTransformPreTranslate (t_transform, -t_bitmap_bounds.origin .x , -t_bitmap_bounds.origin .y );
224+
225+ PangoMatrix t_ptransform;
226+ t_ptransform = MCGAffineTransformToPangoMatrix (t_transform);
227+ pango_context_set_matrix (s_pango, &t_ptransform);
215228
216- pango_ft2_render_layout_line (&t_ftbitmap, t_line, -(t_clipped_bounds . x - t_text_bounds . x), -(t_clipped_bounds . y - t_text_bounds . y) - t_text_bounds . y );
229+ pango_ft2_render_layout_line (&t_ftbitmap, t_line, 0 , 0 );
217230
218231 // The paint containing the fill settings
219232 SkPaint t_paint;
220233 if (MCGContextSetupFill (self, t_paint))
221234 {
222- SkImageInfo t_info = SkImageInfo::MakeA8 (t_clipped_bounds. width , t_clipped_bounds .height );
235+ SkImageInfo t_info = SkImageInfo::MakeA8 (t_bitmap_bounds. size . width , t_bitmap_bounds. size .height );
223236
224237 SkBitmap t_bitmap;
225238 t_bitmap.setInfo (t_info);
@@ -228,8 +241,8 @@ void MCGContextDrawPlatformText(MCGContextRef self, const unichar_t *p_text, uin
228241 self->layer ->canvas ->save ();
229242 self->layer ->canvas ->resetMatrix ();
230243 self->layer ->canvas ->drawBitmap (t_bitmap,
231- t_clipped_bounds. x + t_device_location .x ,
232- t_clipped_bounds. y + t_device_location .y ,
244+ t_bitmap_bounds. origin .x ,
245+ t_bitmap_bounds. origin .y ,
233246 &t_paint);
234247 self->layer ->canvas ->restore ();
235248 }
@@ -284,7 +297,7 @@ bool MCGContextMeasurePlatformTextImageBounds(MCGContextRef self, const unichar_
284297 t_success = true ;
285298
286299 if (t_success)
287- t_success = lnx_pango_objects_intialize ();
300+ t_success = lnx_pango_objects_initialize ();
288301
289302 char *t_text;
290303 t_text = nil;
0 commit comments