Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
pfrsbit.c
Go to the documentation of this file.
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 
47 
48 
49  static void
50  pfr_bitwriter_init( PFR_BitWriter writer,
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  {
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  {
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 )
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 || ( ypos + ysize ) > FT_INT_MAX )
640  {
641  FT_TRACE1(( "pfr_slot_load_bitmap:" ));
642  FT_TRACE1(( "huge bitmap glyph %dx%d over FT_GlyphSlot\n",
643  xpos, ypos ));
644  error = FT_THROW( Invalid_Pixel_Size );
645  }
646 
647  if ( !error )
648  {
649  glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
650 
651  /* Set up glyph bitmap and metrics */
652 
653  /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
654  glyph->root.bitmap.width = (FT_Int)xsize;
655  glyph->root.bitmap.rows = (FT_Int)ysize;
656  glyph->root.bitmap.pitch = (FT_Int)( xsize + 7 ) >> 3;
657  glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
658 
659  /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
660  glyph->root.metrics.width = (FT_Pos)xsize << 6;
661  glyph->root.metrics.height = (FT_Pos)ysize << 6;
662  glyph->root.metrics.horiBearingX = xpos << 6;
663  glyph->root.metrics.horiBearingY = ypos << 6;
664  glyph->root.metrics.horiAdvance = FT_PIX_ROUND( ( advance >> 2 ) );
665  glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
666  glyph->root.metrics.vertBearingY = 0;
667  glyph->root.metrics.vertAdvance = size->root.metrics.height;
668 
669  /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */
670  glyph->root.bitmap_left = (FT_Int)xpos;
671  glyph->root.bitmap_top = (FT_Int)(ypos + ysize);
672 
673  /* Allocate and read bitmap data */
674  {
675  FT_ULong len = glyph->root.bitmap.pitch * ysize;
676 
677 
678  error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
679  if ( !error )
680  {
681  error = pfr_load_bitmap_bits(
682  p,
683  stream->limit,
684  format,
685  FT_BOOL(face->header.color_flags & 2),
686  &glyph->root.bitmap );
687  }
688  }
689  }
690 
691  FT_FRAME_EXIT();
692  }
693 
694  Exit:
695  return error;
696  }
697 
698 /* END */
int FT_Error
Definition: fttypes.h:296
GLuint GLuint stream
for(n=1;n< outline->n_points;n++)
Definition: ftbbox.c:593
signed long FT_Long
Definition: fttypes.h:238
unsigned long FT_ULong
Definition: fttypes.h:249
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:59
#define PFR_CHECK(x)
Definition: pfrload.h:31
GLfloat GLfloat p
#define PFR_NEXT_LONG(p)
Definition: pfrload.h:42
signed int FT_Int
Definition: fttypes.h:216
int rows
Definition: ftimage.h:312
return FT_THROW(Missing_Property)
unsigned char * buffer
Definition: ftimage.h:315
pfr_slot_load_bitmap(PFR_Slot glyph, PFR_Size size, FT_UInt glyph_index)
Definition: pfrsbit.c:528
signed char FT_Char
Definition: fttypes.h:139
GLint GLint GLsizei width
int pitch
Definition: ftimage.h:314
return FT_Err_Ok
Definition: ftbbox.c:645
GLboolean GLboolean GLboolean b
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:104
#define FT_TRACE1(varformat)
Definition: ftdebug.h:158
GLenum GLuint GLint GLenum face
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
unsigned char FT_Byte
Definition: fttypes.h:150
GLdouble GLdouble right
#define FT_LOCAL(x)
Definition: ftconfig.h:235
GLenum GLint GLuint mask
GLenum GLsizei len
GLint left
FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
Definition: ftcalc.c:412
FT_Error error
Definition: cffdrivr.c:411
const GLdouble * v
ft_glyphslot_alloc_bitmap(FT_GlyphSlot slot, FT_ULong size)
Definition: ftobjs.c:306
GLbitfield flags
GLuint GLfloat * val
GLdouble n
const GLubyte * c
int width
Definition: ftimage.h:313
#define FT_BOOL(x)
Definition: fttypes.h:574
#define FT_FRAME_EXIT()
Definition: ftstream.h:514
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:489
signed long FT_Fixed
Definition: fttypes.h:284
unsigned int FT_UInt
Definition: fttypes.h:227
GLenum target
struct PFR_BitWriter_ * PFR_BitWriter
#define PFR_NEXT_INT8(p)
Definition: pfrload.h:39
struct PFR_BitWriter_ PFR_BitWriterRec
typedefFT_BEGIN_HEADER struct PFR_FaceRec_ * PFR_Face
Definition: pfrobjs.h:27
#define PFR_NEXT_BYTE(p)
Definition: pfrload.h:38
GLuint GLuint GLsizei count
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:510
#define FT_INT_MAX
Definition: ftstdlib.h:64
#define PFR_NEXT_USHORT(p)
Definition: pfrload.h:41
#define PFR_NEXT_ULONG(p)
Definition: pfrload.h:43
local int * code
Definition: enough.c:174
GLsizeiptr size
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
#define FT_PIX_ROUND(x)
Definition: ftobjs.h:81
GLint limit
#define PFR_NEXT_SHORT(p)
Definition: pfrload.h:40