00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_DEBUG_H
00021 #include FT_INTERNAL_OBJECTS_H
00022 #include FT_OUTLINE_H
00023 #include "ftsmooth.h"
00024 #include "ftgrays.h"
00025 #include "ftspic.h"
00026
00027 #include "ftsmerrs.h"
00028
00029
00030
00031 static FT_Error
00032 ft_smooth_init( FT_Renderer render )
00033 {
00034 FT_Library library = FT_MODULE_LIBRARY( render );
00035
00036
00037 render->clazz->raster_class->raster_reset( render->raster,
00038 library->raster_pool,
00039 library->raster_pool_size );
00040
00041 return 0;
00042 }
00043
00044
00045
00046 static FT_Error
00047 ft_smooth_set_mode( FT_Renderer render,
00048 FT_ULong mode_tag,
00049 FT_Pointer data )
00050 {
00051
00052 return render->clazz->raster_class->raster_set_mode( render->raster,
00053 mode_tag,
00054 data );
00055 }
00056
00057
00058 static FT_Error
00059 ft_smooth_transform( FT_Renderer render,
00060 FT_GlyphSlot slot,
00061 const FT_Matrix* matrix,
00062 const FT_Vector* delta )
00063 {
00064 FT_Error error = Smooth_Err_Ok;
00065
00066
00067 if ( slot->format != render->glyph_format )
00068 {
00069 error = Smooth_Err_Invalid_Argument;
00070 goto Exit;
00071 }
00072
00073 if ( matrix )
00074 FT_Outline_Transform( &slot->outline, matrix );
00075
00076 if ( delta )
00077 FT_Outline_Translate( &slot->outline, delta->x, delta->y );
00078
00079 Exit:
00080 return error;
00081 }
00082
00083
00084
00085 static void
00086 ft_smooth_get_cbox( FT_Renderer render,
00087 FT_GlyphSlot slot,
00088 FT_BBox* cbox )
00089 {
00090 FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
00091
00092 if ( slot->format == render->glyph_format )
00093 FT_Outline_Get_CBox( &slot->outline, cbox );
00094 }
00095
00096
00097
00098 static FT_Error
00099 ft_smooth_render_generic( FT_Renderer render,
00100 FT_GlyphSlot slot,
00101 FT_Render_Mode mode,
00102 const FT_Vector* origin,
00103 FT_Render_Mode required_mode )
00104 {
00105 FT_Error error;
00106 FT_Outline* outline = NULL;
00107 FT_BBox cbox;
00108 FT_UInt width, height, height_org, width_org, pitch;
00109 FT_Bitmap* bitmap;
00110 FT_Memory memory;
00111 FT_Int hmul = mode == FT_RENDER_MODE_LCD;
00112 FT_Int vmul = mode == FT_RENDER_MODE_LCD_V;
00113 FT_Pos x_shift, y_shift, x_left, y_top;
00114
00115 FT_Raster_Params params;
00116
00117
00118
00119 if ( slot->format != render->glyph_format )
00120 {
00121 error = Smooth_Err_Invalid_Argument;
00122 goto Exit;
00123 }
00124
00125
00126 if ( mode != required_mode )
00127 return Smooth_Err_Cannot_Render_Glyph;
00128
00129 outline = &slot->outline;
00130
00131
00132 if ( origin )
00133 FT_Outline_Translate( outline, origin->x, origin->y );
00134
00135
00136 FT_Outline_Get_CBox( outline, &cbox );
00137
00138 cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
00139 cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
00140 cbox.xMax = FT_PIX_CEIL( cbox.xMax );
00141 cbox.yMax = FT_PIX_CEIL( cbox.yMax );
00142
00143 width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
00144 height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
00145 bitmap = &slot->bitmap;
00146 memory = render->root.memory;
00147
00148 width_org = width;
00149 height_org = height;
00150
00151
00152 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
00153 {
00154 FT_FREE( bitmap->buffer );
00155 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
00156 }
00157
00158
00159 pitch = width;
00160 if ( hmul )
00161 {
00162 width = width * 3;
00163 pitch = FT_PAD_CEIL( width, 4 );
00164 }
00165
00166 if ( vmul )
00167 height *= 3;
00168
00169 x_shift = (FT_Int) cbox.xMin;
00170 y_shift = (FT_Int) cbox.yMin;
00171 x_left = (FT_Int)( cbox.xMin >> 6 );
00172 y_top = (FT_Int)( cbox.yMax >> 6 );
00173
00174 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
00175
00176 if ( slot->library->lcd_filter_func )
00177 {
00178 FT_Int extra = slot->library->lcd_extra;
00179
00180
00181 if ( hmul )
00182 {
00183 x_shift -= 64 * ( extra >> 1 );
00184 width += 3 * extra;
00185 pitch = FT_PAD_CEIL( width, 4 );
00186 x_left -= extra >> 1;
00187 }
00188
00189 if ( vmul )
00190 {
00191 y_shift -= 64 * ( extra >> 1 );
00192 height += 3 * extra;
00193 y_top += extra >> 1;
00194 }
00195 }
00196
00197 #endif
00198
00199 #if FT_UINT_MAX > 0xFFFFU
00200
00201
00202
00203 if ( width > 0xFFFFU || height > 0xFFFFU )
00204 {
00205 FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n",
00206 width, height ));
00207 return Smooth_Err_Raster_Overflow;
00208 }
00209
00210 #endif
00211
00212 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
00213 bitmap->num_grays = 256;
00214 bitmap->width = width;
00215 bitmap->rows = height;
00216 bitmap->pitch = pitch;
00217
00218
00219 FT_Outline_Translate( outline, -x_shift, -y_shift );
00220
00221 if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
00222 goto Exit;
00223
00224 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
00225
00226
00227 params.target = bitmap;
00228 params.source = outline;
00229 params.flags = FT_RASTER_FLAG_AA;
00230
00231 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
00232
00233
00234 {
00235 FT_Vector* points = outline->points;
00236 FT_Vector* points_end = points + outline->n_points;
00237 FT_Vector* vec;
00238
00239
00240 if ( hmul )
00241 for ( vec = points; vec < points_end; vec++ )
00242 vec->x *= 3;
00243
00244 if ( vmul )
00245 for ( vec = points; vec < points_end; vec++ )
00246 vec->y *= 3;
00247 }
00248
00249
00250 error = render->raster_render( render->raster, ¶ms );
00251
00252
00253 {
00254 FT_Vector* points = outline->points;
00255 FT_Vector* points_end = points + outline->n_points;
00256 FT_Vector* vec;
00257
00258
00259 if ( hmul )
00260 for ( vec = points; vec < points_end; vec++ )
00261 vec->x /= 3;
00262
00263 if ( vmul )
00264 for ( vec = points; vec < points_end; vec++ )
00265 vec->y /= 3;
00266 }
00267
00268 if ( slot->library->lcd_filter_func )
00269 slot->library->lcd_filter_func( bitmap, mode, slot->library );
00270
00271 #else
00272
00273
00274 error = render->raster_render( render->raster, ¶ms );
00275
00276
00277 if ( hmul )
00278 {
00279 FT_Byte* line = bitmap->buffer;
00280 FT_UInt hh;
00281
00282
00283 for ( hh = height_org; hh > 0; hh--, line += pitch )
00284 {
00285 FT_UInt xx;
00286 FT_Byte* end = line + width;
00287
00288
00289 for ( xx = width_org; xx > 0; xx-- )
00290 {
00291 FT_UInt pixel = line[xx-1];
00292
00293
00294 end[-3] = (FT_Byte)pixel;
00295 end[-2] = (FT_Byte)pixel;
00296 end[-1] = (FT_Byte)pixel;
00297 end -= 3;
00298 }
00299 }
00300 }
00301
00302
00303 if ( vmul )
00304 {
00305 FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
00306 FT_Byte* write = bitmap->buffer;
00307 FT_UInt hh;
00308
00309
00310 for ( hh = height_org; hh > 0; hh-- )
00311 {
00312 ft_memcpy( write, read, pitch );
00313 write += pitch;
00314
00315 ft_memcpy( write, read, pitch );
00316 write += pitch;
00317
00318 ft_memcpy( write, read, pitch );
00319 write += pitch;
00320 read += pitch;
00321 }
00322 }
00323
00324 #endif
00325
00326 FT_Outline_Translate( outline, x_shift, y_shift );
00327
00328
00329
00330
00331
00332 if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
00333 return Smooth_Err_Invalid_Pixel_Size;
00334
00335 if ( error )
00336 goto Exit;
00337
00338 slot->format = FT_GLYPH_FORMAT_BITMAP;
00339 slot->bitmap_left = (FT_Int)x_left;
00340 slot->bitmap_top = (FT_Int)y_top;
00341
00342 Exit:
00343 if ( outline && origin )
00344 FT_Outline_Translate( outline, -origin->x, -origin->y );
00345
00346 return error;
00347 }
00348
00349
00350
00351 static FT_Error
00352 ft_smooth_render( FT_Renderer render,
00353 FT_GlyphSlot slot,
00354 FT_Render_Mode mode,
00355 const FT_Vector* origin )
00356 {
00357 if ( mode == FT_RENDER_MODE_LIGHT )
00358 mode = FT_RENDER_MODE_NORMAL;
00359
00360 return ft_smooth_render_generic( render, slot, mode, origin,
00361 FT_RENDER_MODE_NORMAL );
00362 }
00363
00364
00365
00366 static FT_Error
00367 ft_smooth_render_lcd( FT_Renderer render,
00368 FT_GlyphSlot slot,
00369 FT_Render_Mode mode,
00370 const FT_Vector* origin )
00371 {
00372 FT_Error error;
00373
00374 error = ft_smooth_render_generic( render, slot, mode, origin,
00375 FT_RENDER_MODE_LCD );
00376 if ( !error )
00377 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
00378
00379 return error;
00380 }
00381
00382
00383
00384 static FT_Error
00385 ft_smooth_render_lcd_v( FT_Renderer render,
00386 FT_GlyphSlot slot,
00387 FT_Render_Mode mode,
00388 const FT_Vector* origin )
00389 {
00390 FT_Error error;
00391
00392 error = ft_smooth_render_generic( render, slot, mode, origin,
00393 FT_RENDER_MODE_LCD_V );
00394 if ( !error )
00395 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
00396
00397 return error;
00398 }
00399
00400
00401 FT_DEFINE_RENDERER(ft_smooth_renderer_class,
00402
00403 FT_MODULE_RENDERER,
00404 sizeof( FT_RendererRec ),
00405
00406 "smooth",
00407 0x10000L,
00408 0x20000L,
00409
00410 0,
00411
00412 (FT_Module_Constructor)ft_smooth_init,
00413 (FT_Module_Destructor) 0,
00414 (FT_Module_Requester) 0
00415 ,
00416
00417 FT_GLYPH_FORMAT_OUTLINE,
00418
00419 (FT_Renderer_RenderFunc) ft_smooth_render,
00420 (FT_Renderer_TransformFunc)ft_smooth_transform,
00421 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
00422 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
00423
00424 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
00425 )
00426
00427
00428 FT_DEFINE_RENDERER(ft_smooth_lcd_renderer_class,
00429
00430 FT_MODULE_RENDERER,
00431 sizeof( FT_RendererRec ),
00432
00433 "smooth-lcd",
00434 0x10000L,
00435 0x20000L,
00436
00437 0,
00438
00439 (FT_Module_Constructor)ft_smooth_init,
00440 (FT_Module_Destructor) 0,
00441 (FT_Module_Requester) 0
00442 ,
00443
00444 FT_GLYPH_FORMAT_OUTLINE,
00445
00446 (FT_Renderer_RenderFunc) ft_smooth_render_lcd,
00447 (FT_Renderer_TransformFunc)ft_smooth_transform,
00448 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
00449 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
00450
00451 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
00452 )
00453
00454 FT_DEFINE_RENDERER(ft_smooth_lcdv_renderer_class,
00455
00456 FT_MODULE_RENDERER,
00457 sizeof( FT_RendererRec ),
00458
00459 "smooth-lcdv",
00460 0x10000L,
00461 0x20000L,
00462
00463 0,
00464
00465 (FT_Module_Constructor)ft_smooth_init,
00466 (FT_Module_Destructor) 0,
00467 (FT_Module_Requester) 0
00468 ,
00469
00470 FT_GLYPH_FORMAT_OUTLINE,
00471
00472 (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v,
00473 (FT_Renderer_TransformFunc)ft_smooth_transform,
00474 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
00475 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
00476
00477 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
00478 )
00479
00480
00481