xref: /inferno-os/libfreetype/pfrobjs.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  pfrobjs.c                                                              */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    FreeType PFR object methods (body).                                  */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 2002 by                                                      */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth #include "pfrobjs.h"
20*37da2899SCharles.Forsyth #include "pfrload.h"
21*37da2899SCharles.Forsyth #include "pfrgload.h"
22*37da2899SCharles.Forsyth #include "pfrcmap.h"
23*37da2899SCharles.Forsyth #include "pfrsbit.h"
24*37da2899SCharles.Forsyth #include FT_OUTLINE_H
25*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth #include "pfrerror.h"
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth #undef  FT_COMPONENT
30*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_pfr
31*37da2899SCharles.Forsyth 
32*37da2899SCharles.Forsyth 
33*37da2899SCharles.Forsyth   /*************************************************************************/
34*37da2899SCharles.Forsyth   /*************************************************************************/
35*37da2899SCharles.Forsyth   /*****                                                               *****/
36*37da2899SCharles.Forsyth   /*****                     FACE OBJECT METHODS                       *****/
37*37da2899SCharles.Forsyth   /*****                                                               *****/
38*37da2899SCharles.Forsyth   /*************************************************************************/
39*37da2899SCharles.Forsyth   /*************************************************************************/
40*37da2899SCharles.Forsyth 
41*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
pfr_face_done(PFR_Face face)42*37da2899SCharles.Forsyth   pfr_face_done( PFR_Face  face )
43*37da2899SCharles.Forsyth   {
44*37da2899SCharles.Forsyth     /* finalize the physical font record */
45*37da2899SCharles.Forsyth     pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) );
46*37da2899SCharles.Forsyth 
47*37da2899SCharles.Forsyth     /* no need to finalize the logical font or the header */
48*37da2899SCharles.Forsyth   }
49*37da2899SCharles.Forsyth 
50*37da2899SCharles.Forsyth 
51*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
pfr_face_init(FT_Stream stream,PFR_Face face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)52*37da2899SCharles.Forsyth   pfr_face_init( FT_Stream      stream,
53*37da2899SCharles.Forsyth                  PFR_Face       face,
54*37da2899SCharles.Forsyth                  FT_Int         face_index,
55*37da2899SCharles.Forsyth                  FT_Int         num_params,
56*37da2899SCharles.Forsyth                  FT_Parameter*  params )
57*37da2899SCharles.Forsyth   {
58*37da2899SCharles.Forsyth     FT_Error  error;
59*37da2899SCharles.Forsyth 
60*37da2899SCharles.Forsyth     FT_UNUSED( num_params );
61*37da2899SCharles.Forsyth     FT_UNUSED( params );
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth 
64*37da2899SCharles.Forsyth     /* load the header and check it */
65*37da2899SCharles.Forsyth     error = pfr_header_load( &face->header, stream );
66*37da2899SCharles.Forsyth     if ( error )
67*37da2899SCharles.Forsyth       goto Exit;
68*37da2899SCharles.Forsyth 
69*37da2899SCharles.Forsyth     if ( !pfr_header_check( &face->header ) )
70*37da2899SCharles.Forsyth     {
71*37da2899SCharles.Forsyth       FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" ));
72*37da2899SCharles.Forsyth       error = PFR_Err_Unknown_File_Format;
73*37da2899SCharles.Forsyth       goto Exit;
74*37da2899SCharles.Forsyth     }
75*37da2899SCharles.Forsyth 
76*37da2899SCharles.Forsyth     /* check face index */
77*37da2899SCharles.Forsyth     {
78*37da2899SCharles.Forsyth       FT_UInt  num_faces;
79*37da2899SCharles.Forsyth 
80*37da2899SCharles.Forsyth 
81*37da2899SCharles.Forsyth       error = pfr_log_font_count( stream,
82*37da2899SCharles.Forsyth                                   face->header.log_dir_offset,
83*37da2899SCharles.Forsyth                                   &num_faces );
84*37da2899SCharles.Forsyth       if ( error )
85*37da2899SCharles.Forsyth         goto Exit;
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth       face->root.num_faces = num_faces;
88*37da2899SCharles.Forsyth     }
89*37da2899SCharles.Forsyth 
90*37da2899SCharles.Forsyth     if ( face_index < 0 )
91*37da2899SCharles.Forsyth       goto Exit;
92*37da2899SCharles.Forsyth 
93*37da2899SCharles.Forsyth     if ( face_index >= face->root.num_faces )
94*37da2899SCharles.Forsyth     {
95*37da2899SCharles.Forsyth       FT_ERROR(( "pfr_face_init: invalid face index\n" ));
96*37da2899SCharles.Forsyth       error = PFR_Err_Invalid_Argument;
97*37da2899SCharles.Forsyth       goto Exit;
98*37da2899SCharles.Forsyth     }
99*37da2899SCharles.Forsyth 
100*37da2899SCharles.Forsyth     /* load the face */
101*37da2899SCharles.Forsyth     error = pfr_log_font_load(
102*37da2899SCharles.Forsyth                &face->log_font, stream, face_index,
103*37da2899SCharles.Forsyth                face->header.log_dir_offset,
104*37da2899SCharles.Forsyth                FT_BOOL( face->header.phy_font_max_size_high != 0 ) );
105*37da2899SCharles.Forsyth     if ( error )
106*37da2899SCharles.Forsyth       goto Exit;
107*37da2899SCharles.Forsyth 
108*37da2899SCharles.Forsyth     /* now load the physical font descriptor */
109*37da2899SCharles.Forsyth      error = pfr_phy_font_load( &face->phy_font, stream,
110*37da2899SCharles.Forsyth                                  face->log_font.phys_offset,
111*37da2899SCharles.Forsyth                                  face->log_font.phys_size );
112*37da2899SCharles.Forsyth      if ( error )
113*37da2899SCharles.Forsyth        goto Exit;
114*37da2899SCharles.Forsyth 
115*37da2899SCharles.Forsyth      /* now, set-up all root face fields */
116*37da2899SCharles.Forsyth      {
117*37da2899SCharles.Forsyth        FT_Face      root     = FT_FACE( face );
118*37da2899SCharles.Forsyth        PFR_PhyFont  phy_font = &face->phy_font;
119*37da2899SCharles.Forsyth 
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth        root->face_index = face_index;
122*37da2899SCharles.Forsyth        root->num_glyphs = phy_font->num_chars;
123*37da2899SCharles.Forsyth        root->face_flags = FT_FACE_FLAG_SCALABLE;
124*37da2899SCharles.Forsyth 
125*37da2899SCharles.Forsyth        if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 )
126*37da2899SCharles.Forsyth          root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
127*37da2899SCharles.Forsyth 
128*37da2899SCharles.Forsyth        if ( phy_font->flags & PFR_PHY_VERTICAL )
129*37da2899SCharles.Forsyth          root->face_flags |= FT_FACE_FLAG_VERTICAL;
130*37da2899SCharles.Forsyth        else
131*37da2899SCharles.Forsyth          root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
132*37da2899SCharles.Forsyth 
133*37da2899SCharles.Forsyth        if ( phy_font->num_strikes > 0 )
134*37da2899SCharles.Forsyth          root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth        if ( phy_font->num_kern_pairs > 0 )
137*37da2899SCharles.Forsyth          root->face_flags |= FT_FACE_FLAG_KERNING;
138*37da2899SCharles.Forsyth 
139*37da2899SCharles.Forsyth        root->family_name = phy_font->font_id;
140*37da2899SCharles.Forsyth        root->style_name  = NULL;  /* no style name in font file */
141*37da2899SCharles.Forsyth 
142*37da2899SCharles.Forsyth        root->num_fixed_sizes = 0;
143*37da2899SCharles.Forsyth        root->available_sizes = 0;
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth        root->bbox         = phy_font->bbox;
146*37da2899SCharles.Forsyth        root->units_per_EM = (FT_UShort)phy_font->outline_resolution;
147*37da2899SCharles.Forsyth        root->ascender     = (FT_Short) phy_font->bbox.yMax;
148*37da2899SCharles.Forsyth        root->descender    = (FT_Short) phy_font->bbox.yMin;
149*37da2899SCharles.Forsyth        root->height       = (FT_Short)
150*37da2899SCharles.Forsyth                               ( ( ( root->ascender - root->descender ) * 12 )
151*37da2899SCharles.Forsyth                                 / 10 );
152*37da2899SCharles.Forsyth 
153*37da2899SCharles.Forsyth        /* now compute maximum advance width */
154*37da2899SCharles.Forsyth        if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 )
155*37da2899SCharles.Forsyth          root->max_advance_width = (FT_Short)phy_font->standard_advance;
156*37da2899SCharles.Forsyth        else
157*37da2899SCharles.Forsyth        {
158*37da2899SCharles.Forsyth          FT_Int    max = 0;
159*37da2899SCharles.Forsyth          FT_UInt   count = phy_font->num_chars;
160*37da2899SCharles.Forsyth          PFR_Char  gchar = phy_font->chars;
161*37da2899SCharles.Forsyth 
162*37da2899SCharles.Forsyth 
163*37da2899SCharles.Forsyth          for ( ; count > 0; count--, gchar++ )
164*37da2899SCharles.Forsyth          {
165*37da2899SCharles.Forsyth            if ( max < gchar->advance )
166*37da2899SCharles.Forsyth              max = gchar->advance;
167*37da2899SCharles.Forsyth          }
168*37da2899SCharles.Forsyth 
169*37da2899SCharles.Forsyth          root->max_advance_width = (FT_Short)max;
170*37da2899SCharles.Forsyth        }
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth        root->max_advance_height = root->height;
173*37da2899SCharles.Forsyth 
174*37da2899SCharles.Forsyth        root->underline_position  = (FT_Short)( - root->units_per_EM / 10 );
175*37da2899SCharles.Forsyth        root->underline_thickness = (FT_Short)(   root->units_per_EM / 30 );
176*37da2899SCharles.Forsyth 
177*37da2899SCharles.Forsyth        /* create charmap */
178*37da2899SCharles.Forsyth        {
179*37da2899SCharles.Forsyth          FT_CharMapRec  charmap;
180*37da2899SCharles.Forsyth 
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth          charmap.face        = root;
183*37da2899SCharles.Forsyth          charmap.platform_id = 3;
184*37da2899SCharles.Forsyth          charmap.encoding_id = 1;
185*37da2899SCharles.Forsyth          charmap.encoding    = FT_ENCODING_UNICODE;
186*37da2899SCharles.Forsyth 
187*37da2899SCharles.Forsyth          FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL );
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth #if 0
190*37da2899SCharles.Forsyth          /* Select default charmap */
191*37da2899SCharles.Forsyth          if (root->num_charmaps)
192*37da2899SCharles.Forsyth            root->charmap = root->charmaps[0];
193*37da2899SCharles.Forsyth #endif
194*37da2899SCharles.Forsyth        }
195*37da2899SCharles.Forsyth 
196*37da2899SCharles.Forsyth        /* check whether we've loaded any kerning pairs */
197*37da2899SCharles.Forsyth        if ( phy_font->num_kern_pairs )
198*37da2899SCharles.Forsyth          root->face_flags |= FT_FACE_FLAG_KERNING;
199*37da2899SCharles.Forsyth      }
200*37da2899SCharles.Forsyth 
201*37da2899SCharles.Forsyth   Exit:
202*37da2899SCharles.Forsyth     return error;
203*37da2899SCharles.Forsyth   }
204*37da2899SCharles.Forsyth 
205*37da2899SCharles.Forsyth 
206*37da2899SCharles.Forsyth   /*************************************************************************/
207*37da2899SCharles.Forsyth   /*************************************************************************/
208*37da2899SCharles.Forsyth   /*****                                                               *****/
209*37da2899SCharles.Forsyth   /*****                    SLOT OBJECT METHOD                         *****/
210*37da2899SCharles.Forsyth   /*****                                                               *****/
211*37da2899SCharles.Forsyth   /*************************************************************************/
212*37da2899SCharles.Forsyth   /*************************************************************************/
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
pfr_slot_init(PFR_Slot slot)215*37da2899SCharles.Forsyth   pfr_slot_init( PFR_Slot  slot )
216*37da2899SCharles.Forsyth   {
217*37da2899SCharles.Forsyth     FT_GlyphLoader  loader = slot->root.internal->loader;
218*37da2899SCharles.Forsyth 
219*37da2899SCharles.Forsyth     pfr_glyph_init( &slot->glyph, loader );
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth     return 0;
222*37da2899SCharles.Forsyth   }
223*37da2899SCharles.Forsyth 
224*37da2899SCharles.Forsyth 
225*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
pfr_slot_done(PFR_Slot slot)226*37da2899SCharles.Forsyth   pfr_slot_done( PFR_Slot  slot )
227*37da2899SCharles.Forsyth   {
228*37da2899SCharles.Forsyth     pfr_glyph_done( &slot->glyph );
229*37da2899SCharles.Forsyth   }
230*37da2899SCharles.Forsyth 
231*37da2899SCharles.Forsyth 
232*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
pfr_slot_load(PFR_Slot slot,PFR_Size size,FT_UInt gindex,FT_Int32 load_flags)233*37da2899SCharles.Forsyth   pfr_slot_load( PFR_Slot  slot,
234*37da2899SCharles.Forsyth                  PFR_Size  size,
235*37da2899SCharles.Forsyth                  FT_UInt   gindex,
236*37da2899SCharles.Forsyth                  FT_Int32  load_flags )
237*37da2899SCharles.Forsyth   {
238*37da2899SCharles.Forsyth     FT_Error     error;
239*37da2899SCharles.Forsyth     PFR_Face     face    = (PFR_Face)slot->root.face;
240*37da2899SCharles.Forsyth     PFR_Char     gchar;
241*37da2899SCharles.Forsyth     FT_Outline*  outline = &slot->root.outline;
242*37da2899SCharles.Forsyth     FT_ULong     gps_offset;
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth     if (gindex > 0)
245*37da2899SCharles.Forsyth       gindex--;
246*37da2899SCharles.Forsyth 
247*37da2899SCharles.Forsyth     /* check that the glyph index is correct */
248*37da2899SCharles.Forsyth     FT_ASSERT( gindex < face->phy_font.num_chars );
249*37da2899SCharles.Forsyth 
250*37da2899SCharles.Forsyth     /* try to load an embedded bitmap */
251*37da2899SCharles.Forsyth     if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 )
252*37da2899SCharles.Forsyth     {
253*37da2899SCharles.Forsyth       error = pfr_slot_load_bitmap( slot, size, gindex );
254*37da2899SCharles.Forsyth       if ( error == 0 )
255*37da2899SCharles.Forsyth         goto Exit;
256*37da2899SCharles.Forsyth     }
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth     gchar               = face->phy_font.chars + gindex;
259*37da2899SCharles.Forsyth     slot->root.format   = FT_GLYPH_FORMAT_OUTLINE;
260*37da2899SCharles.Forsyth     outline->n_points   = 0;
261*37da2899SCharles.Forsyth     outline->n_contours = 0;
262*37da2899SCharles.Forsyth     gps_offset          = face->header.gps_section_offset;
263*37da2899SCharles.Forsyth 
264*37da2899SCharles.Forsyth     /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */
265*37da2899SCharles.Forsyth     error = pfr_glyph_load( &slot->glyph, face->root.stream,
266*37da2899SCharles.Forsyth                             gps_offset, gchar->gps_offset, gchar->gps_size );
267*37da2899SCharles.Forsyth 
268*37da2899SCharles.Forsyth     if ( !error )
269*37da2899SCharles.Forsyth     {
270*37da2899SCharles.Forsyth       FT_BBox            cbox;
271*37da2899SCharles.Forsyth       FT_Glyph_Metrics*  metrics = &slot->root.metrics;
272*37da2899SCharles.Forsyth       FT_Pos             advance;
273*37da2899SCharles.Forsyth       FT_Int             em_metrics, em_outline;
274*37da2899SCharles.Forsyth       FT_Bool            scaling;
275*37da2899SCharles.Forsyth 
276*37da2899SCharles.Forsyth 
277*37da2899SCharles.Forsyth       scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth       /* copy outline data */
280*37da2899SCharles.Forsyth       *outline = slot->glyph.loader->base.outline;
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth       outline->flags &= ~FT_OUTLINE_OWNER;
283*37da2899SCharles.Forsyth       outline->flags |= FT_OUTLINE_REVERSE_FILL;
284*37da2899SCharles.Forsyth 
285*37da2899SCharles.Forsyth       if ( size && size->root.metrics.y_ppem < 24 )
286*37da2899SCharles.Forsyth         outline->flags |= FT_OUTLINE_HIGH_PRECISION;
287*37da2899SCharles.Forsyth 
288*37da2899SCharles.Forsyth       /* compute the advance vector */
289*37da2899SCharles.Forsyth       metrics->horiAdvance = 0;
290*37da2899SCharles.Forsyth       metrics->vertAdvance = 0;
291*37da2899SCharles.Forsyth 
292*37da2899SCharles.Forsyth       advance    = gchar->advance;
293*37da2899SCharles.Forsyth       em_metrics = face->phy_font.metrics_resolution;
294*37da2899SCharles.Forsyth       em_outline = face->phy_font.outline_resolution;
295*37da2899SCharles.Forsyth 
296*37da2899SCharles.Forsyth       if ( em_metrics != em_outline )
297*37da2899SCharles.Forsyth         advance = FT_MulDiv( advance, em_outline, em_metrics );
298*37da2899SCharles.Forsyth 
299*37da2899SCharles.Forsyth       if ( face->phy_font.flags & PFR_PHY_VERTICAL )
300*37da2899SCharles.Forsyth         metrics->vertAdvance = advance;
301*37da2899SCharles.Forsyth       else
302*37da2899SCharles.Forsyth         metrics->horiAdvance = advance;
303*37da2899SCharles.Forsyth 
304*37da2899SCharles.Forsyth       slot->root.linearHoriAdvance = metrics->horiAdvance;
305*37da2899SCharles.Forsyth       slot->root.linearVertAdvance = metrics->vertAdvance;
306*37da2899SCharles.Forsyth 
307*37da2899SCharles.Forsyth       /* make-up vertical metrics(?) */
308*37da2899SCharles.Forsyth       metrics->vertBearingX = 0;
309*37da2899SCharles.Forsyth       metrics->vertBearingY = 0;
310*37da2899SCharles.Forsyth 
311*37da2899SCharles.Forsyth       /* scale when needed */
312*37da2899SCharles.Forsyth       if ( scaling )
313*37da2899SCharles.Forsyth       {
314*37da2899SCharles.Forsyth         FT_Int      n;
315*37da2899SCharles.Forsyth         FT_Fixed    x_scale = size->root.metrics.x_scale;
316*37da2899SCharles.Forsyth         FT_Fixed    y_scale = size->root.metrics.y_scale;
317*37da2899SCharles.Forsyth         FT_Vector*  vec     = outline->points;
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth 
320*37da2899SCharles.Forsyth         /* scale outline points */
321*37da2899SCharles.Forsyth         for ( n = 0; n < outline->n_points; n++, vec++ )
322*37da2899SCharles.Forsyth         {
323*37da2899SCharles.Forsyth           vec->x = FT_MulFix( vec->x, x_scale );
324*37da2899SCharles.Forsyth           vec->y = FT_MulFix( vec->y, y_scale );
325*37da2899SCharles.Forsyth         }
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth         /* scale the advance */
328*37da2899SCharles.Forsyth         metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
329*37da2899SCharles.Forsyth         metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
330*37da2899SCharles.Forsyth       }
331*37da2899SCharles.Forsyth 
332*37da2899SCharles.Forsyth       /* compute the rest of the metrics */
333*37da2899SCharles.Forsyth       FT_Outline_Get_CBox( outline, &cbox );
334*37da2899SCharles.Forsyth 
335*37da2899SCharles.Forsyth       metrics->width        = cbox.xMax - cbox.xMin;
336*37da2899SCharles.Forsyth       metrics->height       = cbox.yMax - cbox.yMin;
337*37da2899SCharles.Forsyth       metrics->horiBearingX = cbox.xMin;
338*37da2899SCharles.Forsyth       metrics->horiBearingY = cbox.yMax - metrics->height;
339*37da2899SCharles.Forsyth     }
340*37da2899SCharles.Forsyth 
341*37da2899SCharles.Forsyth   Exit:
342*37da2899SCharles.Forsyth     return error;
343*37da2899SCharles.Forsyth   }
344*37da2899SCharles.Forsyth 
345*37da2899SCharles.Forsyth 
346*37da2899SCharles.Forsyth   /*************************************************************************/
347*37da2899SCharles.Forsyth   /*************************************************************************/
348*37da2899SCharles.Forsyth   /*****                                                               *****/
349*37da2899SCharles.Forsyth   /*****                      KERNING METHOD                           *****/
350*37da2899SCharles.Forsyth   /*****                                                               *****/
351*37da2899SCharles.Forsyth   /*************************************************************************/
352*37da2899SCharles.Forsyth   /*************************************************************************/
353*37da2899SCharles.Forsyth 
354*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
pfr_face_get_kerning(PFR_Face face,FT_UInt glyph1,FT_UInt glyph2,FT_Vector * kerning)355*37da2899SCharles.Forsyth   pfr_face_get_kerning( PFR_Face    face,
356*37da2899SCharles.Forsyth                         FT_UInt     glyph1,
357*37da2899SCharles.Forsyth                         FT_UInt     glyph2,
358*37da2899SCharles.Forsyth                         FT_Vector*  kerning )
359*37da2899SCharles.Forsyth   {
360*37da2899SCharles.Forsyth     FT_Error      error;
361*37da2899SCharles.Forsyth     PFR_PhyFont   phy_font = &face->phy_font;
362*37da2899SCharles.Forsyth     PFR_KernItem  item     = phy_font->kern_items;
363*37da2899SCharles.Forsyth     FT_UInt32     idx      = PFR_KERN_INDEX( glyph1, glyph2 );
364*37da2899SCharles.Forsyth 
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth     kerning->x = 0;
367*37da2899SCharles.Forsyth     kerning->y = 0;
368*37da2899SCharles.Forsyth 
369*37da2899SCharles.Forsyth     /* find the kerning item containing our pair */
370*37da2899SCharles.Forsyth     while ( item )
371*37da2899SCharles.Forsyth     {
372*37da2899SCharles.Forsyth       if ( item->pair1 <= idx && idx <= item->pair2 )
373*37da2899SCharles.Forsyth         goto Found_Item;
374*37da2899SCharles.Forsyth 
375*37da2899SCharles.Forsyth       item = item->next;
376*37da2899SCharles.Forsyth     }
377*37da2899SCharles.Forsyth 
378*37da2899SCharles.Forsyth     /* not found */
379*37da2899SCharles.Forsyth     goto Exit;
380*37da2899SCharles.Forsyth 
381*37da2899SCharles.Forsyth   Found_Item:
382*37da2899SCharles.Forsyth     {
383*37da2899SCharles.Forsyth       /* perform simply binary search within the item */
384*37da2899SCharles.Forsyth       FT_UInt    min, mid, max;
385*37da2899SCharles.Forsyth       FT_Stream  stream = face->root.stream;
386*37da2899SCharles.Forsyth       FT_Byte*   p;
387*37da2899SCharles.Forsyth 
388*37da2899SCharles.Forsyth 
389*37da2899SCharles.Forsyth       if ( FT_STREAM_SEEK( item->offset )                       ||
390*37da2899SCharles.Forsyth            FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
391*37da2899SCharles.Forsyth         goto Exit;
392*37da2899SCharles.Forsyth 
393*37da2899SCharles.Forsyth       min = 0;
394*37da2899SCharles.Forsyth       max = item->pair_count;
395*37da2899SCharles.Forsyth       while ( min < max )
396*37da2899SCharles.Forsyth       {
397*37da2899SCharles.Forsyth         FT_UInt  char1, char2, charcode;
398*37da2899SCharles.Forsyth 
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth         mid = ( min + max ) >> 1;
401*37da2899SCharles.Forsyth         p   = stream->cursor + mid*item->pair_size;
402*37da2899SCharles.Forsyth 
403*37da2899SCharles.Forsyth         if ( item->flags & PFR_KERN_2BYTE_CHAR )
404*37da2899SCharles.Forsyth         {
405*37da2899SCharles.Forsyth           char1 = FT_NEXT_USHORT( p );
406*37da2899SCharles.Forsyth           char2 = FT_NEXT_USHORT( p );
407*37da2899SCharles.Forsyth         }
408*37da2899SCharles.Forsyth         else
409*37da2899SCharles.Forsyth         {
410*37da2899SCharles.Forsyth           char1 = FT_NEXT_USHORT( p );
411*37da2899SCharles.Forsyth           char2 = FT_NEXT_USHORT( p );
412*37da2899SCharles.Forsyth         }
413*37da2899SCharles.Forsyth         charcode = PFR_KERN_INDEX( char1, char2 );
414*37da2899SCharles.Forsyth 
415*37da2899SCharles.Forsyth         if ( idx == charcode )
416*37da2899SCharles.Forsyth         {
417*37da2899SCharles.Forsyth           if ( item->flags & PFR_KERN_2BYTE_ADJ )
418*37da2899SCharles.Forsyth             kerning->x = item->base_adj + FT_NEXT_SHORT( p );
419*37da2899SCharles.Forsyth           else
420*37da2899SCharles.Forsyth             kerning->x = item->base_adj + FT_NEXT_CHAR( p );
421*37da2899SCharles.Forsyth 
422*37da2899SCharles.Forsyth           break;
423*37da2899SCharles.Forsyth         }
424*37da2899SCharles.Forsyth         if ( idx > charcode )
425*37da2899SCharles.Forsyth           min = mid + 1;
426*37da2899SCharles.Forsyth         else
427*37da2899SCharles.Forsyth           max = mid;
428*37da2899SCharles.Forsyth       }
429*37da2899SCharles.Forsyth 
430*37da2899SCharles.Forsyth       FT_FRAME_EXIT();
431*37da2899SCharles.Forsyth     }
432*37da2899SCharles.Forsyth 
433*37da2899SCharles.Forsyth   Exit:
434*37da2899SCharles.Forsyth     return 0;
435*37da2899SCharles.Forsyth   }
436*37da2899SCharles.Forsyth 
437*37da2899SCharles.Forsyth /* END */
438