xref: /inferno-os/libfreetype/pcfdriver.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 /*  pcfdriver.c
2 
3     FreeType font driver for pcf files
4 
5     Copyright (C) 2000-2001, 2002 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_ERRORS_H
35 
36 #include "pcf.h"
37 #include "pcfdriver.h"
38 #include "pcfutil.h"
39 
40 #include "pcferror.h"
41 
42 #undef  FT_COMPONENT
43 #define FT_COMPONENT  trace_pcfread
44 
45 
46   typedef struct  PCF_CMapRec_
47   {
48     FT_CMapRec    cmap;
49     FT_UInt       num_encodings;
50     PCF_Encoding  encodings;
51 
52   } PCF_CMapRec, *PCF_CMap;
53 
54 
55   FT_CALLBACK_DEF( FT_Error )
pcf_cmap_init(PCF_CMap cmap)56   pcf_cmap_init( PCF_CMap  cmap )
57   {
58     PCF_Face  face = (PCF_Face)FT_CMAP_FACE( cmap );
59 
60 
61     cmap->num_encodings = (FT_UInt)face->nencodings;
62     cmap->encodings     = face->encodings;
63 
64     return FT_Err_Ok;
65   }
66 
67 
68   FT_CALLBACK_DEF( void )
pcf_cmap_done(PCF_CMap cmap)69   pcf_cmap_done( PCF_CMap  cmap )
70   {
71     cmap->encodings     = NULL;
72     cmap->num_encodings = 0;
73   }
74 
75 
76   FT_CALLBACK_DEF( FT_UInt )
pcf_cmap_char_index(PCF_CMap cmap,FT_UInt32 charcode)77   pcf_cmap_char_index( PCF_CMap   cmap,
78                        FT_UInt32  charcode )
79   {
80     PCF_Encoding  encodings = cmap->encodings;
81     FT_UInt       min, max, mid;
82     FT_UInt       result = 0;
83 
84 
85     min = 0;
86     max = cmap->num_encodings;
87 
88     while ( min < max )
89     {
90       FT_UInt32  code;
91 
92 
93       mid  = ( min + max ) >> 1;
94       code = encodings[mid].enc;
95 
96       if ( charcode == code )
97       {
98         result = encodings[mid].glyph + 1;
99         break;
100       }
101 
102       if ( charcode < code )
103         max = mid;
104       else
105         min = mid + 1;
106     }
107 
108     return result;
109   }
110 
111 
112   FT_CALLBACK_DEF( FT_UInt )
pcf_cmap_char_next(PCF_CMap cmap,FT_UInt32 * acharcode)113   pcf_cmap_char_next( PCF_CMap    cmap,
114                       FT_UInt32  *acharcode )
115   {
116     PCF_Encoding  encodings = cmap->encodings;
117     FT_UInt       min, max, mid;
118     FT_UInt32     charcode = *acharcode + 1;
119     FT_UInt       result   = 0;
120 
121 
122     min = 0;
123     max = cmap->num_encodings;
124 
125     while ( min < max )
126     {
127       FT_UInt32  code;
128 
129 
130       mid  = ( min + max ) >> 1;
131       code = encodings[mid].enc;
132 
133       if ( charcode == code )
134       {
135         result = encodings[mid].glyph + 1;
136         goto Exit;
137       }
138 
139       if ( charcode < code )
140         max = mid;
141       else
142         min = mid + 1;
143     }
144 
145     charcode = 0;
146     if ( min < cmap->num_encodings )
147     {
148       charcode = encodings[min].enc;
149       result   = encodings[min].glyph + 1;
150     }
151 
152   Exit:
153     *acharcode = charcode;
154     return result;
155   }
156 
157 
158   FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec  pcf_cmap_class =
159   {
160     sizeof( PCF_CMapRec ),
161     (FT_CMap_InitFunc)     pcf_cmap_init,
162     (FT_CMap_DoneFunc)     pcf_cmap_done,
163     (FT_CMap_CharIndexFunc)pcf_cmap_char_index,
164     (FT_CMap_CharNextFunc) pcf_cmap_char_next
165   };
166 
167 
168   /*************************************************************************/
169   /*                                                                       */
170   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
171   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
172   /* messages during execution.                                            */
173   /*                                                                       */
174 #undef  FT_COMPONENT
175 #define FT_COMPONENT  trace_pcfdriver
176 
177 
178   FT_CALLBACK_DEF( FT_Error )
PCF_Face_Done(PCF_Face face)179   PCF_Face_Done( PCF_Face  face )
180   {
181     FT_Memory  memory = FT_FACE_MEMORY( face );
182 
183 
184     FT_FREE( face->encodings );
185     FT_FREE( face->metrics );
186 
187     /* free properties */
188     {
189       PCF_Property  prop = face->properties;
190       FT_Int        i;
191 
192 
193       for ( i = 0; i < face->nprops; i++ )
194       {
195         prop = &face->properties[i];
196 
197         FT_FREE( prop->name );
198         if ( prop->isString )
199           FT_FREE( prop->value );
200       }
201 
202       FT_FREE( face->properties );
203     }
204 
205     FT_FREE( face->toc.tables );
206     FT_FREE( face->root.family_name );
207     FT_FREE( face->root.available_sizes );
208     FT_FREE( face->charset_encoding );
209     FT_FREE( face->charset_registry );
210 
211     FT_TRACE4(( "PCF_Face_Done: done face\n" ));
212 
213     /* close gzip stream if any */
214     if ( face->root.stream == &face->gzip_stream )
215     {
216       FT_Stream_Close( &face->gzip_stream );
217       face->root.stream = face->gzip_source;
218     }
219 
220     return PCF_Err_Ok;
221   }
222 
223 
224   FT_CALLBACK_DEF( FT_Error )
PCF_Face_Init(FT_Stream stream,PCF_Face face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)225   PCF_Face_Init( FT_Stream      stream,
226                  PCF_Face       face,
227                  FT_Int         face_index,
228                  FT_Int         num_params,
229                  FT_Parameter*  params )
230   {
231     FT_Error  error = PCF_Err_Ok;
232 
233     FT_UNUSED( num_params );
234     FT_UNUSED( params );
235     FT_UNUSED( face_index );
236 
237 
238     error = pcf_load_font( stream, face );
239     if ( error )
240     {
241       FT_Error  error2;
242 
243       /* this didn't work, try gzip support !! */
244       error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream );
245       if ( error2 == FT_Err_Unimplemented_Feature )
246         goto Fail;
247 
248       error = error2;
249       if ( error )
250         goto Fail;
251 
252       face->gzip_source = stream;
253       face->root.stream = &face->gzip_stream;
254 
255       stream = face->root.stream;
256 
257       error = pcf_load_font( stream, face );
258       if ( error )
259         goto Fail;
260     }
261 
262     /* set-up charmap */
263     {
264       FT_String  *charset_registry, *charset_encoding;
265       FT_Bool     unicode_charmap  = 0;
266 
267 
268       charset_registry = face->charset_registry;
269       charset_encoding = face->charset_encoding;
270 
271       if ( ( charset_registry != NULL ) &&
272            ( charset_encoding != NULL ) )
273       {
274         if ( !ft_strcmp( face->charset_registry, "ISO10646" )     ||
275              ( !ft_strcmp( face->charset_registry, "ISO8859" ) &&
276                !ft_strcmp( face->charset_encoding, "1" )       )  )
277           unicode_charmap = 1;
278       }
279 
280       {
281         FT_CharMapRec  charmap;
282 
283 
284         charmap.face        = FT_FACE( face );
285         charmap.encoding    = FT_ENCODING_NONE;
286         charmap.platform_id = 0;
287         charmap.encoding_id = 0;
288 
289         if ( unicode_charmap )
290         {
291           charmap.encoding    = FT_ENCODING_UNICODE;
292           charmap.platform_id = 3;
293           charmap.encoding_id = 1;
294         }
295 
296         error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
297 
298 #if 0
299         /* Select default charmap */
300         if (face->root.num_charmaps)
301           face->root.charmap = face->root.charmaps[0];
302 #endif
303       }
304     }
305 
306   Exit:
307     return error;
308 
309   Fail:
310     FT_TRACE2(( "[not a valid PCF file]\n" ));
311     error = PCF_Err_Unknown_File_Format;  /* error */
312     goto Exit;
313   }
314 
315 
316   static FT_Error
PCF_Set_Pixel_Size(FT_Size size)317   PCF_Set_Pixel_Size( FT_Size  size )
318   {
319     PCF_Face face = (PCF_Face)FT_SIZE_FACE( size );
320 
321 
322     FT_TRACE4(( "rec %d - pres %d\n", size->metrics.y_ppem,
323                                       face->root.available_sizes->height ));
324 
325     if ( size->metrics.y_ppem == face->root.available_sizes->height )
326     {
327       size->metrics.ascender    = face->accel.fontAscent << 6;
328       size->metrics.descender   = face->accel.fontDescent * (-64);
329 #if 0
330       size->metrics.height      = face->accel.maxbounds.ascent << 6;
331 #endif
332       size->metrics.height      = size->metrics.ascender -
333                                   size->metrics.descender;
334 
335       size->metrics.max_advance = face->accel.maxbounds.characterWidth << 6;
336 
337       return PCF_Err_Ok;
338     }
339     else
340     {
341       FT_TRACE4(( "size WRONG\n" ));
342       return PCF_Err_Invalid_Pixel_Size;
343     }
344   }
345 
346 
347   static FT_Error
PCF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)348   PCF_Glyph_Load( FT_GlyphSlot  slot,
349                   FT_Size       size,
350                   FT_UInt       glyph_index,
351                   FT_Int32      load_flags )
352   {
353     PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
354     FT_Stream   stream = face->root.stream;
355     FT_Error    error  = PCF_Err_Ok;
356     FT_Memory   memory = FT_FACE( face )->memory;
357     FT_Bitmap*  bitmap = &slot->bitmap;
358     PCF_Metric  metric;
359     int         bytes;
360 
361     FT_UNUSED( load_flags );
362 
363 
364     FT_TRACE4(( "load_glyph %d ---", glyph_index ));
365 
366     if ( !face )
367     {
368       error = PCF_Err_Invalid_Argument;
369       goto Exit;
370     }
371 
372     if ( glyph_index > 0 )
373       glyph_index--;
374 
375     metric = face->metrics + glyph_index;
376 
377     bitmap->rows       = metric->ascent + metric->descent;
378     bitmap->width      = metric->rightSideBearing - metric->leftSideBearing;
379     bitmap->num_grays  = 1;
380     bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
381 
382     FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
383                   PCF_BIT_ORDER( face->bitmapsFormat ),
384                   PCF_BYTE_ORDER( face->bitmapsFormat ),
385                   PCF_GLYPH_PAD( face->bitmapsFormat ) ));
386 
387     switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
388     {
389     case 1:
390       bitmap->pitch = ( bitmap->width + 7 ) >> 3;
391       break;
392 
393     case 2:
394       bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
395       break;
396 
397     case 4:
398       bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
399       break;
400 
401     case 8:
402       bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
403       break;
404 
405     default:
406       return PCF_Err_Invalid_File_Format;
407     }
408 
409     /* XXX: to do: are there cases that need repadding the bitmap? */
410     bytes = bitmap->pitch * bitmap->rows;
411 
412     if ( FT_ALLOC( bitmap->buffer, bytes ) )
413       goto Exit;
414 
415     if ( FT_STREAM_SEEK( metric->bits )          ||
416          FT_STREAM_READ( bitmap->buffer, bytes ) )
417       goto Exit;
418 
419     if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
420       BitOrderInvert( bitmap->buffer, bytes );
421 
422     if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
423            PCF_BIT_ORDER( face->bitmapsFormat )  ) )
424     {
425       switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
426       {
427       case 1:
428         break;
429 
430       case 2:
431         TwoByteSwap( bitmap->buffer, bytes );
432         break;
433 
434       case 4:
435         FourByteSwap( bitmap->buffer, bytes );
436         break;
437       }
438     }
439 
440     slot->bitmap_left = metric->leftSideBearing;
441     slot->bitmap_top  = metric->ascent;
442 
443     slot->metrics.horiAdvance  = metric->characterWidth << 6 ;
444     slot->metrics.horiBearingX = metric->leftSideBearing << 6 ;
445     slot->metrics.horiBearingY = metric->ascent << 6 ;
446     slot->metrics.width        = ( metric->rightSideBearing -
447                                    metric->leftSideBearing ) << 6;
448     slot->metrics.height       = bitmap->rows << 6;
449 
450     slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16;
451     slot->format            = FT_GLYPH_FORMAT_BITMAP;
452     slot->flags             = FT_GLYPH_OWN_BITMAP;
453 
454     FT_TRACE4(( " --- ok\n" ));
455 
456   Exit:
457     return error;
458   }
459 
460 
461   FT_CALLBACK_TABLE_DEF
462   const FT_Driver_ClassRec  pcf_driver_class =
463   {
464     {
465       ft_module_font_driver,
466       sizeof ( FT_DriverRec ),
467 
468       "pcf",
469       0x10000L,
470       0x20000L,
471 
472       0,
473 
474       (FT_Module_Constructor)0,
475       (FT_Module_Destructor) 0,
476       (FT_Module_Requester)  0
477     },
478 
479     sizeof( PCF_FaceRec ),
480     sizeof( FT_SizeRec ),
481     sizeof( FT_GlyphSlotRec ),
482 
483     (FT_Face_InitFunc)        PCF_Face_Init,
484     (FT_Face_DoneFunc)        PCF_Face_Done,
485     (FT_Size_InitFunc)        0,
486     (FT_Size_DoneFunc)        0,
487     (FT_Slot_InitFunc)        0,
488     (FT_Slot_DoneFunc)        0,
489 
490     (FT_Size_ResetPointsFunc) PCF_Set_Pixel_Size,
491     (FT_Size_ResetPixelsFunc) PCF_Set_Pixel_Size,
492 
493     (FT_Slot_LoadFunc)        PCF_Glyph_Load,
494 
495     (FT_Face_GetKerningFunc)  0,
496     (FT_Face_AttachFunc)      0,
497     (FT_Face_GetAdvancesFunc) 0
498   };
499 
500 
501 /* END */
502