tizen 2.3.1 release
[framework/graphics/freetype.git] / src / pcf / pcfdrivr.c
1 /*  pcfdrivr.c
2
3     FreeType font driver for pcf files
4
5     Copyright (C) 2000-2004, 2006-2011, 2013, 2014 by
6     Francesco Zappa Nardelli
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 */
26
27
28 #include <ft2build.h>
29
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_INTERNAL_STREAM_H
32 #include FT_INTERNAL_OBJECTS_H
33 #include FT_GZIP_H
34 #include FT_LZW_H
35 #include FT_BZIP2_H
36 #include FT_ERRORS_H
37 #include FT_BDF_H
38 #include FT_TRUETYPE_IDS_H
39
40 #include "pcf.h"
41 #include "pcfdrivr.h"
42 #include "pcfread.h"
43
44 #include "pcferror.h"
45 #include "pcfutil.h"
46
47 #undef  FT_COMPONENT
48 #define FT_COMPONENT  trace_pcfread
49
50 #include FT_SERVICE_BDF_H
51 #include FT_SERVICE_XFREE86_NAME_H
52
53
54   /*************************************************************************/
55   /*                                                                       */
56   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
57   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
58   /* messages during execution.                                            */
59   /*                                                                       */
60 #undef  FT_COMPONENT
61 #define FT_COMPONENT  trace_pcfdriver
62
63
64   typedef struct  PCF_CMapRec_
65   {
66     FT_CMapRec    root;
67     FT_UInt       num_encodings;
68     PCF_Encoding  encodings;
69
70   } PCF_CMapRec, *PCF_CMap;
71
72
73   FT_CALLBACK_DEF( FT_Error )
74   pcf_cmap_init( FT_CMap     pcfcmap,   /* PCF_CMap */
75                  FT_Pointer  init_data )
76   {
77     PCF_CMap  cmap = (PCF_CMap)pcfcmap;
78     PCF_Face  face = (PCF_Face)FT_CMAP_FACE( pcfcmap );
79
80     FT_UNUSED( init_data );
81
82
83     cmap->num_encodings = (FT_UInt)face->nencodings;
84     cmap->encodings     = face->encodings;
85
86     return FT_Err_Ok;
87   }
88
89
90   FT_CALLBACK_DEF( void )
91   pcf_cmap_done( FT_CMap  pcfcmap )         /* PCF_CMap */
92   {
93     PCF_CMap  cmap = (PCF_CMap)pcfcmap;
94
95
96     cmap->encodings     = NULL;
97     cmap->num_encodings = 0;
98   }
99
100
101   FT_CALLBACK_DEF( FT_UInt )
102   pcf_cmap_char_index( FT_CMap    pcfcmap,  /* PCF_CMap */
103                        FT_UInt32  charcode )
104   {
105     PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
106     PCF_Encoding  encodings = cmap->encodings;
107     FT_UInt       min, max, mid;
108     FT_UInt       result    = 0;
109
110
111     min = 0;
112     max = cmap->num_encodings;
113
114     while ( min < max )
115     {
116       FT_ULong  code;
117
118
119       mid  = ( min + max ) >> 1;
120       code = encodings[mid].enc;
121
122       if ( charcode == code )
123       {
124         result = encodings[mid].glyph + 1;
125         break;
126       }
127
128       if ( charcode < code )
129         max = mid;
130       else
131         min = mid + 1;
132     }
133
134     return result;
135   }
136
137
138   FT_CALLBACK_DEF( FT_UInt )
139   pcf_cmap_char_next( FT_CMap    pcfcmap,   /* PCF_CMap */
140                       FT_UInt32  *acharcode )
141   {
142     PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
143     PCF_Encoding  encodings = cmap->encodings;
144     FT_UInt       min, max, mid;
145     FT_ULong      charcode  = *acharcode + 1;
146     FT_UInt       result    = 0;
147
148
149     min = 0;
150     max = cmap->num_encodings;
151
152     while ( min < max )
153     {
154       FT_ULong  code;
155
156
157       mid  = ( min + max ) >> 1;
158       code = encodings[mid].enc;
159
160       if ( charcode == code )
161       {
162         result = encodings[mid].glyph + 1;
163         goto Exit;
164       }
165
166       if ( charcode < code )
167         max = mid;
168       else
169         min = mid + 1;
170     }
171
172     charcode = 0;
173     if ( min < cmap->num_encodings )
174     {
175       charcode = encodings[min].enc;
176       result   = encodings[min].glyph + 1;
177     }
178
179   Exit:
180     if ( charcode > 0xFFFFFFFFUL )
181     {
182       FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" ));
183       *acharcode = 0;
184       /* XXX: result should be changed to indicate an overflow error */
185     }
186     else
187       *acharcode = (FT_UInt32)charcode;
188     return result;
189   }
190
191
192   static
193   const FT_CMap_ClassRec  pcf_cmap_class =
194   {
195     sizeof ( PCF_CMapRec ),
196     pcf_cmap_init,
197     pcf_cmap_done,
198     pcf_cmap_char_index,
199     pcf_cmap_char_next,
200
201     NULL, NULL, NULL, NULL, NULL
202   };
203
204
205   FT_CALLBACK_DEF( void )
206   PCF_Face_Done( FT_Face  pcfface )         /* PCF_Face */
207   {
208     PCF_Face   face = (PCF_Face)pcfface;
209     FT_Memory  memory;
210
211
212     if ( !face )
213       return;
214
215     memory = FT_FACE_MEMORY( face );
216
217     FT_FREE( face->encodings );
218     FT_FREE( face->metrics );
219
220     /* free properties */
221     if ( face->properties )
222     {
223       FT_Int  i;
224
225
226       for ( i = 0; i < face->nprops; i++ )
227       {
228         PCF_Property  prop = &face->properties[i];
229
230
231         if ( prop )
232         {
233           FT_FREE( prop->name );
234           if ( prop->isString )
235             FT_FREE( prop->value.atom );
236         }
237       }
238
239       FT_FREE( face->properties );
240     }
241
242     FT_FREE( face->toc.tables );
243     FT_FREE( pcfface->family_name );
244     FT_FREE( pcfface->style_name );
245     FT_FREE( pcfface->available_sizes );
246     FT_FREE( face->charset_encoding );
247     FT_FREE( face->charset_registry );
248
249     /* close compressed stream if any */
250     if ( pcfface->stream == &face->comp_stream )
251     {
252       FT_Stream_Close( &face->comp_stream );
253       pcfface->stream = face->comp_source;
254     }
255   }
256
257
258   FT_CALLBACK_DEF( FT_Error )
259   PCF_Face_Init( FT_Stream      stream,
260                  FT_Face        pcfface,        /* PCF_Face */
261                  FT_Int         face_index,
262                  FT_Int         num_params,
263                  FT_Parameter*  params )
264   {
265     PCF_Face  face  = (PCF_Face)pcfface;
266     FT_Error  error;
267
268     FT_UNUSED( num_params );
269     FT_UNUSED( params );
270
271
272     FT_TRACE2(( "PCF driver\n" ));
273
274     error = pcf_load_font( stream, face );
275     if ( error )
276     {
277       PCF_Face_Done( pcfface );
278
279 #if defined( FT_CONFIG_OPTION_USE_ZLIB )  || \
280     defined( FT_CONFIG_OPTION_USE_LZW )   || \
281     defined( FT_CONFIG_OPTION_USE_BZIP2 )
282
283 #ifdef FT_CONFIG_OPTION_USE_ZLIB
284       {
285         FT_Error  error2;
286
287
288         /* this didn't work, try gzip support! */
289         error2 = FT_Stream_OpenGzip( &face->comp_stream, stream );
290         if ( FT_ERR_EQ( error2, Unimplemented_Feature ) )
291           goto Fail;
292
293         error = error2;
294       }
295 #endif /* FT_CONFIG_OPTION_USE_ZLIB */
296
297 #ifdef FT_CONFIG_OPTION_USE_LZW
298       if ( error )
299       {
300         FT_Error  error3;
301
302
303         /* this didn't work, try LZW support! */
304         error3 = FT_Stream_OpenLZW( &face->comp_stream, stream );
305         if ( FT_ERR_EQ( error3, Unimplemented_Feature ) )
306           goto Fail;
307
308         error = error3;
309       }
310 #endif /* FT_CONFIG_OPTION_USE_LZW */
311
312 #ifdef FT_CONFIG_OPTION_USE_BZIP2
313       if ( error )
314       {
315         FT_Error  error4;
316
317
318         /* this didn't work, try Bzip2 support! */
319         error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream );
320         if ( FT_ERR_EQ( error4, Unimplemented_Feature ) )
321           goto Fail;
322
323         error = error4;
324       }
325 #endif /* FT_CONFIG_OPTION_USE_BZIP2 */
326
327       if ( error )
328         goto Fail;
329
330       face->comp_source = stream;
331       pcfface->stream   = &face->comp_stream;
332
333       stream = pcfface->stream;
334
335       error = pcf_load_font( stream, face );
336       if ( error )
337         goto Fail;
338
339 #else /* !(FT_CONFIG_OPTION_USE_ZLIB ||
340            FT_CONFIG_OPTION_USE_LZW ||
341            FT_CONFIG_OPTION_USE_BZIP2) */
342
343       goto Fail;
344
345 #endif
346     }
347
348     /* PCF could not have multiple face in single font file.
349      * XXX: non-zero face_index is already invalid argument, but
350      *      Type1, Type42 driver has a convention to return
351      *      an invalid argument error when the font could be
352      *      opened by the specified driver.
353      */
354     if ( face_index > 0 ) {
355       FT_ERROR(( "PCF_Face_Init: invalid face index\n" ));
356       PCF_Face_Done( pcfface );
357       return FT_THROW( Invalid_Argument );
358     }
359
360     /* set up charmap */
361     {
362       FT_String  *charset_registry = face->charset_registry;
363       FT_String  *charset_encoding = face->charset_encoding;
364       FT_Bool     unicode_charmap  = 0;
365
366
367       if ( charset_registry && charset_encoding )
368       {
369         char*  s = charset_registry;
370
371
372         /* Uh, oh, compare first letters manually to avoid dependency
373            on locales. */
374         if ( ( s[0] == 'i' || s[0] == 'I' ) &&
375              ( s[1] == 's' || s[1] == 'S' ) &&
376              ( s[2] == 'o' || s[2] == 'O' ) )
377         {
378           s += 3;
379           if ( !ft_strcmp( s, "10646" )                      ||
380                ( !ft_strcmp( s, "8859" ) &&
381                  !ft_strcmp( face->charset_encoding, "1" ) ) )
382           unicode_charmap = 1;
383         }
384       }
385
386       {
387         FT_CharMapRec  charmap;
388
389
390         charmap.face        = FT_FACE( face );
391         charmap.encoding    = FT_ENCODING_NONE;
392         /* initial platform/encoding should indicate unset status? */
393         charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
394         charmap.encoding_id = TT_APPLE_ID_DEFAULT;
395
396         if ( unicode_charmap )
397         {
398           charmap.encoding    = FT_ENCODING_UNICODE;
399           charmap.platform_id = TT_PLATFORM_MICROSOFT;
400           charmap.encoding_id = TT_MS_ID_UNICODE_CS;
401         }
402
403         error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
404
405 #if 0
406         /* Select default charmap */
407         if ( pcfface->num_charmaps )
408           pcfface->charmap = pcfface->charmaps[0];
409 #endif
410       }
411     }
412
413   Exit:
414     return error;
415
416   Fail:
417     FT_TRACE2(( "  not a PCF file\n" ));
418     PCF_Face_Done( pcfface );
419     error = FT_THROW( Unknown_File_Format );  /* error */
420     goto Exit;
421   }
422
423
424   FT_CALLBACK_DEF( FT_Error )
425   PCF_Size_Select( FT_Size   size,
426                    FT_ULong  strike_index )
427   {
428     PCF_Accel  accel = &( (PCF_Face)size->face )->accel;
429
430
431     FT_Select_Metrics( size->face, strike_index );
432
433     size->metrics.ascender    =  accel->fontAscent << 6;
434     size->metrics.descender   = -accel->fontDescent << 6;
435     size->metrics.max_advance =  accel->maxbounds.characterWidth << 6;
436
437     return FT_Err_Ok;
438   }
439
440
441   FT_CALLBACK_DEF( FT_Error )
442   PCF_Size_Request( FT_Size          size,
443                     FT_Size_Request  req )
444   {
445     PCF_Face         face  = (PCF_Face)size->face;
446     FT_Bitmap_Size*  bsize = size->face->available_sizes;
447     FT_Error         error = FT_ERR( Invalid_Pixel_Size );
448     FT_Long          height;
449
450
451     height = FT_REQUEST_HEIGHT( req );
452     height = ( height + 32 ) >> 6;
453
454     switch ( req->type )
455     {
456     case FT_SIZE_REQUEST_TYPE_NOMINAL:
457       if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
458         error = FT_Err_Ok;
459       break;
460
461     case FT_SIZE_REQUEST_TYPE_REAL_DIM:
462       if ( height == ( face->accel.fontAscent +
463                        face->accel.fontDescent ) )
464         error = FT_Err_Ok;
465       break;
466
467     default:
468       error = FT_THROW( Unimplemented_Feature );
469       break;
470     }
471
472     if ( error )
473       return error;
474     else
475       return PCF_Size_Select( size, 0 );
476   }
477
478
479   FT_CALLBACK_DEF( FT_Error )
480   PCF_Glyph_Load( FT_GlyphSlot  slot,
481                   FT_Size       size,
482                   FT_UInt       glyph_index,
483                   FT_Int32      load_flags )
484   {
485     PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
486     FT_Stream   stream;
487     FT_Error    error  = FT_Err_Ok;
488     FT_Bitmap*  bitmap = &slot->bitmap;
489     PCF_Metric  metric;
490     FT_Offset   bytes;
491
492     FT_UNUSED( load_flags );
493
494
495     FT_TRACE1(( "PCF_Glyph_Load: glyph index %d\n", glyph_index ));
496
497     if ( !face )
498     {
499       error = FT_THROW( Invalid_Face_Handle );
500       goto Exit;
501     }
502
503     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
504     {
505       error = FT_THROW( Invalid_Argument );
506       goto Exit;
507     }
508
509     stream = face->root.stream;
510
511     if ( glyph_index > 0 )
512       glyph_index--;
513
514     metric = face->metrics + glyph_index;
515
516     bitmap->rows       = metric->ascent + metric->descent;
517     bitmap->width      = metric->rightSideBearing - metric->leftSideBearing;
518     bitmap->num_grays  = 1;
519     bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
520
521     FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
522                   PCF_BIT_ORDER( face->bitmapsFormat ),
523                   PCF_BYTE_ORDER( face->bitmapsFormat ),
524                   PCF_GLYPH_PAD( face->bitmapsFormat ) ));
525
526     switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
527     {
528     case 1:
529       bitmap->pitch = ( bitmap->width + 7 ) >> 3;
530       break;
531
532     case 2:
533       bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
534       break;
535
536     case 4:
537       bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
538       break;
539
540     case 8:
541       bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
542       break;
543
544     default:
545       return FT_THROW( Invalid_File_Format );
546     }
547
548     /* XXX: to do: are there cases that need repadding the bitmap? */
549     bytes = bitmap->pitch * bitmap->rows;
550
551     error = ft_glyphslot_alloc_bitmap( slot, (FT_ULong)bytes );
552     if ( error )
553       goto Exit;
554
555     if ( FT_STREAM_SEEK( metric->bits )          ||
556          FT_STREAM_READ( bitmap->buffer, bytes ) )
557       goto Exit;
558
559     if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
560       BitOrderInvert( bitmap->buffer, bytes );
561
562     if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
563            PCF_BIT_ORDER( face->bitmapsFormat )  ) )
564     {
565       switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
566       {
567       case 1:
568         break;
569
570       case 2:
571         TwoByteSwap( bitmap->buffer, bytes );
572         break;
573
574       case 4:
575         FourByteSwap( bitmap->buffer, bytes );
576         break;
577       }
578     }
579
580     slot->format      = FT_GLYPH_FORMAT_BITMAP;
581     slot->bitmap_left = metric->leftSideBearing;
582     slot->bitmap_top  = metric->ascent;
583
584     slot->metrics.horiAdvance  = metric->characterWidth << 6;
585     slot->metrics.horiBearingX = metric->leftSideBearing << 6;
586     slot->metrics.horiBearingY = metric->ascent << 6;
587     slot->metrics.width        = ( metric->rightSideBearing -
588                                    metric->leftSideBearing ) << 6;
589     slot->metrics.height       = bitmap->rows << 6;
590
591     ft_synthesize_vertical_metrics( &slot->metrics,
592                                     ( face->accel.fontAscent +
593                                       face->accel.fontDescent ) << 6 );
594
595   Exit:
596     return error;
597   }
598
599
600  /*
601   *
602   *  BDF SERVICE
603   *
604   */
605
606   static FT_Error
607   pcf_get_bdf_property( PCF_Face          face,
608                         const char*       prop_name,
609                         BDF_PropertyRec  *aproperty )
610   {
611     PCF_Property  prop;
612
613
614     prop = pcf_find_property( face, prop_name );
615     if ( prop != NULL )
616     {
617       if ( prop->isString )
618       {
619         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
620         aproperty->u.atom = prop->value.atom;
621       }
622       else
623       {
624         if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
625         {
626           FT_TRACE1(( "pcf_get_bdf_property: " ));
627           FT_TRACE1(( "too large integer 0x%x is truncated\n" ));
628         }
629         /* Apparently, the PCF driver loads all properties as signed integers!
630          * This really doesn't seem to be a problem, because this is
631          * sufficient for any meaningful values.
632          */
633         aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
634         aproperty->u.integer = (FT_Int32)prop->value.l;
635       }
636       return 0;
637     }
638
639     return FT_THROW( Invalid_Argument );
640   }
641
642
643   static FT_Error
644   pcf_get_charset_id( PCF_Face      face,
645                       const char*  *acharset_encoding,
646                       const char*  *acharset_registry )
647   {
648     *acharset_encoding = face->charset_encoding;
649     *acharset_registry = face->charset_registry;
650
651     return 0;
652   }
653
654
655   static const FT_Service_BDFRec  pcf_service_bdf =
656   {
657     (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,
658     (FT_BDF_GetPropertyFunc) pcf_get_bdf_property
659   };
660
661
662  /*
663   *
664   *  SERVICE LIST
665   *
666   */
667
668   static const FT_ServiceDescRec  pcf_services[] =
669   {
670     { FT_SERVICE_ID_BDF,       &pcf_service_bdf },
671     { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF },
672     { NULL, NULL }
673   };
674
675
676   FT_CALLBACK_DEF( FT_Module_Interface )
677   pcf_driver_requester( FT_Module    module,
678                         const char*  name )
679   {
680     FT_UNUSED( module );
681
682     return ft_service_list_lookup( pcf_services, name );
683   }
684
685
686   FT_CALLBACK_TABLE_DEF
687   const FT_Driver_ClassRec  pcf_driver_class =
688   {
689     {
690       FT_MODULE_FONT_DRIVER        |
691       FT_MODULE_DRIVER_NO_OUTLINES,
692       sizeof ( FT_DriverRec ),
693
694       "pcf",
695       0x10000L,
696       0x20000L,
697
698       0,
699
700       0,                    /* FT_Module_Constructor */
701       0,                    /* FT_Module_Destructor  */
702       pcf_driver_requester
703     },
704
705     sizeof ( PCF_FaceRec ),
706     sizeof ( FT_SizeRec ),
707     sizeof ( FT_GlyphSlotRec ),
708
709     PCF_Face_Init,
710     PCF_Face_Done,
711     0,                      /* FT_Size_InitFunc */
712     0,                      /* FT_Size_DoneFunc */
713     0,                      /* FT_Slot_InitFunc */
714     0,                      /* FT_Slot_DoneFunc */
715
716     PCF_Glyph_Load,
717
718     0,                      /* FT_Face_GetKerningFunc  */
719     0,                      /* FT_Face_AttachFunc      */
720     0,                      /* FT_Face_GetAdvancesFunc */
721
722     PCF_Size_Request,
723     PCF_Size_Select
724   };
725
726
727 /* END */