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