misc/libfreetype/src/pfr/pfrobjs.c
branchwebgl
changeset 9521 8054d9d775fd
parent 9282 92af50454cf2
parent 9519 b8b5c82eb61b
child 9950 2759212a27de
equal deleted inserted replaced
9282:92af50454cf2 9521:8054d9d775fd
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  pfrobjs.c                                                              */
       
     4 /*                                                                         */
       
     5 /*    FreeType PFR object methods (body).                                  */
       
     6 /*                                                                         */
       
     7 /*  Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by            */
       
     8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
       
     9 /*                                                                         */
       
    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      */
       
    12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
       
    13 /*  this file you indicate that you have read the license and              */
       
    14 /*  understand and accept it fully.                                        */
       
    15 /*                                                                         */
       
    16 /***************************************************************************/
       
    17 
       
    18 
       
    19 #include "pfrobjs.h"
       
    20 #include "pfrload.h"
       
    21 #include "pfrgload.h"
       
    22 #include "pfrcmap.h"
       
    23 #include "pfrsbit.h"
       
    24 #include FT_OUTLINE_H
       
    25 #include FT_INTERNAL_DEBUG_H
       
    26 #include FT_TRUETYPE_IDS_H 
       
    27 
       
    28 #include "pfrerror.h"
       
    29 
       
    30 #undef  FT_COMPONENT
       
    31 #define FT_COMPONENT  trace_pfr
       
    32 
       
    33 
       
    34   /*************************************************************************/
       
    35   /*************************************************************************/
       
    36   /*****                                                               *****/
       
    37   /*****                     FACE OBJECT METHODS                       *****/
       
    38   /*****                                                               *****/
       
    39   /*************************************************************************/
       
    40   /*************************************************************************/
       
    41 
       
    42   FT_LOCAL_DEF( void )
       
    43   pfr_face_done( FT_Face  pfrface )     /* PFR_Face */
       
    44   {
       
    45     PFR_Face   face = (PFR_Face)pfrface;
       
    46     FT_Memory  memory;
       
    47 
       
    48 
       
    49     if ( !face )
       
    50       return;
       
    51 
       
    52     memory = pfrface->driver->root.memory;
       
    53 
       
    54     /* we don't want dangling pointers */
       
    55     pfrface->family_name = NULL;
       
    56     pfrface->style_name  = NULL;
       
    57 
       
    58     /* finalize the physical font record */
       
    59     pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) );
       
    60 
       
    61     /* no need to finalize the logical font or the header */
       
    62     FT_FREE( pfrface->available_sizes );
       
    63   }
       
    64 
       
    65 
       
    66   FT_LOCAL_DEF( FT_Error )
       
    67   pfr_face_init( FT_Stream      stream,
       
    68                  FT_Face        pfrface,
       
    69                  FT_Int         face_index,
       
    70                  FT_Int         num_params,
       
    71                  FT_Parameter*  params )
       
    72   {
       
    73     PFR_Face  face = (PFR_Face)pfrface;
       
    74     FT_Error  error;
       
    75 
       
    76     FT_UNUSED( num_params );
       
    77     FT_UNUSED( params );
       
    78 
       
    79 
       
    80     /* load the header and check it */
       
    81     error = pfr_header_load( &face->header, stream );
       
    82     if ( error )
       
    83       goto Exit;
       
    84 
       
    85     if ( !pfr_header_check( &face->header ) )
       
    86     {
       
    87       FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" ));
       
    88       error = PFR_Err_Unknown_File_Format;
       
    89       goto Exit;
       
    90     }
       
    91 
       
    92     /* check face index */
       
    93     {
       
    94       FT_UInt  num_faces;
       
    95 
       
    96 
       
    97       error = pfr_log_font_count( stream,
       
    98                                   face->header.log_dir_offset,
       
    99                                   &num_faces );
       
   100       if ( error )
       
   101         goto Exit;
       
   102 
       
   103       pfrface->num_faces = num_faces;
       
   104     }
       
   105 
       
   106     if ( face_index < 0 )
       
   107       goto Exit;
       
   108 
       
   109     if ( face_index >= pfrface->num_faces )
       
   110     {
       
   111       FT_ERROR(( "pfr_face_init: invalid face index\n" ));
       
   112       error = PFR_Err_Invalid_Argument;
       
   113       goto Exit;
       
   114     }
       
   115 
       
   116     /* load the face */
       
   117     error = pfr_log_font_load(
       
   118                &face->log_font, stream, face_index,
       
   119                face->header.log_dir_offset,
       
   120                FT_BOOL( face->header.phy_font_max_size_high != 0 ) );
       
   121     if ( error )
       
   122       goto Exit;
       
   123 
       
   124     /* now load the physical font descriptor */
       
   125     error = pfr_phy_font_load( &face->phy_font, stream,
       
   126                                face->log_font.phys_offset,
       
   127                                face->log_font.phys_size );
       
   128     if ( error )
       
   129       goto Exit;
       
   130 
       
   131     /* now set up all root face fields */
       
   132     {
       
   133       PFR_PhyFont  phy_font = &face->phy_font;
       
   134 
       
   135 
       
   136       pfrface->face_index = face_index;
       
   137       pfrface->num_glyphs = phy_font->num_chars + 1;
       
   138       pfrface->face_flags = FT_FACE_FLAG_SCALABLE;
       
   139 
       
   140       /* if all characters point to the same gps_offset 0, we */
       
   141       /* assume that the font only contains bitmaps           */
       
   142       {
       
   143         FT_UInt  nn;
       
   144 
       
   145 
       
   146         for ( nn = 0; nn < phy_font->num_chars; nn++ )
       
   147           if ( phy_font->chars[nn].gps_offset != 0 )
       
   148             break;
       
   149 
       
   150         if ( nn == phy_font->num_chars )
       
   151         {
       
   152           if ( phy_font->num_strikes > 0 )
       
   153             pfrface->face_flags = 0;        /* not scalable */
       
   154           else
       
   155           {
       
   156             FT_ERROR(( "pfr_face_init: font doesn't contain glyphs\n" ));
       
   157             error = PFR_Err_Invalid_File_Format;
       
   158             goto Exit;
       
   159           }
       
   160         }
       
   161       }
       
   162 
       
   163       if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 )
       
   164         pfrface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
       
   165 
       
   166       if ( phy_font->flags & PFR_PHY_VERTICAL )
       
   167         pfrface->face_flags |= FT_FACE_FLAG_VERTICAL;
       
   168       else
       
   169         pfrface->face_flags |= FT_FACE_FLAG_HORIZONTAL;
       
   170 
       
   171       if ( phy_font->num_strikes > 0 )
       
   172         pfrface->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
       
   173 
       
   174       if ( phy_font->num_kern_pairs > 0 )
       
   175         pfrface->face_flags |= FT_FACE_FLAG_KERNING;
       
   176 
       
   177       /* If no family name was found in the "undocumented" auxiliary
       
   178        * data, use the font ID instead.  This sucks but is better than
       
   179        * nothing.
       
   180        */
       
   181       pfrface->family_name = phy_font->family_name;
       
   182       if ( pfrface->family_name == NULL )
       
   183         pfrface->family_name = phy_font->font_id;
       
   184 
       
   185       /* note that the style name can be NULL in certain PFR fonts,
       
   186        * probably meaning "Regular"
       
   187        */
       
   188       pfrface->style_name = phy_font->style_name;
       
   189 
       
   190       pfrface->num_fixed_sizes = 0;
       
   191       pfrface->available_sizes = 0;
       
   192 
       
   193       pfrface->bbox         = phy_font->bbox;
       
   194       pfrface->units_per_EM = (FT_UShort)phy_font->outline_resolution;
       
   195       pfrface->ascender     = (FT_Short) phy_font->bbox.yMax;
       
   196       pfrface->descender    = (FT_Short) phy_font->bbox.yMin;
       
   197 
       
   198       pfrface->height = (FT_Short)( ( pfrface->units_per_EM * 12 ) / 10 );
       
   199       if ( pfrface->height < pfrface->ascender - pfrface->descender )
       
   200         pfrface->height = (FT_Short)(pfrface->ascender - pfrface->descender);
       
   201 
       
   202       if ( phy_font->num_strikes > 0 )
       
   203       {
       
   204         FT_UInt          n, count = phy_font->num_strikes;
       
   205         FT_Bitmap_Size*  size;
       
   206         PFR_Strike       strike;
       
   207         FT_Memory        memory = pfrface->stream->memory;
       
   208 
       
   209 
       
   210         if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) )
       
   211           goto Exit;
       
   212 
       
   213         size   = pfrface->available_sizes;
       
   214         strike = phy_font->strikes;
       
   215         for ( n = 0; n < count; n++, size++, strike++ )
       
   216         {
       
   217           size->height = (FT_UShort)strike->y_ppm;
       
   218           size->width  = (FT_UShort)strike->x_ppm;
       
   219           size->size   = strike->y_ppm << 6;
       
   220           size->x_ppem = strike->x_ppm << 6;
       
   221           size->y_ppem = strike->y_ppm << 6;
       
   222         }
       
   223         pfrface->num_fixed_sizes = count;
       
   224       }
       
   225 
       
   226       /* now compute maximum advance width */
       
   227       if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 )
       
   228         pfrface->max_advance_width = (FT_Short)phy_font->standard_advance;
       
   229       else
       
   230       {
       
   231         FT_Int    max = 0;
       
   232         FT_UInt   count = phy_font->num_chars;
       
   233         PFR_Char  gchar = phy_font->chars;
       
   234 
       
   235 
       
   236         for ( ; count > 0; count--, gchar++ )
       
   237         {
       
   238           if ( max < gchar->advance )
       
   239             max = gchar->advance;
       
   240         }
       
   241 
       
   242         pfrface->max_advance_width = (FT_Short)max;
       
   243       }
       
   244 
       
   245       pfrface->max_advance_height = pfrface->height;
       
   246 
       
   247       pfrface->underline_position  = (FT_Short)( -pfrface->units_per_EM / 10 );
       
   248       pfrface->underline_thickness = (FT_Short)(  pfrface->units_per_EM / 30 );
       
   249 
       
   250       /* create charmap */
       
   251       {
       
   252         FT_CharMapRec  charmap;
       
   253 
       
   254 
       
   255         charmap.face        = pfrface;
       
   256         charmap.platform_id = TT_PLATFORM_MICROSOFT;
       
   257         charmap.encoding_id = TT_MS_ID_UNICODE_CS;
       
   258         charmap.encoding    = FT_ENCODING_UNICODE;
       
   259 
       
   260         error = FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL );
       
   261 
       
   262 #if 0
       
   263         /* Select default charmap */
       
   264         if ( pfrface->num_charmaps )
       
   265           pfrface->charmap = pfrface->charmaps[0];
       
   266 #endif
       
   267       }
       
   268 
       
   269       /* check whether we've loaded any kerning pairs */
       
   270       if ( phy_font->num_kern_pairs )
       
   271         pfrface->face_flags |= FT_FACE_FLAG_KERNING;
       
   272     }
       
   273 
       
   274   Exit:
       
   275     return error;
       
   276   }
       
   277 
       
   278 
       
   279   /*************************************************************************/
       
   280   /*************************************************************************/
       
   281   /*****                                                               *****/
       
   282   /*****                    SLOT OBJECT METHOD                         *****/
       
   283   /*****                                                               *****/
       
   284   /*************************************************************************/
       
   285   /*************************************************************************/
       
   286 
       
   287   FT_LOCAL_DEF( FT_Error )
       
   288   pfr_slot_init( FT_GlyphSlot  pfrslot )        /* PFR_Slot */
       
   289   {
       
   290     PFR_Slot        slot   = (PFR_Slot)pfrslot;
       
   291     FT_GlyphLoader  loader = pfrslot->internal->loader;
       
   292 
       
   293 
       
   294     pfr_glyph_init( &slot->glyph, loader );
       
   295 
       
   296     return 0;
       
   297   }
       
   298 
       
   299 
       
   300   FT_LOCAL_DEF( void )
       
   301   pfr_slot_done( FT_GlyphSlot  pfrslot )        /* PFR_Slot */
       
   302   {
       
   303     PFR_Slot  slot = (PFR_Slot)pfrslot;
       
   304 
       
   305 
       
   306     pfr_glyph_done( &slot->glyph );
       
   307   }
       
   308 
       
   309 
       
   310   FT_LOCAL_DEF( FT_Error )
       
   311   pfr_slot_load( FT_GlyphSlot  pfrslot,         /* PFR_Slot */
       
   312                  FT_Size       pfrsize,         /* PFR_Size */
       
   313                  FT_UInt       gindex,
       
   314                  FT_Int32      load_flags )
       
   315   {
       
   316     PFR_Slot     slot    = (PFR_Slot)pfrslot;
       
   317     PFR_Size     size    = (PFR_Size)pfrsize;
       
   318     FT_Error     error;
       
   319     PFR_Face     face    = (PFR_Face)pfrslot->face;
       
   320     PFR_Char     gchar;
       
   321     FT_Outline*  outline = &pfrslot->outline;
       
   322     FT_ULong     gps_offset;
       
   323 
       
   324 
       
   325     if ( gindex > 0 )
       
   326       gindex--;
       
   327 
       
   328     if ( !face || gindex >= face->phy_font.num_chars )
       
   329     {
       
   330       error = PFR_Err_Invalid_Argument;
       
   331       goto Exit;
       
   332     }
       
   333 
       
   334     /* try to load an embedded bitmap */
       
   335     if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 )
       
   336     {
       
   337       error = pfr_slot_load_bitmap( slot, size, gindex );
       
   338       if ( error == 0 )
       
   339         goto Exit;
       
   340     }
       
   341 
       
   342     if ( load_flags & FT_LOAD_SBITS_ONLY )
       
   343     {
       
   344       error = PFR_Err_Invalid_Argument;
       
   345       goto Exit;
       
   346     }
       
   347 
       
   348     gchar               = face->phy_font.chars + gindex;
       
   349     pfrslot->format     = FT_GLYPH_FORMAT_OUTLINE;
       
   350     outline->n_points   = 0;
       
   351     outline->n_contours = 0;
       
   352     gps_offset          = face->header.gps_section_offset;
       
   353 
       
   354     /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */
       
   355     error = pfr_glyph_load( &slot->glyph, face->root.stream,
       
   356                             gps_offset, gchar->gps_offset, gchar->gps_size );
       
   357 
       
   358     if ( !error )
       
   359     {
       
   360       FT_BBox            cbox;
       
   361       FT_Glyph_Metrics*  metrics = &pfrslot->metrics;
       
   362       FT_Pos             advance;
       
   363       FT_Int             em_metrics, em_outline;
       
   364       FT_Bool            scaling;
       
   365 
       
   366 
       
   367       scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
       
   368 
       
   369       /* copy outline data */
       
   370       *outline = slot->glyph.loader->base.outline;
       
   371 
       
   372       outline->flags &= ~FT_OUTLINE_OWNER;
       
   373       outline->flags |= FT_OUTLINE_REVERSE_FILL;
       
   374 
       
   375       if ( size && pfrsize->metrics.y_ppem < 24 )
       
   376         outline->flags |= FT_OUTLINE_HIGH_PRECISION;
       
   377 
       
   378       /* compute the advance vector */
       
   379       metrics->horiAdvance = 0;
       
   380       metrics->vertAdvance = 0;
       
   381 
       
   382       advance    = gchar->advance;
       
   383       em_metrics = face->phy_font.metrics_resolution;
       
   384       em_outline = face->phy_font.outline_resolution;
       
   385 
       
   386       if ( em_metrics != em_outline )
       
   387         advance = FT_MulDiv( advance, em_outline, em_metrics );
       
   388 
       
   389       if ( face->phy_font.flags & PFR_PHY_VERTICAL )
       
   390         metrics->vertAdvance = advance;
       
   391       else
       
   392         metrics->horiAdvance = advance;
       
   393 
       
   394       pfrslot->linearHoriAdvance = metrics->horiAdvance;
       
   395       pfrslot->linearVertAdvance = metrics->vertAdvance;
       
   396 
       
   397       /* make-up vertical metrics(?) */
       
   398       metrics->vertBearingX = 0;
       
   399       metrics->vertBearingY = 0;
       
   400 
       
   401 #if 0 /* some fonts seem to be broken here! */
       
   402 
       
   403       /* Apply the font matrix, if any.                 */
       
   404       /* TODO: Test existing fonts with unusual matrix  */
       
   405       /* whether we have to adjust Units per EM.        */
       
   406       {
       
   407         FT_Matrix font_matrix;
       
   408 
       
   409 
       
   410         font_matrix.xx = face->log_font.matrix[0] << 8;
       
   411         font_matrix.yx = face->log_font.matrix[1] << 8;
       
   412         font_matrix.xy = face->log_font.matrix[2] << 8;
       
   413         font_matrix.yy = face->log_font.matrix[3] << 8;
       
   414 
       
   415         FT_Outline_Transform( outline, &font_matrix );
       
   416       }
       
   417 #endif
       
   418 
       
   419       /* scale when needed */
       
   420       if ( scaling )
       
   421       {
       
   422         FT_Int      n;
       
   423         FT_Fixed    x_scale = pfrsize->metrics.x_scale;
       
   424         FT_Fixed    y_scale = pfrsize->metrics.y_scale;
       
   425         FT_Vector*  vec     = outline->points;
       
   426 
       
   427 
       
   428         /* scale outline points */
       
   429         for ( n = 0; n < outline->n_points; n++, vec++ )
       
   430         {
       
   431           vec->x = FT_MulFix( vec->x, x_scale );
       
   432           vec->y = FT_MulFix( vec->y, y_scale );
       
   433         }
       
   434 
       
   435         /* scale the advance */
       
   436         metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
       
   437         metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
       
   438       }
       
   439 
       
   440       /* compute the rest of the metrics */
       
   441       FT_Outline_Get_CBox( outline, &cbox );
       
   442 
       
   443       metrics->width        = cbox.xMax - cbox.xMin;
       
   444       metrics->height       = cbox.yMax - cbox.yMin;
       
   445       metrics->horiBearingX = cbox.xMin;
       
   446       metrics->horiBearingY = cbox.yMax - metrics->height;
       
   447     }
       
   448 
       
   449   Exit:
       
   450     return error;
       
   451   }
       
   452 
       
   453 
       
   454   /*************************************************************************/
       
   455   /*************************************************************************/
       
   456   /*****                                                               *****/
       
   457   /*****                      KERNING METHOD                           *****/
       
   458   /*****                                                               *****/
       
   459   /*************************************************************************/
       
   460   /*************************************************************************/
       
   461 
       
   462   FT_LOCAL_DEF( FT_Error )
       
   463   pfr_face_get_kerning( FT_Face     pfrface,        /* PFR_Face */
       
   464                         FT_UInt     glyph1,
       
   465                         FT_UInt     glyph2,
       
   466                         FT_Vector*  kerning )
       
   467   {
       
   468     PFR_Face     face     = (PFR_Face)pfrface;
       
   469     FT_Error     error    = PFR_Err_Ok;
       
   470     PFR_PhyFont  phy_font = &face->phy_font;
       
   471     FT_UInt32    code1, code2, pair;
       
   472 
       
   473 
       
   474     kerning->x = 0;
       
   475     kerning->y = 0;
       
   476 
       
   477     if ( glyph1 > 0 )
       
   478       glyph1--;
       
   479 
       
   480     if ( glyph2 > 0 )
       
   481       glyph2--;
       
   482 
       
   483     /* convert glyph indices to character codes */
       
   484     if ( glyph1 > phy_font->num_chars ||
       
   485          glyph2 > phy_font->num_chars )
       
   486       goto Exit;
       
   487 
       
   488     code1 = phy_font->chars[glyph1].char_code;
       
   489     code2 = phy_font->chars[glyph2].char_code;
       
   490     pair  = PFR_KERN_INDEX( code1, code2 );
       
   491 
       
   492     /* now search the list of kerning items */
       
   493     {
       
   494       PFR_KernItem  item   = phy_font->kern_items;
       
   495       FT_Stream     stream = pfrface->stream;
       
   496 
       
   497 
       
   498       for ( ; item; item = item->next )
       
   499       {
       
   500         if ( pair >= item->pair1 && pair <= item->pair2 )
       
   501           goto FoundPair;
       
   502       }
       
   503       goto Exit;
       
   504 
       
   505     FoundPair: /* we found an item, now parse it and find the value if any */
       
   506       if ( FT_STREAM_SEEK( item->offset )                       ||
       
   507            FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
       
   508         goto Exit;
       
   509 
       
   510       {
       
   511         FT_UInt    count       = item->pair_count;
       
   512         FT_UInt    size        = item->pair_size;
       
   513         FT_UInt    power       = (FT_UInt)ft_highpow2( (FT_UInt32)count );
       
   514         FT_UInt    probe       = power * size;
       
   515         FT_UInt    extra       = count - power;
       
   516         FT_Byte*   base        = stream->cursor;
       
   517         FT_Bool    twobytes    = FT_BOOL( item->flags & 1 );
       
   518         FT_Bool    twobyte_adj = FT_BOOL( item->flags & 2 );
       
   519         FT_Byte*   p;
       
   520         FT_UInt32  cpair;
       
   521 
       
   522 
       
   523         if ( extra > 0 )
       
   524         {
       
   525           p = base + extra * size;
       
   526 
       
   527           if ( twobytes )
       
   528             cpair = FT_NEXT_ULONG( p );
       
   529           else
       
   530             cpair = PFR_NEXT_KPAIR( p );
       
   531 
       
   532           if ( cpair == pair )
       
   533             goto Found;
       
   534 
       
   535           if ( cpair < pair )
       
   536           {
       
   537             if ( twobyte_adj )
       
   538               p += 2;
       
   539             else
       
   540               p++;
       
   541             base = p;
       
   542           }
       
   543         }
       
   544 
       
   545         while ( probe > size )
       
   546         {
       
   547           probe >>= 1;
       
   548           p       = base + probe;
       
   549 
       
   550           if ( twobytes )
       
   551             cpair = FT_NEXT_ULONG( p );
       
   552           else
       
   553             cpair = PFR_NEXT_KPAIR( p );
       
   554 
       
   555           if ( cpair == pair )
       
   556             goto Found;
       
   557 
       
   558           if ( cpair < pair )
       
   559             base += probe;
       
   560         }
       
   561 
       
   562         p = base;
       
   563 
       
   564         if ( twobytes )
       
   565           cpair = FT_NEXT_ULONG( p );
       
   566         else
       
   567           cpair = PFR_NEXT_KPAIR( p );
       
   568 
       
   569         if ( cpair == pair )
       
   570         {
       
   571           FT_Int  value;
       
   572 
       
   573 
       
   574         Found:
       
   575           if ( twobyte_adj )
       
   576             value = FT_PEEK_SHORT( p );
       
   577           else
       
   578             value = p[0];
       
   579 
       
   580           kerning->x = item->base_adj + value;
       
   581         }
       
   582       }
       
   583 
       
   584       FT_FRAME_EXIT();
       
   585     }
       
   586 
       
   587   Exit:
       
   588     return error;
       
   589   }
       
   590 
       
   591 /* END */