OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* ftsmooth.c */ | 3 /* ftsmooth.c */ |
4 /* */ | 4 /* */ |
5 /* Anti-aliasing renderer interface (body). */ | 5 /* Anti-aliasing renderer interface (body). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 2000-2006, 2009-2013 by */ | 7 /* Copyright 2000-2006, 2009-2013 by */ |
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
9 /* */ | 9 /* */ |
10 /* This file is part of the FreeType project, and may only be used, */ | 10 /* This file is part of the FreeType project, and may only be used, */ |
11 /* modified, and distributed under the terms of the FreeType project */ | 11 /* modified, and distributed under the terms of the FreeType project */ |
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
13 /* this file you indicate that you have read the license and */ | 13 /* this file you indicate that you have read the license and */ |
14 /* understand and accept it fully. */ | 14 /* understand and accept it fully. */ |
15 /* */ | 15 /* */ |
16 /***************************************************************************/ | 16 /***************************************************************************/ |
17 | 17 |
18 | 18 |
19 #include "../../include/ft2build.h" | 19 #include <ft2build.h> |
20 #include "../../include/freetype/internal/ftdebug.h" | 20 #include FT_INTERNAL_DEBUG_H |
21 #include "../../include/freetype/internal/ftobjs.h" | 21 #include FT_INTERNAL_OBJECTS_H |
22 #include "../../include/freetype/ftoutln.h" | 22 #include FT_OUTLINE_H |
23 #include "ftsmooth.h" | 23 #include "ftsmooth.h" |
24 #include "ftgrays.h" | 24 #include "ftgrays.h" |
25 #include "ftspic.h" | 25 #include "ftspic.h" |
26 | 26 |
27 #include "ftsmerrs.h" | 27 #include "ftsmerrs.h" |
28 | 28 |
29 | 29 |
30 /* initialize renderer -- init its raster */ | 30 /* initialize renderer -- init its raster */ |
31 static FT_Error | 31 static FT_Error |
32 ft_smooth_init( FT_Renderer render ) | 32 ft_smooth_init( FT_Renderer render ) |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 | 96 |
97 /* convert a slot's glyph image into a bitmap */ | 97 /* convert a slot's glyph image into a bitmap */ |
98 static FT_Error | 98 static FT_Error |
99 ft_smooth_render_generic( FT_Renderer render, | 99 ft_smooth_render_generic( FT_Renderer render, |
100 FT_GlyphSlot slot, | 100 FT_GlyphSlot slot, |
101 FT_Render_Mode mode, | 101 FT_Render_Mode mode, |
102 const FT_Vector* origin, | 102 const FT_Vector* origin, |
103 FT_Render_Mode required_mode ) | 103 FT_Render_Mode required_mode ) |
104 { | 104 { |
105 FT_Error error; | 105 FT_Error error; |
106 FT_Outline* outline = NULL; | 106 FT_Outline* outline = &slot->outline; |
| 107 FT_Bitmap* bitmap = &slot->bitmap; |
| 108 FT_Memory memory = render->root.memory; |
107 FT_BBox cbox; | 109 FT_BBox cbox; |
| 110 FT_Pos x_shift = 0; |
| 111 FT_Pos y_shift = 0; |
| 112 FT_Pos x_left, y_top; |
108 FT_Pos width, height, pitch; | 113 FT_Pos width, height, pitch; |
109 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING | 114 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING |
110 FT_Pos height_org, width_org; | 115 FT_Pos height_org, width_org; |
111 #endif | 116 #endif |
112 FT_Bitmap* bitmap = &slot->bitmap; | |
113 FT_Memory memory = render->root.memory; | |
114 FT_Int hmul = mode == FT_RENDER_MODE_LCD; | 117 FT_Int hmul = mode == FT_RENDER_MODE_LCD; |
115 FT_Int vmul = mode == FT_RENDER_MODE_LCD_V; | 118 FT_Int vmul = mode == FT_RENDER_MODE_LCD_V; |
116 FT_Pos x_shift = 0; | |
117 FT_Pos y_shift = 0; | |
118 FT_Pos x_left, y_top; | |
119 | 119 |
120 FT_Raster_Params params; | 120 FT_Raster_Params params; |
121 | 121 |
122 FT_Bool have_translated_origin = FALSE; | 122 FT_Bool have_outline_shifted = FALSE; |
123 FT_Bool have_outline_shifted = FALSE; | 123 FT_Bool have_buffer = FALSE; |
124 FT_Bool have_buffer = FALSE; | |
125 | 124 |
126 | 125 |
127 /* check glyph image format */ | 126 /* check glyph image format */ |
128 if ( slot->format != render->glyph_format ) | 127 if ( slot->format != render->glyph_format ) |
129 { | 128 { |
130 error = FT_THROW( Invalid_Argument ); | 129 error = FT_THROW( Invalid_Argument ); |
131 goto Exit; | 130 goto Exit; |
132 } | 131 } |
133 | 132 |
134 /* check mode */ | 133 /* check mode */ |
135 if ( mode != required_mode ) | 134 if ( mode != required_mode ) |
136 { | 135 { |
137 error = FT_THROW( Cannot_Render_Glyph ); | 136 error = FT_THROW( Cannot_Render_Glyph ); |
138 goto Exit; | 137 goto Exit; |
139 } | 138 } |
140 | 139 |
141 outline = &slot->outline; | |
142 | |
143 /* translate the outline to the new origin if needed */ | |
144 if ( origin ) | 140 if ( origin ) |
145 { | 141 { |
146 FT_Outline_Translate( outline, origin->x, origin->y ); | 142 x_shift = origin->x; |
147 have_translated_origin = TRUE; | 143 y_shift = origin->y; |
148 } | 144 } |
149 | 145 |
150 /* compute the control box, and grid fit it */ | 146 /* compute the control box, and grid fit it */ |
| 147 /* taking into account the origin shift */ |
151 FT_Outline_Get_CBox( outline, &cbox ); | 148 FT_Outline_Get_CBox( outline, &cbox ); |
152 | 149 |
153 cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); | 150 cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift ); |
154 cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); | 151 cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift ); |
155 cbox.xMax = FT_PIX_CEIL( cbox.xMax ); | 152 cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift ); |
156 cbox.yMax = FT_PIX_CEIL( cbox.yMax ); | 153 cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift ); |
157 | 154 |
158 if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin ) | 155 x_shift -= cbox.xMin; |
159 { | 156 y_shift -= cbox.yMin; |
160 FT_ERROR(( "ft_smooth_render_generic: glyph too large:" | |
161 " xMin = %d, xMax = %d\n", | |
162 cbox.xMin >> 6, cbox.xMax >> 6 )); | |
163 error = FT_THROW( Raster_Overflow ); | |
164 goto Exit; | |
165 } | |
166 else | |
167 width = ( cbox.xMax - cbox.xMin ) >> 6; | |
168 | 157 |
169 if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin ) | 158 x_left = cbox.xMin >> 6; |
170 { | 159 y_top = cbox.yMax >> 6; |
171 FT_ERROR(( "ft_smooth_render_generic: glyph too large:" | 160 |
172 " yMin = %d, yMax = %d\n", | 161 width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6; |
173 cbox.yMin >> 6, cbox.yMax >> 6 )); | 162 height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6; |
174 error = FT_THROW( Raster_Overflow ); | |
175 goto Exit; | |
176 } | |
177 else | |
178 height = ( cbox.yMax - cbox.yMin ) >> 6; | |
179 | 163 |
180 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING | 164 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING |
181 width_org = width; | 165 width_org = width; |
182 height_org = height; | 166 height_org = height; |
183 #endif | 167 #endif |
184 | 168 |
185 /* release old bitmap buffer */ | |
186 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) | |
187 { | |
188 FT_FREE( bitmap->buffer ); | |
189 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; | |
190 } | |
191 | |
192 /* allocate new one */ | |
193 pitch = width; | 169 pitch = width; |
194 if ( hmul ) | 170 if ( hmul ) |
195 { | 171 { |
196 width = width * 3; | 172 width *= 3; |
197 pitch = FT_PAD_CEIL( width, 4 ); | 173 pitch = FT_PAD_CEIL( width, 4 ); |
198 } | 174 } |
199 | 175 |
200 if ( vmul ) | 176 if ( vmul ) |
201 height *= 3; | 177 height *= 3; |
202 | 178 |
203 x_shift = (FT_Int) cbox.xMin; | |
204 y_shift = (FT_Int) cbox.yMin; | |
205 x_left = (FT_Int)( cbox.xMin >> 6 ); | |
206 y_top = (FT_Int)( cbox.yMax >> 6 ); | |
207 | |
208 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING | 179 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING |
209 | 180 |
210 if ( slot->library->lcd_filter_func ) | 181 if ( slot->library->lcd_filter_func ) |
211 { | 182 { |
212 FT_Int extra = slot->library->lcd_extra; | 183 FT_Int extra = slot->library->lcd_extra; |
213 | 184 |
214 | 185 |
215 if ( hmul ) | 186 if ( hmul ) |
216 { | 187 { |
217 x_shift -= 64 * ( extra >> 1 ); | 188 x_shift += 64 * ( extra >> 1 ); |
| 189 x_left -= extra >> 1; |
218 width += 3 * extra; | 190 width += 3 * extra; |
219 pitch = FT_PAD_CEIL( width, 4 ); | 191 pitch = FT_PAD_CEIL( width, 4 ); |
220 x_left -= extra >> 1; | |
221 } | 192 } |
222 | 193 |
223 if ( vmul ) | 194 if ( vmul ) |
224 { | 195 { |
225 y_shift -= 64 * ( extra >> 1 ); | 196 y_shift += 64 * ( extra >> 1 ); |
| 197 y_top += extra >> 1; |
226 height += 3 * extra; | 198 height += 3 * extra; |
227 y_top += extra >> 1; | |
228 } | 199 } |
229 } | 200 } |
230 | 201 |
231 #endif | 202 #endif |
232 | 203 |
233 #if FT_UINT_MAX > 0xFFFFU | 204 /* |
| 205 * XXX: on 16bit system, we return an error for huge bitmap |
| 206 * to prevent an overflow. |
| 207 */ |
| 208 if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX || |
| 209 x_left < FT_INT_MIN || y_top < FT_INT_MIN ) |
| 210 { |
| 211 error = FT_THROW( Invalid_Pixel_Size ); |
| 212 goto Exit; |
| 213 } |
234 | 214 |
235 /* Required check is (pitch * height < FT_ULONG_MAX), */ | 215 /* Required check is (pitch * height < FT_ULONG_MAX), */ |
236 /* but we care realistic cases only. Always pitch <= width. */ | 216 /* but we care realistic cases only. Always pitch <= width. */ |
237 if ( width > 0x7FFF || height > 0x7FFF ) | 217 if ( width > 0x7FFF || height > 0x7FFF ) |
238 { | 218 { |
239 FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n", | 219 FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n", |
240 width, height )); | 220 width, height )); |
241 error = FT_THROW( Raster_Overflow ); | 221 error = FT_THROW( Raster_Overflow ); |
242 goto Exit; | 222 goto Exit; |
243 } | 223 } |
244 | 224 |
245 #endif | 225 /* release old bitmap buffer */ |
| 226 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) |
| 227 { |
| 228 FT_FREE( bitmap->buffer ); |
| 229 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; |
| 230 } |
| 231 |
| 232 /* allocate new one */ |
| 233 if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) ) |
| 234 goto Exit; |
| 235 else |
| 236 have_buffer = TRUE; |
| 237 |
| 238 slot->internal->flags |= FT_GLYPH_OWN_BITMAP; |
| 239 |
| 240 slot->format = FT_GLYPH_FORMAT_BITMAP; |
| 241 slot->bitmap_left = (FT_Int)x_left; |
| 242 slot->bitmap_top = (FT_Int)y_top; |
246 | 243 |
247 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; | 244 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; |
248 bitmap->num_grays = 256; | 245 bitmap->num_grays = 256; |
249 bitmap->width = width; | 246 bitmap->width = width; |
250 bitmap->rows = height; | 247 bitmap->rows = height; |
251 bitmap->pitch = pitch; | 248 bitmap->pitch = pitch; |
252 | 249 |
253 /* translate outline to render it into the bitmap */ | 250 /* translate outline to render it into the bitmap */ |
254 FT_Outline_Translate( outline, -x_shift, -y_shift ); | 251 if ( x_shift || y_shift ) |
255 have_outline_shifted = TRUE; | 252 { |
256 | 253 FT_Outline_Translate( outline, x_shift, y_shift ); |
257 if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) ) | 254 have_outline_shifted = TRUE; |
258 goto Exit; | 255 } |
259 else | |
260 have_buffer = TRUE; | |
261 | |
262 slot->internal->flags |= FT_GLYPH_OWN_BITMAP; | |
263 | 256 |
264 /* set up parameters */ | 257 /* set up parameters */ |
265 params.target = bitmap; | 258 params.target = bitmap; |
266 params.source = outline; | 259 params.source = outline; |
267 params.flags = FT_RASTER_FLAG_AA; | 260 params.flags = FT_RASTER_FLAG_AA; |
268 | 261 |
269 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING | 262 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING |
270 | 263 |
271 /* implode outline if needed */ | 264 /* implode outline if needed */ |
272 { | 265 { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 write += pitch; | 352 write += pitch; |
360 | 353 |
361 ft_memcpy( write, read, pitch ); | 354 ft_memcpy( write, read, pitch ); |
362 write += pitch; | 355 write += pitch; |
363 read += pitch; | 356 read += pitch; |
364 } | 357 } |
365 } | 358 } |
366 | 359 |
367 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ | 360 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ |
368 | 361 |
369 /* | |
370 * XXX: on 16bit system, we return an error for huge bitmap | |
371 * to prevent an overflow. | |
372 */ | |
373 if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ) | |
374 { | |
375 error = FT_THROW( Invalid_Pixel_Size ); | |
376 goto Exit; | |
377 } | |
378 | |
379 slot->format = FT_GLYPH_FORMAT_BITMAP; | |
380 slot->bitmap_left = (FT_Int)x_left; | |
381 slot->bitmap_top = (FT_Int)y_top; | |
382 | |
383 /* everything is fine; don't deallocate buffer */ | 362 /* everything is fine; don't deallocate buffer */ |
384 have_buffer = FALSE; | 363 have_buffer = FALSE; |
385 | 364 |
386 error = FT_Err_Ok; | 365 error = FT_Err_Ok; |
387 | 366 |
388 Exit: | 367 Exit: |
389 if ( have_outline_shifted ) | 368 if ( have_outline_shifted ) |
390 FT_Outline_Translate( outline, x_shift, y_shift ); | 369 FT_Outline_Translate( outline, -x_shift, -y_shift ); |
391 if ( have_translated_origin ) | |
392 FT_Outline_Translate( outline, -origin->x, -origin->y ); | |
393 if ( have_buffer ) | 370 if ( have_buffer ) |
394 { | 371 { |
395 FT_FREE( bitmap->buffer ); | 372 FT_FREE( bitmap->buffer ); |
396 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; | 373 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; |
397 } | 374 } |
398 | 375 |
399 return error; | 376 return error; |
400 } | 377 } |
401 | 378 |
402 | 379 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v, | 502 (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v, |
526 (FT_Renderer_TransformFunc)ft_smooth_transform, | 503 (FT_Renderer_TransformFunc)ft_smooth_transform, |
527 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, | 504 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, |
528 (FT_Renderer_SetModeFunc) ft_smooth_set_mode, | 505 (FT_Renderer_SetModeFunc) ft_smooth_set_mode, |
529 | 506 |
530 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET | 507 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET |
531 ) | 508 ) |
532 | 509 |
533 | 510 |
534 /* END */ | 511 /* END */ |
OLD | NEW |