xref: /inferno-os/libfreetype/pfrsbit.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  pfrsbit.c                                                              */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    FreeType PFR bitmap loader (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 "pfrsbit.h"
20*37da2899SCharles.Forsyth #include "pfrload.h"
21*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
22*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth #include "pfrerror.h"
25*37da2899SCharles.Forsyth 
26*37da2899SCharles.Forsyth #undef  FT_COMPONENT
27*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_pfr
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth   /*************************************************************************/
31*37da2899SCharles.Forsyth   /*************************************************************************/
32*37da2899SCharles.Forsyth   /*****                                                               *****/
33*37da2899SCharles.Forsyth   /*****                      PFR BIT WRITER                           *****/
34*37da2899SCharles.Forsyth   /*****                                                               *****/
35*37da2899SCharles.Forsyth   /*************************************************************************/
36*37da2899SCharles.Forsyth   /*************************************************************************/
37*37da2899SCharles.Forsyth 
38*37da2899SCharles.Forsyth   typedef struct  PFR_BitWriter_
39*37da2899SCharles.Forsyth   {
40*37da2899SCharles.Forsyth     FT_Byte*  line;      /* current line start                    */
41*37da2899SCharles.Forsyth     FT_Int    pitch;     /* line size in bytes                    */
42*37da2899SCharles.Forsyth     FT_Int    width;     /* width in pixels/bits                  */
43*37da2899SCharles.Forsyth     FT_Int    rows;      /* number of remaining rows to scan      */
44*37da2899SCharles.Forsyth     FT_Int    total;     /* total number of bits to draw          */
45*37da2899SCharles.Forsyth 
46*37da2899SCharles.Forsyth   } PFR_BitWriterRec, *PFR_BitWriter;
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth   static void
pfr_bitwriter_init(PFR_BitWriter writer,FT_Bitmap * target,FT_Bool decreasing)50*37da2899SCharles.Forsyth   pfr_bitwriter_init( PFR_BitWriter  writer,
51*37da2899SCharles.Forsyth                       FT_Bitmap*     target,
52*37da2899SCharles.Forsyth                       FT_Bool        decreasing )
53*37da2899SCharles.Forsyth   {
54*37da2899SCharles.Forsyth     writer->line   = target->buffer;
55*37da2899SCharles.Forsyth     writer->pitch  = target->pitch;
56*37da2899SCharles.Forsyth     writer->width  = target->width;
57*37da2899SCharles.Forsyth     writer->rows   = target->rows;
58*37da2899SCharles.Forsyth     writer->total  = writer->width * writer->rows;
59*37da2899SCharles.Forsyth 
60*37da2899SCharles.Forsyth     if ( !decreasing )
61*37da2899SCharles.Forsyth     {
62*37da2899SCharles.Forsyth       writer->line += writer->pitch * ( target->rows-1 );
63*37da2899SCharles.Forsyth       writer->pitch = -writer->pitch;
64*37da2899SCharles.Forsyth     }
65*37da2899SCharles.Forsyth   }
66*37da2899SCharles.Forsyth 
67*37da2899SCharles.Forsyth 
68*37da2899SCharles.Forsyth   static void
pfr_bitwriter_decode_bytes(PFR_BitWriter writer,FT_Byte * p,FT_Byte * limit)69*37da2899SCharles.Forsyth   pfr_bitwriter_decode_bytes( PFR_BitWriter  writer,
70*37da2899SCharles.Forsyth                               FT_Byte*       p,
71*37da2899SCharles.Forsyth                               FT_Byte*       limit )
72*37da2899SCharles.Forsyth   {
73*37da2899SCharles.Forsyth     FT_Int    n, reload;
74*37da2899SCharles.Forsyth     FT_Int    left = writer->width;
75*37da2899SCharles.Forsyth     FT_Byte*  cur  = writer->line;
76*37da2899SCharles.Forsyth     FT_UInt   mask = 0x80;
77*37da2899SCharles.Forsyth     FT_UInt   val  = 0;
78*37da2899SCharles.Forsyth     FT_UInt   c    = 0;
79*37da2899SCharles.Forsyth 
80*37da2899SCharles.Forsyth 
81*37da2899SCharles.Forsyth     n = (FT_Int)( limit - p ) * 8;
82*37da2899SCharles.Forsyth     if ( n > writer->total )
83*37da2899SCharles.Forsyth       n = writer->total;
84*37da2899SCharles.Forsyth 
85*37da2899SCharles.Forsyth     reload = n & 7;
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth     for ( ; n > 0; n-- )
88*37da2899SCharles.Forsyth     {
89*37da2899SCharles.Forsyth       if ( ( n & 7 ) == reload )
90*37da2899SCharles.Forsyth         val = *p++;
91*37da2899SCharles.Forsyth 
92*37da2899SCharles.Forsyth       if ( val & 0x80 )
93*37da2899SCharles.Forsyth         c |= mask;
94*37da2899SCharles.Forsyth 
95*37da2899SCharles.Forsyth       val  <<= 1;
96*37da2899SCharles.Forsyth       mask >>= 1;
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth       if ( --left <= 0 )
99*37da2899SCharles.Forsyth       {
100*37da2899SCharles.Forsyth         cur[0] = (FT_Byte)c;
101*37da2899SCharles.Forsyth         left   = writer->width;
102*37da2899SCharles.Forsyth         mask   = 0x80;
103*37da2899SCharles.Forsyth 
104*37da2899SCharles.Forsyth         writer->line += writer->pitch;
105*37da2899SCharles.Forsyth         cur           = writer->line;
106*37da2899SCharles.Forsyth         c             = 0;
107*37da2899SCharles.Forsyth       }
108*37da2899SCharles.Forsyth       else if ( mask == 0 )
109*37da2899SCharles.Forsyth       {
110*37da2899SCharles.Forsyth         cur[0] = c;
111*37da2899SCharles.Forsyth         mask   = 0x80;
112*37da2899SCharles.Forsyth         c      = 0;
113*37da2899SCharles.Forsyth         cur ++;
114*37da2899SCharles.Forsyth       }
115*37da2899SCharles.Forsyth     }
116*37da2899SCharles.Forsyth 
117*37da2899SCharles.Forsyth     if ( mask != 0x80 )
118*37da2899SCharles.Forsyth       cur[0] = c;
119*37da2899SCharles.Forsyth   }
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth 
122*37da2899SCharles.Forsyth   static void
pfr_bitwriter_decode_rle1(PFR_BitWriter writer,FT_Byte * p,FT_Byte * limit)123*37da2899SCharles.Forsyth   pfr_bitwriter_decode_rle1( PFR_BitWriter  writer,
124*37da2899SCharles.Forsyth                              FT_Byte*       p,
125*37da2899SCharles.Forsyth                              FT_Byte*       limit )
126*37da2899SCharles.Forsyth   {
127*37da2899SCharles.Forsyth     FT_Int    n, phase, count, counts[2], reload;
128*37da2899SCharles.Forsyth     FT_Int    left = writer->width;
129*37da2899SCharles.Forsyth     FT_Byte*  cur  = writer->line;
130*37da2899SCharles.Forsyth     FT_UInt   mask = 0x80;
131*37da2899SCharles.Forsyth     FT_UInt   c    = 0;
132*37da2899SCharles.Forsyth 
133*37da2899SCharles.Forsyth 
134*37da2899SCharles.Forsyth     n = writer->total;
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth     phase     = 1;
137*37da2899SCharles.Forsyth     counts[0] = 0;
138*37da2899SCharles.Forsyth     counts[1] = 0;
139*37da2899SCharles.Forsyth     count     = 0;
140*37da2899SCharles.Forsyth     reload    = 1;
141*37da2899SCharles.Forsyth 
142*37da2899SCharles.Forsyth     for ( ; n > 0; n-- )
143*37da2899SCharles.Forsyth     {
144*37da2899SCharles.Forsyth       if ( reload )
145*37da2899SCharles.Forsyth       {
146*37da2899SCharles.Forsyth         do
147*37da2899SCharles.Forsyth         {
148*37da2899SCharles.Forsyth           if ( phase )
149*37da2899SCharles.Forsyth           {
150*37da2899SCharles.Forsyth             FT_Int  v;
151*37da2899SCharles.Forsyth 
152*37da2899SCharles.Forsyth 
153*37da2899SCharles.Forsyth             if ( p >= limit )
154*37da2899SCharles.Forsyth               break;
155*37da2899SCharles.Forsyth 
156*37da2899SCharles.Forsyth             v         = *p++;
157*37da2899SCharles.Forsyth             counts[0] = v >> 4;
158*37da2899SCharles.Forsyth             counts[1] = v & 15;
159*37da2899SCharles.Forsyth             phase     = 0;
160*37da2899SCharles.Forsyth             count     = counts[0];
161*37da2899SCharles.Forsyth           }
162*37da2899SCharles.Forsyth           else
163*37da2899SCharles.Forsyth           {
164*37da2899SCharles.Forsyth             phase = 1;
165*37da2899SCharles.Forsyth             count = counts[1];
166*37da2899SCharles.Forsyth           }
167*37da2899SCharles.Forsyth 
168*37da2899SCharles.Forsyth         } while ( count == 0 );
169*37da2899SCharles.Forsyth       }
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth       if ( phase )
172*37da2899SCharles.Forsyth         c |= mask;
173*37da2899SCharles.Forsyth 
174*37da2899SCharles.Forsyth       mask >>= 1;
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth       if ( --left <= 0 )
177*37da2899SCharles.Forsyth       {
178*37da2899SCharles.Forsyth         cur[0] = (FT_Byte) c;
179*37da2899SCharles.Forsyth         left   = writer->width;
180*37da2899SCharles.Forsyth         mask   = 0x80;
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth         writer->line += writer->pitch;
183*37da2899SCharles.Forsyth         cur           = writer->line;
184*37da2899SCharles.Forsyth         c             = 0;
185*37da2899SCharles.Forsyth       }
186*37da2899SCharles.Forsyth       else if ( mask == 0 )
187*37da2899SCharles.Forsyth       {
188*37da2899SCharles.Forsyth         cur[0] = c;
189*37da2899SCharles.Forsyth         mask   = 0x80;
190*37da2899SCharles.Forsyth         c      = 0;
191*37da2899SCharles.Forsyth         cur ++;
192*37da2899SCharles.Forsyth       }
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth       reload = ( --count <= 0 );
195*37da2899SCharles.Forsyth     }
196*37da2899SCharles.Forsyth 
197*37da2899SCharles.Forsyth     if ( mask != 0x80 )
198*37da2899SCharles.Forsyth       cur[0] = (FT_Byte) c;
199*37da2899SCharles.Forsyth   }
200*37da2899SCharles.Forsyth 
201*37da2899SCharles.Forsyth 
202*37da2899SCharles.Forsyth   static void
pfr_bitwriter_decode_rle2(PFR_BitWriter writer,FT_Byte * p,FT_Byte * limit)203*37da2899SCharles.Forsyth   pfr_bitwriter_decode_rle2( PFR_BitWriter  writer,
204*37da2899SCharles.Forsyth                              FT_Byte*       p,
205*37da2899SCharles.Forsyth                              FT_Byte*       limit )
206*37da2899SCharles.Forsyth   {
207*37da2899SCharles.Forsyth     FT_Int    n, phase, count, reload;
208*37da2899SCharles.Forsyth     FT_Int    left = writer->width;
209*37da2899SCharles.Forsyth     FT_Byte*  cur  = writer->line;
210*37da2899SCharles.Forsyth     FT_UInt   mask = 0x80;
211*37da2899SCharles.Forsyth     FT_UInt   c    = 0;
212*37da2899SCharles.Forsyth 
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth     n = writer->total;
215*37da2899SCharles.Forsyth 
216*37da2899SCharles.Forsyth     phase  = 1;
217*37da2899SCharles.Forsyth     count  = 0;
218*37da2899SCharles.Forsyth     reload = 1;
219*37da2899SCharles.Forsyth 
220*37da2899SCharles.Forsyth     for ( ; n > 0; n-- )
221*37da2899SCharles.Forsyth     {
222*37da2899SCharles.Forsyth       if ( reload )
223*37da2899SCharles.Forsyth       {
224*37da2899SCharles.Forsyth         do
225*37da2899SCharles.Forsyth         {
226*37da2899SCharles.Forsyth           if ( p >= limit )
227*37da2899SCharles.Forsyth             break;
228*37da2899SCharles.Forsyth 
229*37da2899SCharles.Forsyth           count = *p++;
230*37da2899SCharles.Forsyth           phase = phase ^ 1;
231*37da2899SCharles.Forsyth 
232*37da2899SCharles.Forsyth         } while ( count == 0 );
233*37da2899SCharles.Forsyth       }
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth       if ( phase )
236*37da2899SCharles.Forsyth         c |= mask;
237*37da2899SCharles.Forsyth 
238*37da2899SCharles.Forsyth       mask >>= 1;
239*37da2899SCharles.Forsyth 
240*37da2899SCharles.Forsyth       if ( --left <= 0 )
241*37da2899SCharles.Forsyth       {
242*37da2899SCharles.Forsyth         cur[0] = (FT_Byte) c;
243*37da2899SCharles.Forsyth         c      = 0;
244*37da2899SCharles.Forsyth         mask   = 0x80;
245*37da2899SCharles.Forsyth         left   = writer->width;
246*37da2899SCharles.Forsyth 
247*37da2899SCharles.Forsyth         writer->line += writer->pitch;
248*37da2899SCharles.Forsyth         cur           = writer->line;
249*37da2899SCharles.Forsyth       }
250*37da2899SCharles.Forsyth       else if ( mask == 0 )
251*37da2899SCharles.Forsyth       {
252*37da2899SCharles.Forsyth         cur[0] = c;
253*37da2899SCharles.Forsyth         c      = 0;
254*37da2899SCharles.Forsyth         mask   = 0x80;
255*37da2899SCharles.Forsyth         cur ++;
256*37da2899SCharles.Forsyth       }
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth       reload = ( --count <= 0 );
259*37da2899SCharles.Forsyth     }
260*37da2899SCharles.Forsyth 
261*37da2899SCharles.Forsyth     if ( mask != 0x80 )
262*37da2899SCharles.Forsyth       cur[0] = (FT_Byte) c;
263*37da2899SCharles.Forsyth   }
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth 
266*37da2899SCharles.Forsyth   /*************************************************************************/
267*37da2899SCharles.Forsyth   /*************************************************************************/
268*37da2899SCharles.Forsyth   /*****                                                               *****/
269*37da2899SCharles.Forsyth   /*****                  BITMAP DATA DECODING                         *****/
270*37da2899SCharles.Forsyth   /*****                                                               *****/
271*37da2899SCharles.Forsyth   /*************************************************************************/
272*37da2899SCharles.Forsyth   /*************************************************************************/
273*37da2899SCharles.Forsyth 
274*37da2899SCharles.Forsyth   static void
pfr_lookup_bitmap_data(FT_Byte * base,FT_Byte * limit,FT_Int count,FT_Byte flags,FT_UInt char_code,FT_ULong * found_offset,FT_ULong * found_size)275*37da2899SCharles.Forsyth   pfr_lookup_bitmap_data( FT_Byte*   base,
276*37da2899SCharles.Forsyth                           FT_Byte*   limit,
277*37da2899SCharles.Forsyth                           FT_Int     count,
278*37da2899SCharles.Forsyth                           FT_Byte    flags,
279*37da2899SCharles.Forsyth                           FT_UInt    char_code,
280*37da2899SCharles.Forsyth                           FT_ULong*  found_offset,
281*37da2899SCharles.Forsyth                           FT_ULong*  found_size )
282*37da2899SCharles.Forsyth   {
283*37da2899SCharles.Forsyth     FT_UInt   left, right, char_len;
284*37da2899SCharles.Forsyth     FT_Bool   two = flags & 1;
285*37da2899SCharles.Forsyth     FT_Byte*  buff;
286*37da2899SCharles.Forsyth 
287*37da2899SCharles.Forsyth 
288*37da2899SCharles.Forsyth     char_len = 4;
289*37da2899SCharles.Forsyth     if ( two )       char_len += 1;
290*37da2899SCharles.Forsyth     if ( flags & 2 ) char_len += 1;
291*37da2899SCharles.Forsyth     if ( flags & 4 ) char_len += 1;
292*37da2899SCharles.Forsyth 
293*37da2899SCharles.Forsyth     left  = 0;
294*37da2899SCharles.Forsyth     right = count;
295*37da2899SCharles.Forsyth 
296*37da2899SCharles.Forsyth     while ( left < right )
297*37da2899SCharles.Forsyth     {
298*37da2899SCharles.Forsyth       FT_UInt  middle, code;
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth 
301*37da2899SCharles.Forsyth       middle = ( left + right ) >> 1;
302*37da2899SCharles.Forsyth       buff   = base + middle * char_len;
303*37da2899SCharles.Forsyth 
304*37da2899SCharles.Forsyth       /* check that we are not outside of the table -- */
305*37da2899SCharles.Forsyth       /* this is possible with broken fonts...         */
306*37da2899SCharles.Forsyth       if ( buff + char_len > limit )
307*37da2899SCharles.Forsyth         goto Fail;
308*37da2899SCharles.Forsyth 
309*37da2899SCharles.Forsyth       if ( two )
310*37da2899SCharles.Forsyth         code = PFR_NEXT_USHORT( buff );
311*37da2899SCharles.Forsyth       else
312*37da2899SCharles.Forsyth         code = PFR_NEXT_BYTE( buff );
313*37da2899SCharles.Forsyth 
314*37da2899SCharles.Forsyth       if ( code == char_code )
315*37da2899SCharles.Forsyth         goto Found_It;
316*37da2899SCharles.Forsyth 
317*37da2899SCharles.Forsyth       if ( code < char_code )
318*37da2899SCharles.Forsyth         left = middle;
319*37da2899SCharles.Forsyth       else
320*37da2899SCharles.Forsyth         right = middle;
321*37da2899SCharles.Forsyth     }
322*37da2899SCharles.Forsyth 
323*37da2899SCharles.Forsyth   Fail:
324*37da2899SCharles.Forsyth     /* Not found */
325*37da2899SCharles.Forsyth     *found_size   = 0;
326*37da2899SCharles.Forsyth     *found_offset = 0;
327*37da2899SCharles.Forsyth     return;
328*37da2899SCharles.Forsyth 
329*37da2899SCharles.Forsyth   Found_It:
330*37da2899SCharles.Forsyth     if ( flags & 2 )
331*37da2899SCharles.Forsyth       *found_size = PFR_NEXT_USHORT( buff );
332*37da2899SCharles.Forsyth     else
333*37da2899SCharles.Forsyth       *found_size = PFR_NEXT_BYTE( buff );
334*37da2899SCharles.Forsyth 
335*37da2899SCharles.Forsyth     if ( flags & 4 )
336*37da2899SCharles.Forsyth       *found_offset = PFR_NEXT_ULONG( buff );
337*37da2899SCharles.Forsyth     else
338*37da2899SCharles.Forsyth       *found_offset = PFR_NEXT_USHORT( buff );
339*37da2899SCharles.Forsyth   }
340*37da2899SCharles.Forsyth 
341*37da2899SCharles.Forsyth 
342*37da2899SCharles.Forsyth   /* load bitmap metrics.  "*padvance" must be set to the default value */
343*37da2899SCharles.Forsyth   /* before calling this function...                                    */
344*37da2899SCharles.Forsyth   /*                                                                    */
345*37da2899SCharles.Forsyth   static FT_Error
pfr_load_bitmap_metrics(FT_Byte ** pdata,FT_Byte * limit,FT_Long scaled_advance,FT_Long * axpos,FT_Long * aypos,FT_UInt * axsize,FT_UInt * aysize,FT_Long * aadvance,FT_UInt * aformat)346*37da2899SCharles.Forsyth   pfr_load_bitmap_metrics( FT_Byte**  pdata,
347*37da2899SCharles.Forsyth                            FT_Byte*   limit,
348*37da2899SCharles.Forsyth                            FT_Long    scaled_advance,
349*37da2899SCharles.Forsyth                            FT_Long   *axpos,
350*37da2899SCharles.Forsyth                            FT_Long   *aypos,
351*37da2899SCharles.Forsyth                            FT_UInt   *axsize,
352*37da2899SCharles.Forsyth                            FT_UInt   *aysize,
353*37da2899SCharles.Forsyth                            FT_Long   *aadvance,
354*37da2899SCharles.Forsyth                            FT_UInt   *aformat )
355*37da2899SCharles.Forsyth   {
356*37da2899SCharles.Forsyth     FT_Error  error = 0;
357*37da2899SCharles.Forsyth     FT_Byte   flags;
358*37da2899SCharles.Forsyth     FT_Char   b;
359*37da2899SCharles.Forsyth     FT_Byte*  p = *pdata;
360*37da2899SCharles.Forsyth     FT_Long   xpos, ypos, advance;
361*37da2899SCharles.Forsyth     FT_UInt   xsize, ysize;
362*37da2899SCharles.Forsyth 
363*37da2899SCharles.Forsyth 
364*37da2899SCharles.Forsyth     PFR_CHECK( 1 );
365*37da2899SCharles.Forsyth     flags = PFR_NEXT_BYTE( p );
366*37da2899SCharles.Forsyth 
367*37da2899SCharles.Forsyth     xpos    = 0;
368*37da2899SCharles.Forsyth     ypos    = 0;
369*37da2899SCharles.Forsyth     xsize   = 0;
370*37da2899SCharles.Forsyth     ysize   = 0;
371*37da2899SCharles.Forsyth     advance = 0;
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth     switch ( flags & 3 )
374*37da2899SCharles.Forsyth     {
375*37da2899SCharles.Forsyth     case 0:
376*37da2899SCharles.Forsyth       PFR_CHECK( 1 );
377*37da2899SCharles.Forsyth       b    = PFR_NEXT_INT8( p );
378*37da2899SCharles.Forsyth       xpos = b >> 4;
379*37da2899SCharles.Forsyth       ypos = ( (FT_Char)( b << 4 ) ) >> 4;
380*37da2899SCharles.Forsyth       break;
381*37da2899SCharles.Forsyth 
382*37da2899SCharles.Forsyth     case 1:
383*37da2899SCharles.Forsyth       PFR_CHECK( 2 );
384*37da2899SCharles.Forsyth       xpos = PFR_NEXT_INT8( p );
385*37da2899SCharles.Forsyth       ypos = PFR_NEXT_INT8( p );
386*37da2899SCharles.Forsyth       break;
387*37da2899SCharles.Forsyth 
388*37da2899SCharles.Forsyth     case 2:
389*37da2899SCharles.Forsyth       PFR_CHECK( 4 );
390*37da2899SCharles.Forsyth       xpos = PFR_NEXT_SHORT( p );
391*37da2899SCharles.Forsyth       ypos = PFR_NEXT_SHORT( p );
392*37da2899SCharles.Forsyth       break;
393*37da2899SCharles.Forsyth 
394*37da2899SCharles.Forsyth     case 3:
395*37da2899SCharles.Forsyth       PFR_CHECK( 6 );
396*37da2899SCharles.Forsyth       xpos = PFR_NEXT_LONG( p );
397*37da2899SCharles.Forsyth       ypos = PFR_NEXT_LONG( p );
398*37da2899SCharles.Forsyth       break;
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth     default:
401*37da2899SCharles.Forsyth       ;
402*37da2899SCharles.Forsyth     }
403*37da2899SCharles.Forsyth 
404*37da2899SCharles.Forsyth     flags >>= 2;
405*37da2899SCharles.Forsyth     switch ( flags & 3 )
406*37da2899SCharles.Forsyth     {
407*37da2899SCharles.Forsyth     case 0:
408*37da2899SCharles.Forsyth       /* blank image */
409*37da2899SCharles.Forsyth       xsize = 0;
410*37da2899SCharles.Forsyth       ysize = 0;
411*37da2899SCharles.Forsyth       break;
412*37da2899SCharles.Forsyth 
413*37da2899SCharles.Forsyth     case 1:
414*37da2899SCharles.Forsyth       PFR_CHECK( 1 );
415*37da2899SCharles.Forsyth       b     = PFR_NEXT_BYTE( p );
416*37da2899SCharles.Forsyth       xsize = ( b >> 4 ) & 0xF;
417*37da2899SCharles.Forsyth       ysize = b & 0xF;
418*37da2899SCharles.Forsyth       break;
419*37da2899SCharles.Forsyth 
420*37da2899SCharles.Forsyth     case 2:
421*37da2899SCharles.Forsyth       PFR_CHECK( 2 );
422*37da2899SCharles.Forsyth       xsize = PFR_NEXT_BYTE( p );
423*37da2899SCharles.Forsyth       ysize = PFR_NEXT_BYTE( p );
424*37da2899SCharles.Forsyth       break;
425*37da2899SCharles.Forsyth 
426*37da2899SCharles.Forsyth     case 3:
427*37da2899SCharles.Forsyth       PFR_CHECK( 4 );
428*37da2899SCharles.Forsyth       xsize = PFR_NEXT_USHORT( p );
429*37da2899SCharles.Forsyth       ysize = PFR_NEXT_USHORT( p );
430*37da2899SCharles.Forsyth       break;
431*37da2899SCharles.Forsyth 
432*37da2899SCharles.Forsyth     default:
433*37da2899SCharles.Forsyth       ;
434*37da2899SCharles.Forsyth     }
435*37da2899SCharles.Forsyth 
436*37da2899SCharles.Forsyth     flags >>= 2;
437*37da2899SCharles.Forsyth     switch ( flags & 3 )
438*37da2899SCharles.Forsyth     {
439*37da2899SCharles.Forsyth     case 0:
440*37da2899SCharles.Forsyth       advance = scaled_advance;
441*37da2899SCharles.Forsyth       break;
442*37da2899SCharles.Forsyth 
443*37da2899SCharles.Forsyth     case 1:
444*37da2899SCharles.Forsyth       PFR_CHECK( 1 );
445*37da2899SCharles.Forsyth       advance = PFR_NEXT_INT8( p ) << 8;
446*37da2899SCharles.Forsyth       break;
447*37da2899SCharles.Forsyth 
448*37da2899SCharles.Forsyth     case 2:
449*37da2899SCharles.Forsyth       PFR_CHECK( 2 );
450*37da2899SCharles.Forsyth       advance = PFR_NEXT_SHORT( p );
451*37da2899SCharles.Forsyth       break;
452*37da2899SCharles.Forsyth 
453*37da2899SCharles.Forsyth     case 3:
454*37da2899SCharles.Forsyth       PFR_CHECK( 3 );
455*37da2899SCharles.Forsyth       advance = PFR_NEXT_LONG( p );
456*37da2899SCharles.Forsyth       break;
457*37da2899SCharles.Forsyth 
458*37da2899SCharles.Forsyth     default:
459*37da2899SCharles.Forsyth       ;
460*37da2899SCharles.Forsyth     }
461*37da2899SCharles.Forsyth 
462*37da2899SCharles.Forsyth     *axpos    = xpos;
463*37da2899SCharles.Forsyth     *aypos    = ypos;
464*37da2899SCharles.Forsyth     *axsize   = xsize;
465*37da2899SCharles.Forsyth     *aysize   = ysize;
466*37da2899SCharles.Forsyth     *aadvance = advance;
467*37da2899SCharles.Forsyth     *aformat  = flags >> 2;
468*37da2899SCharles.Forsyth     *pdata    = p;
469*37da2899SCharles.Forsyth 
470*37da2899SCharles.Forsyth   Exit:
471*37da2899SCharles.Forsyth     return error;
472*37da2899SCharles.Forsyth 
473*37da2899SCharles.Forsyth   Too_Short:
474*37da2899SCharles.Forsyth     error = PFR_Err_Invalid_Table;
475*37da2899SCharles.Forsyth     FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
476*37da2899SCharles.Forsyth     goto Exit;
477*37da2899SCharles.Forsyth   }
478*37da2899SCharles.Forsyth 
479*37da2899SCharles.Forsyth 
480*37da2899SCharles.Forsyth   static FT_Error
pfr_load_bitmap_bits(FT_Byte * p,FT_Byte * limit,FT_UInt format,FT_UInt decreasing,FT_Bitmap * target)481*37da2899SCharles.Forsyth   pfr_load_bitmap_bits( FT_Byte*    p,
482*37da2899SCharles.Forsyth                         FT_Byte*    limit,
483*37da2899SCharles.Forsyth                         FT_UInt     format,
484*37da2899SCharles.Forsyth                         FT_UInt     decreasing,
485*37da2899SCharles.Forsyth                         FT_Bitmap*  target )
486*37da2899SCharles.Forsyth   {
487*37da2899SCharles.Forsyth     FT_Error          error = 0;
488*37da2899SCharles.Forsyth     PFR_BitWriterRec  writer;
489*37da2899SCharles.Forsyth 
490*37da2899SCharles.Forsyth 
491*37da2899SCharles.Forsyth     if ( target->rows > 0 && target->width > 0 )
492*37da2899SCharles.Forsyth     {
493*37da2899SCharles.Forsyth       pfr_bitwriter_init( &writer, target, decreasing );
494*37da2899SCharles.Forsyth 
495*37da2899SCharles.Forsyth       switch ( format )
496*37da2899SCharles.Forsyth       {
497*37da2899SCharles.Forsyth       case 0: /* packed bits */
498*37da2899SCharles.Forsyth         pfr_bitwriter_decode_bytes( &writer, p, limit );
499*37da2899SCharles.Forsyth         break;
500*37da2899SCharles.Forsyth 
501*37da2899SCharles.Forsyth       case 1: /* RLE1 */
502*37da2899SCharles.Forsyth         pfr_bitwriter_decode_rle1( &writer, p, limit );
503*37da2899SCharles.Forsyth         break;
504*37da2899SCharles.Forsyth 
505*37da2899SCharles.Forsyth       case 2: /* RLE2 */
506*37da2899SCharles.Forsyth         pfr_bitwriter_decode_rle2( &writer, p, limit );
507*37da2899SCharles.Forsyth         break;
508*37da2899SCharles.Forsyth 
509*37da2899SCharles.Forsyth       default:
510*37da2899SCharles.Forsyth         FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));
511*37da2899SCharles.Forsyth         error = FT_Err_Invalid_File_Format;
512*37da2899SCharles.Forsyth       }
513*37da2899SCharles.Forsyth     }
514*37da2899SCharles.Forsyth 
515*37da2899SCharles.Forsyth     return error;
516*37da2899SCharles.Forsyth   }
517*37da2899SCharles.Forsyth 
518*37da2899SCharles.Forsyth 
519*37da2899SCharles.Forsyth   /*************************************************************************/
520*37da2899SCharles.Forsyth   /*************************************************************************/
521*37da2899SCharles.Forsyth   /*****                                                               *****/
522*37da2899SCharles.Forsyth   /*****                     BITMAP LOADING                            *****/
523*37da2899SCharles.Forsyth   /*****                                                               *****/
524*37da2899SCharles.Forsyth   /*************************************************************************/
525*37da2899SCharles.Forsyth   /*************************************************************************/
526*37da2899SCharles.Forsyth 
527*37da2899SCharles.Forsyth   FT_LOCAL( FT_Error )
pfr_slot_load_bitmap(PFR_Slot glyph,PFR_Size size,FT_UInt glyph_index)528*37da2899SCharles.Forsyth   pfr_slot_load_bitmap( PFR_Slot  glyph,
529*37da2899SCharles.Forsyth                         PFR_Size  size,
530*37da2899SCharles.Forsyth                         FT_UInt   glyph_index )
531*37da2899SCharles.Forsyth   {
532*37da2899SCharles.Forsyth     FT_Error     error;
533*37da2899SCharles.Forsyth     PFR_Face     face   = (PFR_Face) glyph->root.face;
534*37da2899SCharles.Forsyth     FT_Stream    stream = face->root.stream;
535*37da2899SCharles.Forsyth     PFR_PhyFont  phys   = &face->phy_font;
536*37da2899SCharles.Forsyth     FT_ULong     gps_offset;
537*37da2899SCharles.Forsyth     FT_ULong     gps_size;
538*37da2899SCharles.Forsyth     PFR_Char     character;
539*37da2899SCharles.Forsyth     PFR_Strike   strike;
540*37da2899SCharles.Forsyth 
541*37da2899SCharles.Forsyth 
542*37da2899SCharles.Forsyth     character = &phys->chars[glyph_index];
543*37da2899SCharles.Forsyth 
544*37da2899SCharles.Forsyth     /* Look-up a bitmap strike corresponding to the current */
545*37da2899SCharles.Forsyth     /* character dimensions                                 */
546*37da2899SCharles.Forsyth     {
547*37da2899SCharles.Forsyth       FT_UInt  n;
548*37da2899SCharles.Forsyth 
549*37da2899SCharles.Forsyth 
550*37da2899SCharles.Forsyth       strike = phys->strikes;
551*37da2899SCharles.Forsyth       for ( n = 0; n < phys->num_strikes; n++ )
552*37da2899SCharles.Forsyth       {
553*37da2899SCharles.Forsyth         if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
554*37da2899SCharles.Forsyth              strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
555*37da2899SCharles.Forsyth         {
556*37da2899SCharles.Forsyth           goto Found_Strike;
557*37da2899SCharles.Forsyth         }
558*37da2899SCharles.Forsyth 
559*37da2899SCharles.Forsyth         strike++;
560*37da2899SCharles.Forsyth       }
561*37da2899SCharles.Forsyth 
562*37da2899SCharles.Forsyth       /* couldn't find it */
563*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
564*37da2899SCharles.Forsyth     }
565*37da2899SCharles.Forsyth 
566*37da2899SCharles.Forsyth   Found_Strike:
567*37da2899SCharles.Forsyth 
568*37da2899SCharles.Forsyth     /* Now lookup the glyph's position within the file */
569*37da2899SCharles.Forsyth     {
570*37da2899SCharles.Forsyth       FT_UInt  char_len;
571*37da2899SCharles.Forsyth 
572*37da2899SCharles.Forsyth 
573*37da2899SCharles.Forsyth       char_len = 4;
574*37da2899SCharles.Forsyth       if ( strike->flags & 1 ) char_len += 1;
575*37da2899SCharles.Forsyth       if ( strike->flags & 2 ) char_len += 1;
576*37da2899SCharles.Forsyth       if ( strike->flags & 4 ) char_len += 1;
577*37da2899SCharles.Forsyth 
578*37da2899SCharles.Forsyth       /* Access data directly in the frame to speed lookups */
579*37da2899SCharles.Forsyth       if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
580*37da2899SCharles.Forsyth            FT_FRAME_ENTER( char_len * strike->num_bitmaps )        )
581*37da2899SCharles.Forsyth         goto Exit;
582*37da2899SCharles.Forsyth 
583*37da2899SCharles.Forsyth       pfr_lookup_bitmap_data( stream->cursor,
584*37da2899SCharles.Forsyth                               stream->limit,
585*37da2899SCharles.Forsyth                               strike->num_bitmaps,
586*37da2899SCharles.Forsyth                               strike->flags,
587*37da2899SCharles.Forsyth                               character->char_code,
588*37da2899SCharles.Forsyth                               &gps_offset,
589*37da2899SCharles.Forsyth                               &gps_size );
590*37da2899SCharles.Forsyth 
591*37da2899SCharles.Forsyth       FT_FRAME_EXIT();
592*37da2899SCharles.Forsyth 
593*37da2899SCharles.Forsyth       if ( gps_size == 0 )
594*37da2899SCharles.Forsyth       {
595*37da2899SCharles.Forsyth         /* Could not find a bitmap program string for this glyph */
596*37da2899SCharles.Forsyth         error = FT_Err_Invalid_Argument;
597*37da2899SCharles.Forsyth         goto Exit;
598*37da2899SCharles.Forsyth       }
599*37da2899SCharles.Forsyth     }
600*37da2899SCharles.Forsyth 
601*37da2899SCharles.Forsyth     /* get the bitmap metrics */
602*37da2899SCharles.Forsyth     {
603*37da2899SCharles.Forsyth       FT_Long   xpos, ypos, advance;
604*37da2899SCharles.Forsyth       FT_UInt   xsize, ysize, format;
605*37da2899SCharles.Forsyth       FT_Byte*  p;
606*37da2899SCharles.Forsyth 
607*37da2899SCharles.Forsyth 
608*37da2899SCharles.Forsyth       advance = FT_MulDiv( size->root.metrics.x_ppem << 8,
609*37da2899SCharles.Forsyth                            character->advance,
610*37da2899SCharles.Forsyth                            phys->metrics_resolution );
611*37da2899SCharles.Forsyth 
612*37da2899SCharles.Forsyth       /* XXX: handle linearHoriAdvance correctly! */
613*37da2899SCharles.Forsyth 
614*37da2899SCharles.Forsyth       if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
615*37da2899SCharles.Forsyth            FT_FRAME_ENTER( gps_size )                                     )
616*37da2899SCharles.Forsyth         goto Exit;
617*37da2899SCharles.Forsyth 
618*37da2899SCharles.Forsyth       p     = stream->cursor;
619*37da2899SCharles.Forsyth       error = pfr_load_bitmap_metrics( &p, stream->limit,
620*37da2899SCharles.Forsyth                                        advance,
621*37da2899SCharles.Forsyth                                        &xpos, &ypos,
622*37da2899SCharles.Forsyth                                        &xsize, &ysize,
623*37da2899SCharles.Forsyth                                        &advance, &format );
624*37da2899SCharles.Forsyth       if ( !error )
625*37da2899SCharles.Forsyth       {
626*37da2899SCharles.Forsyth         glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
627*37da2899SCharles.Forsyth 
628*37da2899SCharles.Forsyth         /* Set up glyph bitmap and metrics */
629*37da2899SCharles.Forsyth         glyph->root.bitmap.width      = (FT_Int)xsize;
630*37da2899SCharles.Forsyth         glyph->root.bitmap.rows       = (FT_Int)ysize;
631*37da2899SCharles.Forsyth         glyph->root.bitmap.pitch      = (FT_Long)( xsize + 7 ) >> 3;
632*37da2899SCharles.Forsyth         glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
633*37da2899SCharles.Forsyth 
634*37da2899SCharles.Forsyth         glyph->root.metrics.width        = (FT_Long)xsize << 6;
635*37da2899SCharles.Forsyth         glyph->root.metrics.height       = (FT_Long)ysize << 6;
636*37da2899SCharles.Forsyth         glyph->root.metrics.horiBearingX = xpos << 6;
637*37da2899SCharles.Forsyth         glyph->root.metrics.horiBearingY = ypos << 6;
638*37da2899SCharles.Forsyth         glyph->root.metrics.horiAdvance  = ( ( advance >> 2 ) + 32 ) & -64;
639*37da2899SCharles.Forsyth         glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
640*37da2899SCharles.Forsyth         glyph->root.metrics.vertBearingY = 0;
641*37da2899SCharles.Forsyth         glyph->root.metrics.vertAdvance  = size->root.metrics.height;
642*37da2899SCharles.Forsyth 
643*37da2899SCharles.Forsyth         glyph->root.bitmap_left = xpos;
644*37da2899SCharles.Forsyth         glyph->root.bitmap_top  = ypos + ysize;
645*37da2899SCharles.Forsyth 
646*37da2899SCharles.Forsyth         /* Allocate and read bitmap data */
647*37da2899SCharles.Forsyth         {
648*37da2899SCharles.Forsyth           FT_Memory  memory = face->root.memory;
649*37da2899SCharles.Forsyth           FT_Long    len    = glyph->root.bitmap.pitch * ysize;
650*37da2899SCharles.Forsyth 
651*37da2899SCharles.Forsyth 
652*37da2899SCharles.Forsyth           if ( !FT_ALLOC( glyph->root.bitmap.buffer, len ) )
653*37da2899SCharles.Forsyth           {
654*37da2899SCharles.Forsyth             error = pfr_load_bitmap_bits( p,
655*37da2899SCharles.Forsyth                                           stream->limit,
656*37da2899SCharles.Forsyth                                           format,
657*37da2899SCharles.Forsyth                                           face->header.color_flags & 2,
658*37da2899SCharles.Forsyth                                           &glyph->root.bitmap );
659*37da2899SCharles.Forsyth           }
660*37da2899SCharles.Forsyth         }
661*37da2899SCharles.Forsyth       }
662*37da2899SCharles.Forsyth 
663*37da2899SCharles.Forsyth       FT_FRAME_EXIT();
664*37da2899SCharles.Forsyth     }
665*37da2899SCharles.Forsyth 
666*37da2899SCharles.Forsyth   Exit:
667*37da2899SCharles.Forsyth     return error;
668*37da2899SCharles.Forsyth   }
669*37da2899SCharles.Forsyth 
670*37da2899SCharles.Forsyth /* END */
671