Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenafloader.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* afloader.c */ 00004 /* */ 00005 /* Auto-fitter glyph loading routines (body). */ 00006 /* */ 00007 /* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 00015 /* */ 00016 /***************************************************************************/ 00017 00018 00019 #include "afloader.h" 00020 #include "afhints.h" 00021 #include "afglobal.h" 00022 #include "aferrors.h" 00023 00024 00025 FT_LOCAL_DEF( FT_Error ) 00026 af_loader_init( AF_Loader loader, 00027 FT_Memory memory ) 00028 { 00029 FT_ZERO( loader ); 00030 00031 af_glyph_hints_init( &loader->hints, memory ); 00032 #ifdef AF_DEBUG 00033 _af_debug_hints = &loader->hints; 00034 #endif 00035 return FT_GlyphLoader_New( memory, &loader->gloader ); 00036 } 00037 00038 00039 FT_LOCAL_DEF( FT_Error ) 00040 af_loader_reset( AF_Loader loader, 00041 FT_Face face ) 00042 { 00043 FT_Error error = AF_Err_Ok; 00044 00045 00046 loader->face = face; 00047 loader->globals = (AF_FaceGlobals)face->autohint.data; 00048 00049 FT_GlyphLoader_Rewind( loader->gloader ); 00050 00051 if ( loader->globals == NULL ) 00052 { 00053 error = af_face_globals_new( face, &loader->globals ); 00054 if ( !error ) 00055 { 00056 face->autohint.data = 00057 (FT_Pointer)loader->globals; 00058 face->autohint.finalizer = 00059 (FT_Generic_Finalizer)af_face_globals_free; 00060 } 00061 } 00062 00063 return error; 00064 } 00065 00066 00067 FT_LOCAL_DEF( void ) 00068 af_loader_done( AF_Loader loader ) 00069 { 00070 af_glyph_hints_done( &loader->hints ); 00071 00072 loader->face = NULL; 00073 loader->globals = NULL; 00074 00075 #ifdef AF_DEBUG 00076 _af_debug_hints = NULL; 00077 #endif 00078 FT_GlyphLoader_Done( loader->gloader ); 00079 loader->gloader = NULL; 00080 } 00081 00082 00083 static FT_Error 00084 af_loader_load_g( AF_Loader loader, 00085 AF_Scaler scaler, 00086 FT_UInt glyph_index, 00087 FT_Int32 load_flags, 00088 FT_UInt depth ) 00089 { 00090 FT_Error error; 00091 FT_Face face = loader->face; 00092 FT_GlyphLoader gloader = loader->gloader; 00093 AF_ScriptMetrics metrics = loader->metrics; 00094 AF_GlyphHints hints = &loader->hints; 00095 FT_GlyphSlot slot = face->glyph; 00096 FT_Slot_Internal internal = slot->internal; 00097 00098 00099 error = FT_Load_Glyph( face, glyph_index, load_flags ); 00100 if ( error ) 00101 goto Exit; 00102 00103 loader->transformed = internal->glyph_transformed; 00104 if ( loader->transformed ) 00105 { 00106 FT_Matrix inverse; 00107 00108 00109 loader->trans_matrix = internal->glyph_matrix; 00110 loader->trans_delta = internal->glyph_delta; 00111 00112 inverse = loader->trans_matrix; 00113 FT_Matrix_Invert( &inverse ); 00114 FT_Vector_Transform( &loader->trans_delta, &inverse ); 00115 } 00116 00117 /* set linear metrics */ 00118 slot->linearHoriAdvance = slot->metrics.horiAdvance; 00119 slot->linearVertAdvance = slot->metrics.vertAdvance; 00120 00121 switch ( slot->format ) 00122 { 00123 case FT_GLYPH_FORMAT_OUTLINE: 00124 /* translate the loaded glyph when an internal transform is needed */ 00125 if ( loader->transformed ) 00126 FT_Outline_Translate( &slot->outline, 00127 loader->trans_delta.x, 00128 loader->trans_delta.y ); 00129 00130 /* copy the outline points in the loader's current */ 00131 /* extra points which is used to keep original glyph coordinates */ 00132 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 00133 slot->outline.n_points + 4, 00134 slot->outline.n_contours ); 00135 if ( error ) 00136 goto Exit; 00137 00138 FT_ARRAY_COPY( gloader->current.outline.points, 00139 slot->outline.points, 00140 slot->outline.n_points ); 00141 00142 FT_ARRAY_COPY( gloader->current.outline.contours, 00143 slot->outline.contours, 00144 slot->outline.n_contours ); 00145 00146 FT_ARRAY_COPY( gloader->current.outline.tags, 00147 slot->outline.tags, 00148 slot->outline.n_points ); 00149 00150 gloader->current.outline.n_points = slot->outline.n_points; 00151 gloader->current.outline.n_contours = slot->outline.n_contours; 00152 00153 /* compute original horizontal phantom points (and ignore */ 00154 /* vertical ones) */ 00155 loader->pp1.x = hints->x_delta; 00156 loader->pp1.y = hints->y_delta; 00157 loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance, 00158 hints->x_scale ) + hints->x_delta; 00159 loader->pp2.y = hints->y_delta; 00160 00161 /* be sure to check for spacing glyphs */ 00162 if ( slot->outline.n_points == 0 ) 00163 goto Hint_Metrics; 00164 00165 /* now load the slot image into the auto-outline and run the */ 00166 /* automatic hinting process */ 00167 if ( metrics->clazz->script_hints_apply ) 00168 metrics->clazz->script_hints_apply( hints, 00169 &gloader->current.outline, 00170 metrics ); 00171 00172 /* we now need to hint the metrics according to the change in */ 00173 /* width/positioning that occurred during the hinting process */ 00174 if ( scaler->render_mode != FT_RENDER_MODE_LIGHT ) 00175 { 00176 FT_Pos old_rsb, old_lsb, new_lsb; 00177 FT_Pos pp1x_uh, pp2x_uh; 00178 AF_AxisHints axis = &hints->axis[AF_DIMENSION_HORZ]; 00179 AF_Edge edge1 = axis->edges; /* leftmost edge */ 00180 AF_Edge edge2 = edge1 + 00181 axis->num_edges - 1; /* rightmost edge */ 00182 00183 00184 if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) ) 00185 { 00186 old_rsb = loader->pp2.x - edge2->opos; 00187 old_lsb = edge1->opos; 00188 new_lsb = edge1->pos; 00189 00190 /* remember unhinted values to later account */ 00191 /* for rounding errors */ 00192 00193 pp1x_uh = new_lsb - old_lsb; 00194 pp2x_uh = edge2->pos + old_rsb; 00195 00196 /* prefer too much space over too little space */ 00197 /* for very small sizes */ 00198 00199 if ( old_lsb < 24 ) 00200 pp1x_uh -= 8; 00201 00202 if ( old_rsb < 24 ) 00203 pp2x_uh += 8; 00204 00205 loader->pp1.x = FT_PIX_ROUND( pp1x_uh ); 00206 loader->pp2.x = FT_PIX_ROUND( pp2x_uh ); 00207 00208 if ( loader->pp1.x >= new_lsb && old_lsb > 0 ) 00209 loader->pp1.x -= 64; 00210 00211 if ( loader->pp2.x <= edge2->pos && old_rsb > 0 ) 00212 loader->pp2.x += 64; 00213 00214 slot->lsb_delta = loader->pp1.x - pp1x_uh; 00215 slot->rsb_delta = loader->pp2.x - pp2x_uh; 00216 } 00217 else 00218 { 00219 FT_Pos pp1x = loader->pp1.x; 00220 FT_Pos pp2x = loader->pp2.x; 00221 00222 00223 loader->pp1.x = FT_PIX_ROUND( pp1x ); 00224 loader->pp2.x = FT_PIX_ROUND( pp2x ); 00225 00226 slot->lsb_delta = loader->pp1.x - pp1x; 00227 slot->rsb_delta = loader->pp2.x - pp2x; 00228 } 00229 } 00230 else 00231 { 00232 FT_Pos pp1x = loader->pp1.x; 00233 FT_Pos pp2x = loader->pp2.x; 00234 00235 00236 loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta ); 00237 loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta ); 00238 00239 slot->lsb_delta = loader->pp1.x - pp1x; 00240 slot->rsb_delta = loader->pp2.x - pp2x; 00241 } 00242 00243 /* good, we simply add the glyph to our loader's base */ 00244 FT_GlyphLoader_Add( gloader ); 00245 break; 00246 00247 case FT_GLYPH_FORMAT_COMPOSITE: 00248 { 00249 FT_UInt nn, num_subglyphs = slot->num_subglyphs; 00250 FT_UInt num_base_subgs, start_point; 00251 FT_SubGlyph subglyph; 00252 00253 00254 start_point = gloader->base.outline.n_points; 00255 00256 /* first of all, copy the subglyph descriptors in the glyph loader */ 00257 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs ); 00258 if ( error ) 00259 goto Exit; 00260 00261 FT_ARRAY_COPY( gloader->current.subglyphs, 00262 slot->subglyphs, 00263 num_subglyphs ); 00264 00265 gloader->current.num_subglyphs = num_subglyphs; 00266 num_base_subgs = gloader->base.num_subglyphs; 00267 00268 /* now, read each subglyph independently */ 00269 for ( nn = 0; nn < num_subglyphs; nn++ ) 00270 { 00271 FT_Vector pp1, pp2; 00272 FT_Pos x, y; 00273 FT_UInt num_points, num_new_points, num_base_points; 00274 00275 00276 /* gloader.current.subglyphs can change during glyph loading due */ 00277 /* to re-allocation -- we must recompute the current subglyph on */ 00278 /* each iteration */ 00279 subglyph = gloader->base.subglyphs + num_base_subgs + nn; 00280 00281 pp1 = loader->pp1; 00282 pp2 = loader->pp2; 00283 00284 num_base_points = gloader->base.outline.n_points; 00285 00286 error = af_loader_load_g( loader, scaler, subglyph->index, 00287 load_flags, depth + 1 ); 00288 if ( error ) 00289 goto Exit; 00290 00291 /* recompute subglyph pointer */ 00292 subglyph = gloader->base.subglyphs + num_base_subgs + nn; 00293 00294 if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ) 00295 { 00296 pp1 = loader->pp1; 00297 pp2 = loader->pp2; 00298 } 00299 else 00300 { 00301 loader->pp1 = pp1; 00302 loader->pp2 = pp2; 00303 } 00304 00305 num_points = gloader->base.outline.n_points; 00306 num_new_points = num_points - num_base_points; 00307 00308 /* now perform the transform required for this subglyph */ 00309 00310 if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE | 00311 FT_SUBGLYPH_FLAG_XY_SCALE | 00312 FT_SUBGLYPH_FLAG_2X2 ) ) 00313 { 00314 FT_Vector* cur = gloader->base.outline.points + 00315 num_base_points; 00316 FT_Vector* limit = cur + num_new_points; 00317 00318 00319 for ( ; cur < limit; cur++ ) 00320 FT_Vector_Transform( cur, &subglyph->transform ); 00321 } 00322 00323 /* apply offset */ 00324 00325 if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) ) 00326 { 00327 FT_Int k = subglyph->arg1; 00328 FT_UInt l = subglyph->arg2; 00329 FT_Vector* p1; 00330 FT_Vector* p2; 00331 00332 00333 if ( start_point + k >= num_base_points || 00334 l >= (FT_UInt)num_new_points ) 00335 { 00336 error = AF_Err_Invalid_Composite; 00337 goto Exit; 00338 } 00339 00340 l += num_base_points; 00341 00342 /* for now, only use the current point coordinates; */ 00343 /* we may consider another approach in the near future */ 00344 p1 = gloader->base.outline.points + start_point + k; 00345 p2 = gloader->base.outline.points + start_point + l; 00346 00347 x = p1->x - p2->x; 00348 y = p1->y - p2->y; 00349 } 00350 else 00351 { 00352 x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta; 00353 y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta; 00354 00355 x = FT_PIX_ROUND( x ); 00356 y = FT_PIX_ROUND( y ); 00357 } 00358 00359 { 00360 FT_Outline dummy = gloader->base.outline; 00361 00362 00363 dummy.points += num_base_points; 00364 dummy.n_points = (short)num_new_points; 00365 00366 FT_Outline_Translate( &dummy, x, y ); 00367 } 00368 } 00369 } 00370 break; 00371 00372 default: 00373 /* we don't support other formats (yet?) */ 00374 error = AF_Err_Unimplemented_Feature; 00375 } 00376 00377 Hint_Metrics: 00378 if ( depth == 0 ) 00379 { 00380 FT_BBox bbox; 00381 FT_Vector vvector; 00382 00383 00384 vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX; 00385 vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY; 00386 vvector.x = FT_MulFix( vvector.x, metrics->scaler.x_scale ); 00387 vvector.y = FT_MulFix( vvector.y, metrics->scaler.y_scale ); 00388 00389 /* transform the hinted outline if needed */ 00390 if ( loader->transformed ) 00391 { 00392 FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix ); 00393 FT_Vector_Transform( &vvector, &loader->trans_matrix ); 00394 } 00395 #if 1 00396 /* we must translate our final outline by -pp1.x and compute */ 00397 /* the new metrics */ 00398 if ( loader->pp1.x ) 00399 FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 ); 00400 #endif 00401 FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); 00402 00403 bbox.xMin = FT_PIX_FLOOR( bbox.xMin ); 00404 bbox.yMin = FT_PIX_FLOOR( bbox.yMin ); 00405 bbox.xMax = FT_PIX_CEIL( bbox.xMax ); 00406 bbox.yMax = FT_PIX_CEIL( bbox.yMax ); 00407 00408 slot->metrics.width = bbox.xMax - bbox.xMin; 00409 slot->metrics.height = bbox.yMax - bbox.yMin; 00410 slot->metrics.horiBearingX = bbox.xMin; 00411 slot->metrics.horiBearingY = bbox.yMax; 00412 00413 slot->metrics.vertBearingX = FT_PIX_FLOOR( bbox.xMin + vvector.x ); 00414 slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y ); 00415 00416 /* for mono-width fonts (like Andale, Courier, etc.) we need */ 00417 /* to keep the original rounded advance width; ditto for */ 00418 /* digits if all have the same advance width */ 00419 #if 0 00420 if ( !FT_IS_FIXED_WIDTH( slot->face ) ) 00421 slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; 00422 else 00423 slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, 00424 x_scale ); 00425 #else 00426 if ( FT_IS_FIXED_WIDTH( slot->face ) || 00427 ( af_face_globals_is_digit( loader->globals, glyph_index ) && 00428 metrics->digits_have_same_width ) ) 00429 { 00430 slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, 00431 metrics->scaler.x_scale ); 00432 00433 /* Set delta values to 0. Otherwise code that uses them is */ 00434 /* going to ruin the fixed advance width. */ 00435 slot->lsb_delta = 0; 00436 slot->rsb_delta = 0; 00437 } 00438 else 00439 { 00440 /* non-spacing glyphs must stay as-is */ 00441 if ( slot->metrics.horiAdvance ) 00442 slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; 00443 } 00444 #endif 00445 00446 slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance, 00447 metrics->scaler.y_scale ); 00448 00449 slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance ); 00450 slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance ); 00451 00452 /* now copy outline into glyph slot */ 00453 FT_GlyphLoader_Rewind( internal->loader ); 00454 error = FT_GlyphLoader_CopyPoints( internal->loader, gloader ); 00455 if ( error ) 00456 goto Exit; 00457 00458 slot->outline = internal->loader->base.outline; 00459 slot->format = FT_GLYPH_FORMAT_OUTLINE; 00460 } 00461 00462 #ifdef DEBUG_HINTER 00463 af_debug_hinter = hinter; 00464 #endif 00465 00466 Exit: 00467 return error; 00468 } 00469 00470 00471 FT_LOCAL_DEF( FT_Error ) 00472 af_loader_load_glyph( AF_Loader loader, 00473 FT_Face face, 00474 FT_UInt gindex, 00475 FT_UInt32 load_flags ) 00476 { 00477 FT_Error error; 00478 FT_Size size = face->size; 00479 AF_ScalerRec scaler; 00480 00481 00482 if ( !size ) 00483 return AF_Err_Invalid_Argument; 00484 00485 FT_ZERO( &scaler ); 00486 00487 scaler.face = face; 00488 scaler.x_scale = size->metrics.x_scale; 00489 scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */ 00490 scaler.y_scale = size->metrics.y_scale; 00491 scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */ 00492 00493 scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags ); 00494 scaler.flags = 0; /* XXX: fix this */ 00495 00496 error = af_loader_reset( loader, face ); 00497 if ( !error ) 00498 { 00499 AF_ScriptMetrics metrics; 00500 FT_UInt options = 0; 00501 00502 00503 #ifdef FT_OPTION_AUTOFIT2 00504 /* XXX: undocumented hook to activate the latin2 hinter */ 00505 if ( load_flags & ( 1UL << 20 ) ) 00506 options = 2; 00507 #endif 00508 00509 error = af_face_globals_get_metrics( loader->globals, gindex, 00510 options, &metrics ); 00511 if ( !error ) 00512 { 00513 loader->metrics = metrics; 00514 00515 if ( metrics->clazz->script_metrics_scale ) 00516 metrics->clazz->script_metrics_scale( metrics, &scaler ); 00517 else 00518 metrics->scaler = scaler; 00519 00520 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM; 00521 load_flags &= ~FT_LOAD_RENDER; 00522 00523 if ( metrics->clazz->script_hints_init ) 00524 { 00525 error = metrics->clazz->script_hints_init( &loader->hints, 00526 metrics ); 00527 if ( error ) 00528 goto Exit; 00529 } 00530 00531 error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 ); 00532 } 00533 } 00534 Exit: 00535 return error; 00536 } 00537 00538 00539 /* END */ Generated on Sat May 26 2012 04:32:29 for ReactOS by
1.7.6.1
|