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

Generated on Tue Jul 5 14:13:49 2011 for ROOT_528-00b_version by  doxygen 1.5.1