Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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