Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpfrobjs.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* pfrobjs.c */ 00004 /* */ 00005 /* FreeType PFR object methods (body). */ 00006 /* */ 00007 /* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 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 "pfrobjs.h" 00020 #include "pfrload.h" 00021 #include "pfrgload.h" 00022 #include "pfrcmap.h" 00023 #include "pfrsbit.h" 00024 #include FT_OUTLINE_H 00025 #include FT_INTERNAL_DEBUG_H 00026 #include FT_TRUETYPE_IDS_H 00027 00028 #include "pfrerror.h" 00029 00030 #undef FT_COMPONENT 00031 #define FT_COMPONENT trace_pfr 00032 00033 00034 /*************************************************************************/ 00035 /*************************************************************************/ 00036 /***** *****/ 00037 /***** FACE OBJECT METHODS *****/ 00038 /***** *****/ 00039 /*************************************************************************/ 00040 /*************************************************************************/ 00041 00042 FT_LOCAL_DEF( void ) 00043 pfr_face_done( FT_Face pfrface ) /* PFR_Face */ 00044 { 00045 PFR_Face face = (PFR_Face)pfrface; 00046 FT_Memory memory; 00047 00048 00049 if ( !face ) 00050 return; 00051 00052 memory = pfrface->driver->root.memory; 00053 00054 /* we don't want dangling pointers */ 00055 pfrface->family_name = NULL; 00056 pfrface->style_name = NULL; 00057 00058 /* finalize the physical font record */ 00059 pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) ); 00060 00061 /* no need to finalize the logical font or the header */ 00062 FT_FREE( pfrface->available_sizes ); 00063 } 00064 00065 00066 FT_LOCAL_DEF( FT_Error ) 00067 pfr_face_init( FT_Stream stream, 00068 FT_Face pfrface, 00069 FT_Int face_index, 00070 FT_Int num_params, 00071 FT_Parameter* params ) 00072 { 00073 PFR_Face face = (PFR_Face)pfrface; 00074 FT_Error error; 00075 00076 FT_UNUSED( num_params ); 00077 FT_UNUSED( params ); 00078 00079 00080 /* load the header and check it */ 00081 error = pfr_header_load( &face->header, stream ); 00082 if ( error ) 00083 goto Exit; 00084 00085 if ( !pfr_header_check( &face->header ) ) 00086 { 00087 FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" )); 00088 error = PFR_Err_Unknown_File_Format; 00089 goto Exit; 00090 } 00091 00092 /* check face index */ 00093 { 00094 FT_UInt num_faces; 00095 00096 00097 error = pfr_log_font_count( stream, 00098 face->header.log_dir_offset, 00099 &num_faces ); 00100 if ( error ) 00101 goto Exit; 00102 00103 pfrface->num_faces = num_faces; 00104 } 00105 00106 if ( face_index < 0 ) 00107 goto Exit; 00108 00109 if ( face_index >= pfrface->num_faces ) 00110 { 00111 FT_ERROR(( "pfr_face_init: invalid face index\n" )); 00112 error = PFR_Err_Invalid_Argument; 00113 goto Exit; 00114 } 00115 00116 /* load the face */ 00117 error = pfr_log_font_load( 00118 &face->log_font, stream, face_index, 00119 face->header.log_dir_offset, 00120 FT_BOOL( face->header.phy_font_max_size_high != 0 ) ); 00121 if ( error ) 00122 goto Exit; 00123 00124 /* now load the physical font descriptor */ 00125 error = pfr_phy_font_load( &face->phy_font, stream, 00126 face->log_font.phys_offset, 00127 face->log_font.phys_size ); 00128 if ( error ) 00129 goto Exit; 00130 00131 /* now set up all root face fields */ 00132 { 00133 PFR_PhyFont phy_font = &face->phy_font; 00134 00135 00136 pfrface->face_index = face_index; 00137 pfrface->num_glyphs = phy_font->num_chars + 1; 00138 pfrface->face_flags = FT_FACE_FLAG_SCALABLE; 00139 00140 /* if all characters point to the same gps_offset 0, we */ 00141 /* assume that the font only contains bitmaps */ 00142 { 00143 FT_UInt nn; 00144 00145 00146 for ( nn = 0; nn < phy_font->num_chars; nn++ ) 00147 if ( phy_font->chars[nn].gps_offset != 0 ) 00148 break; 00149 00150 if ( nn == phy_font->num_chars ) 00151 { 00152 if ( phy_font->num_strikes > 0 ) 00153 pfrface->face_flags = 0; /* not scalable */ 00154 else 00155 { 00156 FT_ERROR(( "pfr_face_init: font doesn't contain glyphs\n" )); 00157 error = PFR_Err_Invalid_File_Format; 00158 goto Exit; 00159 } 00160 } 00161 } 00162 00163 if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 ) 00164 pfrface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 00165 00166 if ( phy_font->flags & PFR_PHY_VERTICAL ) 00167 pfrface->face_flags |= FT_FACE_FLAG_VERTICAL; 00168 else 00169 pfrface->face_flags |= FT_FACE_FLAG_HORIZONTAL; 00170 00171 if ( phy_font->num_strikes > 0 ) 00172 pfrface->face_flags |= FT_FACE_FLAG_FIXED_SIZES; 00173 00174 if ( phy_font->num_kern_pairs > 0 ) 00175 pfrface->face_flags |= FT_FACE_FLAG_KERNING; 00176 00177 /* If no family name was found in the "undocumented" auxiliary 00178 * data, use the font ID instead. This sucks but is better than 00179 * nothing. 00180 */ 00181 pfrface->family_name = phy_font->family_name; 00182 if ( pfrface->family_name == NULL ) 00183 pfrface->family_name = phy_font->font_id; 00184 00185 /* note that the style name can be NULL in certain PFR fonts, 00186 * probably meaning "Regular" 00187 */ 00188 pfrface->style_name = phy_font->style_name; 00189 00190 pfrface->num_fixed_sizes = 0; 00191 pfrface->available_sizes = 0; 00192 00193 pfrface->bbox = phy_font->bbox; 00194 pfrface->units_per_EM = (FT_UShort)phy_font->outline_resolution; 00195 pfrface->ascender = (FT_Short) phy_font->bbox.yMax; 00196 pfrface->descender = (FT_Short) phy_font->bbox.yMin; 00197 00198 pfrface->height = (FT_Short)( ( pfrface->units_per_EM * 12 ) / 10 ); 00199 if ( pfrface->height < pfrface->ascender - pfrface->descender ) 00200 pfrface->height = (FT_Short)(pfrface->ascender - pfrface->descender); 00201 00202 if ( phy_font->num_strikes > 0 ) 00203 { 00204 FT_UInt n, count = phy_font->num_strikes; 00205 FT_Bitmap_Size* size; 00206 PFR_Strike strike; 00207 FT_Memory memory = pfrface->stream->memory; 00208 00209 00210 if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) ) 00211 goto Exit; 00212 00213 size = pfrface->available_sizes; 00214 strike = phy_font->strikes; 00215 for ( n = 0; n < count; n++, size++, strike++ ) 00216 { 00217 size->height = (FT_UShort)strike->y_ppm; 00218 size->width = (FT_UShort)strike->x_ppm; 00219 size->size = strike->y_ppm << 6; 00220 size->x_ppem = strike->x_ppm << 6; 00221 size->y_ppem = strike->y_ppm << 6; 00222 } 00223 pfrface->num_fixed_sizes = count; 00224 } 00225 00226 /* now compute maximum advance width */ 00227 if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 ) 00228 pfrface->max_advance_width = (FT_Short)phy_font->standard_advance; 00229 else 00230 { 00231 FT_Int max = 0; 00232 FT_UInt count = phy_font->num_chars; 00233 PFR_Char gchar = phy_font->chars; 00234 00235 00236 for ( ; count > 0; count--, gchar++ ) 00237 { 00238 if ( max < gchar->advance ) 00239 max = gchar->advance; 00240 } 00241 00242 pfrface->max_advance_width = (FT_Short)max; 00243 } 00244 00245 pfrface->max_advance_height = pfrface->height; 00246 00247 pfrface->underline_position = (FT_Short)( -pfrface->units_per_EM / 10 ); 00248 pfrface->underline_thickness = (FT_Short)( pfrface->units_per_EM / 30 ); 00249 00250 /* create charmap */ 00251 { 00252 FT_CharMapRec charmap; 00253 00254 00255 charmap.face = pfrface; 00256 charmap.platform_id = TT_PLATFORM_MICROSOFT; 00257 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 00258 charmap.encoding = FT_ENCODING_UNICODE; 00259 00260 error = FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL ); 00261 00262 #if 0 00263 /* Select default charmap */ 00264 if ( pfrface->num_charmaps ) 00265 pfrface->charmap = pfrface->charmaps[0]; 00266 #endif 00267 } 00268 00269 /* check whether we've loaded any kerning pairs */ 00270 if ( phy_font->num_kern_pairs ) 00271 pfrface->face_flags |= FT_FACE_FLAG_KERNING; 00272 } 00273 00274 Exit: 00275 return error; 00276 } 00277 00278 00279 /*************************************************************************/ 00280 /*************************************************************************/ 00281 /***** *****/ 00282 /***** SLOT OBJECT METHOD *****/ 00283 /***** *****/ 00284 /*************************************************************************/ 00285 /*************************************************************************/ 00286 00287 FT_LOCAL_DEF( FT_Error ) 00288 pfr_slot_init( FT_GlyphSlot pfrslot ) /* PFR_Slot */ 00289 { 00290 PFR_Slot slot = (PFR_Slot)pfrslot; 00291 FT_GlyphLoader loader = pfrslot->internal->loader; 00292 00293 00294 pfr_glyph_init( &slot->glyph, loader ); 00295 00296 return 0; 00297 } 00298 00299 00300 FT_LOCAL_DEF( void ) 00301 pfr_slot_done( FT_GlyphSlot pfrslot ) /* PFR_Slot */ 00302 { 00303 PFR_Slot slot = (PFR_Slot)pfrslot; 00304 00305 00306 pfr_glyph_done( &slot->glyph ); 00307 } 00308 00309 00310 FT_LOCAL_DEF( FT_Error ) 00311 pfr_slot_load( FT_GlyphSlot pfrslot, /* PFR_Slot */ 00312 FT_Size pfrsize, /* PFR_Size */ 00313 FT_UInt gindex, 00314 FT_Int32 load_flags ) 00315 { 00316 PFR_Slot slot = (PFR_Slot)pfrslot; 00317 PFR_Size size = (PFR_Size)pfrsize; 00318 FT_Error error; 00319 PFR_Face face = (PFR_Face)pfrslot->face; 00320 PFR_Char gchar; 00321 FT_Outline* outline = &pfrslot->outline; 00322 FT_ULong gps_offset; 00323 00324 00325 if ( gindex > 0 ) 00326 gindex--; 00327 00328 if ( !face || gindex >= face->phy_font.num_chars ) 00329 { 00330 error = PFR_Err_Invalid_Argument; 00331 goto Exit; 00332 } 00333 00334 /* try to load an embedded bitmap */ 00335 if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 ) 00336 { 00337 error = pfr_slot_load_bitmap( slot, size, gindex ); 00338 if ( error == 0 ) 00339 goto Exit; 00340 } 00341 00342 if ( load_flags & FT_LOAD_SBITS_ONLY ) 00343 { 00344 error = PFR_Err_Invalid_Argument; 00345 goto Exit; 00346 } 00347 00348 gchar = face->phy_font.chars + gindex; 00349 pfrslot->format = FT_GLYPH_FORMAT_OUTLINE; 00350 outline->n_points = 0; 00351 outline->n_contours = 0; 00352 gps_offset = face->header.gps_section_offset; 00353 00354 /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */ 00355 error = pfr_glyph_load( &slot->glyph, face->root.stream, 00356 gps_offset, gchar->gps_offset, gchar->gps_size ); 00357 00358 if ( !error ) 00359 { 00360 FT_BBox cbox; 00361 FT_Glyph_Metrics* metrics = &pfrslot->metrics; 00362 FT_Pos advance; 00363 FT_Int em_metrics, em_outline; 00364 FT_Bool scaling; 00365 00366 00367 scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); 00368 00369 /* copy outline data */ 00370 *outline = slot->glyph.loader->base.outline; 00371 00372 outline->flags &= ~FT_OUTLINE_OWNER; 00373 outline->flags |= FT_OUTLINE_REVERSE_FILL; 00374 00375 if ( size && pfrsize->metrics.y_ppem < 24 ) 00376 outline->flags |= FT_OUTLINE_HIGH_PRECISION; 00377 00378 /* compute the advance vector */ 00379 metrics->horiAdvance = 0; 00380 metrics->vertAdvance = 0; 00381 00382 advance = gchar->advance; 00383 em_metrics = face->phy_font.metrics_resolution; 00384 em_outline = face->phy_font.outline_resolution; 00385 00386 if ( em_metrics != em_outline ) 00387 advance = FT_MulDiv( advance, em_outline, em_metrics ); 00388 00389 if ( face->phy_font.flags & PFR_PHY_VERTICAL ) 00390 metrics->vertAdvance = advance; 00391 else 00392 metrics->horiAdvance = advance; 00393 00394 pfrslot->linearHoriAdvance = metrics->horiAdvance; 00395 pfrslot->linearVertAdvance = metrics->vertAdvance; 00396 00397 /* make-up vertical metrics(?) */ 00398 metrics->vertBearingX = 0; 00399 metrics->vertBearingY = 0; 00400 00401 #if 0 /* some fonts seem to be broken here! */ 00402 00403 /* Apply the font matrix, if any. */ 00404 /* TODO: Test existing fonts with unusual matrix */ 00405 /* whether we have to adjust Units per EM. */ 00406 { 00407 FT_Matrix font_matrix; 00408 00409 00410 font_matrix.xx = face->log_font.matrix[0] << 8; 00411 font_matrix.yx = face->log_font.matrix[1] << 8; 00412 font_matrix.xy = face->log_font.matrix[2] << 8; 00413 font_matrix.yy = face->log_font.matrix[3] << 8; 00414 00415 FT_Outline_Transform( outline, &font_matrix ); 00416 } 00417 #endif 00418 00419 /* scale when needed */ 00420 if ( scaling ) 00421 { 00422 FT_Int n; 00423 FT_Fixed x_scale = pfrsize->metrics.x_scale; 00424 FT_Fixed y_scale = pfrsize->metrics.y_scale; 00425 FT_Vector* vec = outline->points; 00426 00427 00428 /* scale outline points */ 00429 for ( n = 0; n < outline->n_points; n++, vec++ ) 00430 { 00431 vec->x = FT_MulFix( vec->x, x_scale ); 00432 vec->y = FT_MulFix( vec->y, y_scale ); 00433 } 00434 00435 /* scale the advance */ 00436 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 00437 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 00438 } 00439 00440 /* compute the rest of the metrics */ 00441 FT_Outline_Get_CBox( outline, &cbox ); 00442 00443 metrics->width = cbox.xMax - cbox.xMin; 00444 metrics->height = cbox.yMax - cbox.yMin; 00445 metrics->horiBearingX = cbox.xMin; 00446 metrics->horiBearingY = cbox.yMax - metrics->height; 00447 } 00448 00449 Exit: 00450 return error; 00451 } 00452 00453 00454 /*************************************************************************/ 00455 /*************************************************************************/ 00456 /***** *****/ 00457 /***** KERNING METHOD *****/ 00458 /***** *****/ 00459 /*************************************************************************/ 00460 /*************************************************************************/ 00461 00462 FT_LOCAL_DEF( FT_Error ) 00463 pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */ 00464 FT_UInt glyph1, 00465 FT_UInt glyph2, 00466 FT_Vector* kerning ) 00467 { 00468 PFR_Face face = (PFR_Face)pfrface; 00469 FT_Error error = PFR_Err_Ok; 00470 PFR_PhyFont phy_font = &face->phy_font; 00471 FT_UInt32 code1, code2, pair; 00472 00473 00474 kerning->x = 0; 00475 kerning->y = 0; 00476 00477 if ( glyph1 > 0 ) 00478 glyph1--; 00479 00480 if ( glyph2 > 0 ) 00481 glyph2--; 00482 00483 /* convert glyph indices to character codes */ 00484 if ( glyph1 > phy_font->num_chars || 00485 glyph2 > phy_font->num_chars ) 00486 goto Exit; 00487 00488 code1 = phy_font->chars[glyph1].char_code; 00489 code2 = phy_font->chars[glyph2].char_code; 00490 pair = PFR_KERN_INDEX( code1, code2 ); 00491 00492 /* now search the list of kerning items */ 00493 { 00494 PFR_KernItem item = phy_font->kern_items; 00495 FT_Stream stream = pfrface->stream; 00496 00497 00498 for ( ; item; item = item->next ) 00499 { 00500 if ( pair >= item->pair1 && pair <= item->pair2 ) 00501 goto FoundPair; 00502 } 00503 goto Exit; 00504 00505 FoundPair: /* we found an item, now parse it and find the value if any */ 00506 if ( FT_STREAM_SEEK( item->offset ) || 00507 FT_FRAME_ENTER( item->pair_count * item->pair_size ) ) 00508 goto Exit; 00509 00510 { 00511 FT_UInt count = item->pair_count; 00512 FT_UInt size = item->pair_size; 00513 FT_UInt power = (FT_UInt)ft_highpow2( (FT_UInt32)count ); 00514 FT_UInt probe = power * size; 00515 FT_UInt extra = count - power; 00516 FT_Byte* base = stream->cursor; 00517 FT_Bool twobytes = FT_BOOL( item->flags & 1 ); 00518 FT_Bool twobyte_adj = FT_BOOL( item->flags & 2 ); 00519 FT_Byte* p; 00520 FT_UInt32 cpair; 00521 00522 00523 if ( extra > 0 ) 00524 { 00525 p = base + extra * size; 00526 00527 if ( twobytes ) 00528 cpair = FT_NEXT_ULONG( p ); 00529 else 00530 cpair = PFR_NEXT_KPAIR( p ); 00531 00532 if ( cpair == pair ) 00533 goto Found; 00534 00535 if ( cpair < pair ) 00536 { 00537 if ( twobyte_adj ) 00538 p += 2; 00539 else 00540 p++; 00541 base = p; 00542 } 00543 } 00544 00545 while ( probe > size ) 00546 { 00547 probe >>= 1; 00548 p = base + probe; 00549 00550 if ( twobytes ) 00551 cpair = FT_NEXT_ULONG( p ); 00552 else 00553 cpair = PFR_NEXT_KPAIR( p ); 00554 00555 if ( cpair == pair ) 00556 goto Found; 00557 00558 if ( cpair < pair ) 00559 base += probe; 00560 } 00561 00562 p = base; 00563 00564 if ( twobytes ) 00565 cpair = FT_NEXT_ULONG( p ); 00566 else 00567 cpair = PFR_NEXT_KPAIR( p ); 00568 00569 if ( cpair == pair ) 00570 { 00571 FT_Int value; 00572 00573 00574 Found: 00575 if ( twobyte_adj ) 00576 value = FT_PEEK_SHORT( p ); 00577 else 00578 value = p[0]; 00579 00580 kerning->x = item->base_adj + value; 00581 } 00582 } 00583 00584 FT_FRAME_EXIT(); 00585 } 00586 00587 Exit: 00588 return error; 00589 } 00590 00591 /* END */ Generated on Sun May 27 2012 04:33:58 for ReactOS by
1.7.6.1
|