Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / freetype2 / src / src / pfr / pfrobjs.c
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 */