ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pfrobjs.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.