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]
ttsbit.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ttsbit.c */
4 /* */
5 /* TrueType and OpenType embedded bitmap support (body). */
6 /* */
7 /* Copyright 1996-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 #include <ft2build.h>
19 #include FT_INTERNAL_DEBUG_H
20 #include FT_INTERNAL_STREAM_H
21 #include FT_TRUETYPE_TAGS_H
22 
23  /*
24  * Alas, the memory-optimized sbit loader can't be used when implementing
25  * the `old internals' hack
26  */
27 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
28 
29 #include "ttsbit0.c"
30 
31 #else /* FT_CONFIG_OPTION_OLD_INTERNALS */
32 
33 #include <ft2build.h>
34 #include FT_INTERNAL_DEBUG_H
35 #include FT_INTERNAL_STREAM_H
36 #include FT_TRUETYPE_TAGS_H
37 #include "ttsbit.h"
38 
39 #include "sferrors.h"
40 
41 
42  /*************************************************************************/
43  /* */
44  /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
45  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
46  /* messages during execution. */
47  /* */
48 #undef FT_COMPONENT
49 #define FT_COMPONENT trace_ttsbit
50 
51 
52  /*************************************************************************/
53  /* */
54  /* <Function> */
55  /* blit_sbit */
56  /* */
57  /* <Description> */
58  /* Blits a bitmap from an input stream into a given target. Supports */
59  /* x and y offsets as well as byte padded lines. */
60  /* */
61  /* <Input> */
62  /* target :: The target bitmap/pixmap. */
63  /* */
64  /* source :: The input packed bitmap data. */
65  /* */
66  /* line_bits :: The number of bits per line. */
67  /* */
68  /* byte_padded :: A flag which is true if lines are byte-padded. */
69  /* */
70  /* x_offset :: The horizontal offset. */
71  /* */
72  /* y_offset :: The vertical offset. */
73  /* */
74  /* <Note> */
75  /* IMPORTANT: The x and y offsets are relative to the top corner of */
76  /* the target bitmap (unlike the normal TrueType */
77  /* convention). A positive y offset indicates a downwards */
78  /* direction! */
79  /* */
80  static void
81  blit_sbit( FT_Bitmap* target,
82  FT_Byte* source,
83  FT_Int line_bits,
84  FT_Bool byte_padded,
85  FT_Int x_offset,
86  FT_Int y_offset,
87  FT_Int source_height )
88  {
89  FT_Byte* line_buff;
90  FT_Int line_incr;
91  FT_Int height;
92 
93  FT_UShort acc;
94  FT_UInt loaded;
95 
96 
97  /* first of all, compute starting write position */
98  line_incr = target->pitch;
99  line_buff = target->buffer;
100 
101  if ( line_incr < 0 )
102  line_buff -= line_incr * ( target->rows - 1 );
103 
104  line_buff += ( x_offset >> 3 ) + y_offset * line_incr;
105 
106  /***********************************************************************/
107  /* */
108  /* We use the extra-classic `accumulator' trick to extract the bits */
109  /* from the source byte stream. */
110  /* */
111  /* Namely, the variable `acc' is a 16-bit accumulator containing the */
112  /* last `loaded' bits from the input stream. The bits are shifted to */
113  /* the upmost position in `acc'. */
114  /* */
115  /***********************************************************************/
116 
117  acc = 0; /* clear accumulator */
118  loaded = 0; /* no bits were loaded */
119 
120  for ( height = source_height; height > 0; height-- )
121  {
122  FT_Byte* cur = line_buff; /* current write cursor */
123  FT_Int count = line_bits; /* # of bits to extract per line */
124  FT_Byte shift = (FT_Byte)( x_offset & 7 ); /* current write shift */
125  FT_Byte space = (FT_Byte)( 8 - shift );
126 
127 
128  /* first of all, read individual source bytes */
129  if ( count >= 8 )
130  {
131  count -= 8;
132  {
133  do
134  {
135  FT_Byte val;
136 
137 
138  /* ensure that there are at least 8 bits in the accumulator */
139  if ( loaded < 8 )
140  {
141  acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
142  loaded += 8;
143  }
144 
145  /* now write one byte */
146  val = (FT_Byte)( acc >> 8 );
147  if ( shift )
148  {
149  cur[0] |= (FT_Byte)( val >> shift );
150  cur[1] |= (FT_Byte)( val << space );
151  }
152  else
153  cur[0] |= val;
154 
155  cur++;
156  acc <<= 8; /* remove bits from accumulator */
157  loaded -= 8;
158  count -= 8;
159 
160  } while ( count >= 0 );
161  }
162 
163  /* restore `count' to correct value */
164  count += 8;
165  }
166 
167  /* now write remaining bits (count < 8) */
168  if ( count > 0 )
169  {
170  FT_Byte val;
171 
172 
173  /* ensure that there are at least `count' bits in the accumulator */
174  if ( (FT_Int)loaded < count )
175  {
176  acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
177  loaded += 8;
178  }
179 
180  /* now write remaining bits */
181  val = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) );
182  cur[0] |= (FT_Byte)( val >> shift );
183 
184  if ( count > space )
185  cur[1] |= (FT_Byte)( val << space );
186 
187  acc <<= count;
188  loaded -= count;
189  }
190 
191  /* now, skip to next line */
192  if ( byte_padded )
193  {
194  acc = 0;
195  loaded = 0; /* clear accumulator on byte-padded lines */
196  }
197 
198  line_buff += line_incr;
199  }
200  }
201 
202 
203  static const FT_Frame_Field sbit_metrics_fields[] =
204  {
205 #undef FT_STRUCTURE
206 #define FT_STRUCTURE TT_SBit_MetricsRec
207 
208  FT_FRAME_START( 8 ),
209  FT_FRAME_BYTE( height ),
210  FT_FRAME_BYTE( width ),
211 
212  FT_FRAME_CHAR( horiBearingX ),
213  FT_FRAME_CHAR( horiBearingY ),
214  FT_FRAME_BYTE( horiAdvance ),
215 
216  FT_FRAME_CHAR( vertBearingX ),
217  FT_FRAME_CHAR( vertBearingY ),
218  FT_FRAME_BYTE( vertAdvance ),
220  };
221 
222 
223  /*************************************************************************/
224  /* */
225  /* <Function> */
226  /* Load_SBit_Const_Metrics */
227  /* */
228  /* <Description> */
229  /* Loads the metrics for `EBLC' index tables format 2 and 5. */
230  /* */
231  /* <Input> */
232  /* range :: The target range. */
233  /* */
234  /* stream :: The input stream. */
235  /* */
236  /* <Return> */
237  /* FreeType error code. 0 means success. */
238  /* */
239  static FT_Error
240  Load_SBit_Const_Metrics( TT_SBit_Range range,
241  FT_Stream stream )
242  {
243  FT_Error error;
244 
245 
246  if ( FT_READ_ULONG( range->image_size ) )
247  return error;
248 
249  return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics );
250  }
251 
252 
253  /*************************************************************************/
254  /* */
255  /* <Function> */
256  /* Load_SBit_Range_Codes */
257  /* */
258  /* <Description> */
259  /* Loads the range codes for `EBLC' index tables format 4 and 5. */
260  /* */
261  /* <Input> */
262  /* range :: The target range. */
263  /* */
264  /* stream :: The input stream. */
265  /* */
266  /* load_offsets :: A flag whether to load the glyph offset table. */
267  /* */
268  /* <Return> */
269  /* FreeType error code. 0 means success. */
270  /* */
271  static FT_Error
272  Load_SBit_Range_Codes( TT_SBit_Range range,
273  FT_Stream stream,
274  FT_Bool load_offsets )
275  {
276  FT_Error error;
277  FT_ULong count, n, size;
278  FT_Memory memory = stream->memory;
279 
280 
281  if ( FT_READ_ULONG( count ) )
282  goto Exit;
283 
284  range->num_glyphs = count;
285 
286  /* Allocate glyph offsets table if needed */
287  if ( load_offsets )
288  {
289  if ( FT_NEW_ARRAY( range->glyph_offsets, count ) )
290  goto Exit;
291 
292  size = count * 4L;
293  }
294  else
295  size = count * 2L;
296 
297  /* Allocate glyph codes table and access frame */
298  if ( FT_NEW_ARRAY ( range->glyph_codes, count ) ||
299  FT_FRAME_ENTER( size ) )
300  goto Exit;
301 
302  for ( n = 0; n < count; n++ )
303  {
304  range->glyph_codes[n] = FT_GET_USHORT();
305 
306  if ( load_offsets )
307  range->glyph_offsets[n] = (FT_ULong)range->image_offset +
308  FT_GET_USHORT();
309  }
310 
311  FT_FRAME_EXIT();
312 
313  Exit:
314  return error;
315  }
316 
317 
318  /*************************************************************************/
319  /* */
320  /* <Function> */
321  /* Load_SBit_Range */
322  /* */
323  /* <Description> */
324  /* Loads a given `EBLC' index/range table. */
325  /* */
326  /* <Input> */
327  /* range :: The target range. */
328  /* */
329  /* stream :: The input stream. */
330  /* */
331  /* <Return> */
332  /* FreeType error code. 0 means success. */
333  /* */
334  static FT_Error
335  Load_SBit_Range( TT_SBit_Range range,
336  FT_Stream stream )
337  {
338  FT_Error error;
339  FT_Memory memory = stream->memory;
340 
341 
342  switch( range->index_format )
343  {
344  case 1: /* variable metrics with 4-byte offsets */
345  case 3: /* variable metrics with 2-byte offsets */
346  {
347  FT_ULong num_glyphs, n;
348  FT_Int size_elem;
349  FT_Bool large = FT_BOOL( range->index_format == 1 );
350 
351 
352 
353  if ( range->last_glyph < range->first_glyph )
354  {
355  error = FT_THROW( Invalid_File_Format );
356  goto Exit;
357  }
358 
359  num_glyphs = range->last_glyph - range->first_glyph + 1L;
360  range->num_glyphs = num_glyphs;
361  num_glyphs++; /* XXX: BEWARE - see spec */
362 
363  size_elem = large ? 4 : 2;
364 
365  if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) ||
366  FT_FRAME_ENTER( num_glyphs * size_elem ) )
367  goto Exit;
368 
369  for ( n = 0; n < num_glyphs; n++ )
370  range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
371  ( large ? FT_GET_ULONG()
372  : FT_GET_USHORT() ) );
373  FT_FRAME_EXIT();
374  }
375  break;
376 
377  case 2: /* all glyphs have identical metrics */
378  error = Load_SBit_Const_Metrics( range, stream );
379  break;
380 
381  case 4:
382  error = Load_SBit_Range_Codes( range, stream, 1 );
383  break;
384 
385  case 5:
386  error = Load_SBit_Const_Metrics( range, stream );
387  if ( !error )
388  error = Load_SBit_Range_Codes( range, stream, 0 );
389  break;
390 
391  default:
392  error = FT_THROW( Invalid_File_Format );
393  }
394 
395  Exit:
396  return error;
397  }
398 
399 
400  /*************************************************************************/
401  /* */
402  /* <Function> */
403  /* tt_face_load_eblc */
404  /* */
405  /* <Description> */
406  /* Loads the table of embedded bitmap sizes for this face. */
407  /* */
408  /* <Input> */
409  /* face :: The target face object. */
410  /* */
411  /* stream :: The input stream. */
412  /* */
413  /* <Return> */
414  /* FreeType error code. 0 means success. */
415  /* */
418  FT_Stream stream )
419  {
420  FT_Error error = FT_Err_Ok;
421  FT_Memory memory = stream->memory;
423  FT_ULong num_strikes;
424  FT_ULong table_base;
425 
426  static const FT_Frame_Field sbit_line_metrics_fields[] =
427  {
428 #undef FT_STRUCTURE
429 #define FT_STRUCTURE TT_SBit_LineMetricsRec
430 
431  /* no FT_FRAME_START */
432  FT_FRAME_CHAR( ascender ),
433  FT_FRAME_CHAR( descender ),
434  FT_FRAME_BYTE( max_width ),
435 
436  FT_FRAME_CHAR( caret_slope_numerator ),
437  FT_FRAME_CHAR( caret_slope_denominator ),
438  FT_FRAME_CHAR( caret_offset ),
439 
440  FT_FRAME_CHAR( min_origin_SB ),
441  FT_FRAME_CHAR( min_advance_SB ),
442  FT_FRAME_CHAR( max_before_BL ),
443  FT_FRAME_CHAR( min_after_BL ),
444  FT_FRAME_CHAR( pads[0] ),
445  FT_FRAME_CHAR( pads[1] ),
447  };
448 
449  static const FT_Frame_Field strike_start_fields[] =
450  {
451 #undef FT_STRUCTURE
452 #define FT_STRUCTURE TT_SBit_StrikeRec
453 
454  /* no FT_FRAME_START */
455  FT_FRAME_ULONG( ranges_offset ),
457  FT_FRAME_ULONG( num_ranges ),
458  FT_FRAME_ULONG( color_ref ),
460  };
461 
462  static const FT_Frame_Field strike_end_fields[] =
463  {
464  /* no FT_FRAME_START */
465  FT_FRAME_USHORT( start_glyph ),
466  FT_FRAME_USHORT( end_glyph ),
467  FT_FRAME_BYTE ( x_ppem ),
468  FT_FRAME_BYTE ( y_ppem ),
470  FT_FRAME_CHAR ( flags ),
471  FT_FRAME_END
472  };
473 
474 
475  face->num_sbit_strikes = 0;
476 
477  /* this table is optional */
478  error = face->goto_table( face, TTAG_EBLC, stream, 0 );
479  if ( error )
480  error = face->goto_table( face, TTAG_bloc, stream, 0 );
481  if ( error )
482  goto Exit;
483 
484  table_base = FT_STREAM_POS();
485  if ( FT_FRAME_ENTER( 8L ) )
486  goto Exit;
487 
488  version = FT_GET_LONG();
489  num_strikes = FT_GET_ULONG();
490 
491  FT_FRAME_EXIT();
492 
493  /* check version number and strike count */
494  if ( version != 0x00020000L ||
495  num_strikes >= 0x10000L )
496  {
497  FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
498  error = FT_THROW( Invalid_File_Format );
499 
500  goto Exit;
501  }
502 
503  /* allocate the strikes table */
504  if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) )
505  goto Exit;
506 
507  face->num_sbit_strikes = num_strikes;
508 
509  /* now read each strike table separately */
510  {
511  TT_SBit_Strike strike = face->sbit_strikes;
512  FT_ULong count = num_strikes;
513 
514 
515  if ( FT_FRAME_ENTER( 48L * num_strikes ) )
516  goto Exit;
517 
518  while ( count > 0 )
519  {
520  if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike ) ||
521  FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) ||
522  FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) ||
523  FT_STREAM_READ_FIELDS( strike_end_fields, strike ) )
524  break;
525 
526  count--;
527  strike++;
528  }
529 
530  FT_FRAME_EXIT();
531  }
532 
533  /* allocate the index ranges for each strike table */
534  {
535  TT_SBit_Strike strike = face->sbit_strikes;
536  FT_ULong count = num_strikes;
537 
538 
539  while ( count > 0 )
540  {
542  FT_ULong count2 = strike->num_ranges;
543 
544 
545  /* read each range */
546  if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) ||
547  FT_FRAME_ENTER( strike->num_ranges * 8L ) )
548  goto Exit;
549 
550  if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) )
551  goto Exit;
552 
553  range = strike->sbit_ranges;
554  while ( count2 > 0 )
555  {
556  range->first_glyph = FT_GET_USHORT();
557  range->last_glyph = FT_GET_USHORT();
558  range->table_offset = table_base + strike->ranges_offset +
559  FT_GET_ULONG();
560  count2--;
561  range++;
562  }
563 
564  FT_FRAME_EXIT();
565 
566  /* Now, read each index table */
567  count2 = strike->num_ranges;
568  range = strike->sbit_ranges;
569  while ( count2 > 0 )
570  {
571  /* Read the header */
572  if ( FT_STREAM_SEEK( range->table_offset ) ||
573  FT_FRAME_ENTER( 8L ) )
574  goto Exit;
575 
576  range->index_format = FT_GET_USHORT();
577  range->image_format = FT_GET_USHORT();
578  range->image_offset = FT_GET_ULONG();
579 
580  FT_FRAME_EXIT();
581 
582  error = Load_SBit_Range( range, stream );
583  if ( error )
584  goto Exit;
585 
586  count2--;
587  range++;
588  }
589 
590  count--;
591  strike++;
592  }
593  }
594 
595  Exit:
596  return error;
597  }
598 
599 
600  /*************************************************************************/
601  /* */
602  /* <Function> */
603  /* tt_face_free_eblc */
604  /* */
605  /* <Description> */
606  /* Releases the embedded bitmap tables. */
607  /* */
608  /* <Input> */
609  /* face :: The target face object. */
610  /* */
611  FT_LOCAL_DEF( void )
612  tt_face_free_eblc( TT_Face face )
613  {
614  FT_Memory memory = face->root.memory;
615  TT_SBit_Strike strike = face->sbit_strikes;
616  TT_SBit_Strike strike_limit = strike + face->num_sbit_strikes;
617 
618 
619  if ( strike )
620  {
621  for ( ; strike < strike_limit; strike++ )
622  {
623  TT_SBit_Range range = strike->sbit_ranges;
624  TT_SBit_Range range_limit = range + strike->num_ranges;
625 
626 
627  if ( range )
628  {
629  for ( ; range < range_limit; range++ )
630  {
631  /* release the glyph offsets and codes tables */
632  /* where appropriate */
633  FT_FREE( range->glyph_offsets );
634  FT_FREE( range->glyph_codes );
635  }
636  }
637  FT_FREE( strike->sbit_ranges );
638  strike->num_ranges = 0;
639  }
640  FT_FREE( face->sbit_strikes );
641  }
642  face->num_sbit_strikes = 0;
643  }
644 
645 
648  FT_Size_Request req,
649  FT_ULong* astrike_index )
650  {
651  return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
652  }
653 
654 
657  FT_ULong strike_index,
659  {
660  TT_SBit_Strike strike;
661 
662 
663  if ( strike_index >= face->num_sbit_strikes )
664  return FT_THROW( Invalid_Argument );
665 
666  strike = face->sbit_strikes + strike_index;
667 
668  metrics->x_ppem = strike->x_ppem;
669  metrics->y_ppem = strike->y_ppem;
670 
671  metrics->ascender = strike->hori.ascender << 6;
672  metrics->descender = strike->hori.descender << 6;
673 
674  /* XXX: Is this correct? */
675  metrics->max_advance = ( strike->hori.min_origin_SB +
676  strike->hori.max_width +
677  strike->hori.min_advance_SB ) << 6;
678 
679  metrics->height = metrics->ascender - metrics->descender;
680 
681  return FT_Err_Ok;
682  }
683 
684 
685  /*************************************************************************/
686  /* */
687  /* <Function> */
688  /* find_sbit_range */
689  /* */
690  /* <Description> */
691  /* Scans a given strike's ranges and return, for a given glyph */
692  /* index, the corresponding sbit range, and `EBDT' offset. */
693  /* */
694  /* <Input> */
695  /* glyph_index :: The glyph index. */
696  /* */
697  /* strike :: The source/current sbit strike. */
698  /* */
699  /* <Output> */
700  /* arange :: The sbit range containing the glyph index. */
701  /* */
702  /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
703  /* */
704  /* <Return> */
705  /* FreeType error code. 0 means the glyph index was found. */
706  /* */
707  static FT_Error
708  find_sbit_range( FT_UInt glyph_index,
709  TT_SBit_Strike strike,
710  TT_SBit_Range *arange,
711  FT_ULong *aglyph_offset )
712  {
713  TT_SBit_RangeRec *range, *range_limit;
714 
715 
716  /* check whether the glyph index is within this strike's */
717  /* glyph range */
718  if ( glyph_index < (FT_UInt)strike->start_glyph ||
719  glyph_index > (FT_UInt)strike->end_glyph )
720  goto Fail;
721 
722  /* scan all ranges in strike */
723  range = strike->sbit_ranges;
724  range_limit = range + strike->num_ranges;
725  if ( !range )
726  goto Fail;
727 
728  for ( ; range < range_limit; range++ )
729  {
730  if ( glyph_index >= (FT_UInt)range->first_glyph &&
731  glyph_index <= (FT_UInt)range->last_glyph )
732  {
733  FT_UShort delta = (FT_UShort)( glyph_index - range->first_glyph );
734 
735 
736  switch ( range->index_format )
737  {
738  case 1:
739  case 3:
740  *aglyph_offset = range->glyph_offsets[delta];
741  break;
742 
743  case 2:
744  *aglyph_offset = range->image_offset +
745  range->image_size * delta;
746  break;
747 
748  case 4:
749  case 5:
750  {
751  FT_ULong n;
752 
753 
754  for ( n = 0; n < range->num_glyphs; n++ )
755  {
756  if ( (FT_UInt)range->glyph_codes[n] == glyph_index )
757  {
758  if ( range->index_format == 4 )
759  *aglyph_offset = range->glyph_offsets[n];
760  else
761  *aglyph_offset = range->image_offset +
762  n * range->image_size;
763  goto Found;
764  }
765  }
766  }
767 
768  /* fall-through */
769  default:
770  goto Fail;
771  }
772 
773  Found:
774  /* return successfully! */
775  *arange = range;
776  return FT_Err_Ok;
777  }
778  }
779 
780  Fail:
781  *arange = 0;
782  *aglyph_offset = 0;
783 
784  return FT_THROW( Invalid_Argument );
785  }
786 
787 
788  /*************************************************************************/
789  /* */
790  /* <Function> */
791  /* tt_find_sbit_image */
792  /* */
793  /* <Description> */
794  /* Checks whether an embedded bitmap (an `sbit') exists for a given */
795  /* glyph, at a given strike. */
796  /* */
797  /* <Input> */
798  /* face :: The target face object. */
799  /* */
800  /* glyph_index :: The glyph index. */
801  /* */
802  /* strike_index :: The current strike index. */
803  /* */
804  /* <Output> */
805  /* arange :: The SBit range containing the glyph index. */
806  /* */
807  /* astrike :: The SBit strike containing the glyph index. */
808  /* */
809  /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
810  /* */
811  /* <Return> */
812  /* FreeType error code. 0 means success. Returns */
813  /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */
814  /* glyph. */
815  /* */
816  FT_LOCAL( FT_Error )
817  tt_find_sbit_image( TT_Face face,
818  FT_UInt glyph_index,
819  FT_ULong strike_index,
820  TT_SBit_Range *arange,
821  TT_SBit_Strike *astrike,
822  FT_ULong *aglyph_offset )
823  {
824  FT_Error error;
825  TT_SBit_Strike strike;
826 
827 
828  if ( !face->sbit_strikes ||
829  ( face->num_sbit_strikes <= strike_index ) )
830  goto Fail;
831 
832  strike = &face->sbit_strikes[strike_index];
833 
834  error = find_sbit_range( glyph_index, strike,
835  arange, aglyph_offset );
836  if ( error )
837  goto Fail;
838 
839  *astrike = strike;
840 
841  return FT_Err_Ok;
842 
843  Fail:
844  /* no embedded bitmap for this glyph in face */
845  *arange = 0;
846  *astrike = 0;
847  *aglyph_offset = 0;
848 
849  return FT_THROW( Invalid_Argument );
850  }
851 
852 
853  /*************************************************************************/
854  /* */
855  /* <Function> */
856  /* tt_load_sbit_metrics */
857  /* */
858  /* <Description> */
859  /* Gets the big metrics for a given SBit. */
860  /* */
861  /* <Input> */
862  /* stream :: The input stream. */
863  /* */
864  /* range :: The SBit range containing the glyph. */
865  /* */
866  /* <Output> */
867  /* big_metrics :: A big SBit metrics structure for the glyph. */
868  /* */
869  /* <Return> */
870  /* FreeType error code. 0 means success. */
871  /* */
872  /* <Note> */
873  /* The stream cursor must be positioned at the glyph's offset within */
874  /* the `EBDT' table before the call. */
875  /* */
876  /* If the image format uses variable metrics, the stream cursor is */
877  /* positioned just after the metrics header in the `EBDT' table on */
878  /* function exit. */
879  /* */
880  FT_LOCAL( FT_Error )
881  tt_load_sbit_metrics( FT_Stream stream,
882  TT_SBit_Range range,
883  TT_SBit_Metrics metrics )
884  {
885  FT_Error error = FT_Err_Ok;
886 
887 
888  switch ( range->image_format )
889  {
890  case 1:
891  case 2:
892  case 8:
893  /* variable small metrics */
894  {
895  TT_SBit_SmallMetricsRec smetrics;
896 
897  static const FT_Frame_Field sbit_small_metrics_fields[] =
898  {
899 #undef FT_STRUCTURE
900 #define FT_STRUCTURE TT_SBit_SmallMetricsRec
901 
902  FT_FRAME_START( 5 ),
903  FT_FRAME_BYTE( height ),
904  FT_FRAME_BYTE( width ),
905  FT_FRAME_CHAR( bearingX ),
906  FT_FRAME_CHAR( bearingY ),
907  FT_FRAME_BYTE( advance ),
908  FT_FRAME_END
909  };
910 
911 
912  /* read small metrics */
913  if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) )
914  goto Exit;
915 
916  /* convert it to a big metrics */
917  metrics->height = smetrics.height;
918  metrics->width = smetrics.width;
919  metrics->horiBearingX = smetrics.bearingX;
920  metrics->horiBearingY = smetrics.bearingY;
921  metrics->horiAdvance = smetrics.advance;
922 
923  /* these metrics are made up at a higher level when */
924  /* needed. */
925  metrics->vertBearingX = 0;
926  metrics->vertBearingY = 0;
927  metrics->vertAdvance = 0;
928  }
929  break;
930 
931  case 6:
932  case 7:
933  case 9:
934  /* variable big metrics */
935  if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) )
936  goto Exit;
937  break;
938 
939  case 5:
940  default: /* constant metrics */
941  if ( range->index_format == 2 || range->index_format == 5 )
942  *metrics = range->metrics;
943  else
944  return FT_THROW( Invalid_File_Format );
945  }
946 
947  Exit:
948  return error;
949  }
950 
951 
952  /*************************************************************************/
953  /* */
954  /* <Function> */
955  /* crop_bitmap */
956  /* */
957  /* <Description> */
958  /* Crops a bitmap to its tightest bounding box, and adjusts its */
959  /* metrics. */
960  /* */
961  /* <InOut> */
962  /* map :: The bitmap. */
963  /* */
964  /* metrics :: The corresponding metrics structure. */
965  /* */
966  static void
967  crop_bitmap( FT_Bitmap* map,
968  TT_SBit_Metrics metrics )
969  {
970  /***********************************************************************/
971  /* */
972  /* In this situation, some bounding boxes of embedded bitmaps are too */
973  /* large. We need to crop it to a reasonable size. */
974  /* */
975  /* --------- */
976  /* | | ----- */
977  /* | *** | |***| */
978  /* | * | | * | */
979  /* | * | ------> | * | */
980  /* | * | | * | */
981  /* | * | | * | */
982  /* | *** | |***| */
983  /* --------- ----- */
984  /* */
985  /***********************************************************************/
986 
987  FT_Int rows, count;
988  FT_Long line_len;
989  FT_Byte* line;
990 
991 
992  /***********************************************************************/
993  /* */
994  /* first of all, check the top-most lines of the bitmap, and remove */
995  /* them if they're empty. */
996  /* */
997  {
998  line = (FT_Byte*)map->buffer;
999  rows = map->rows;
1000  line_len = map->pitch;
1001 
1002 
1003  for ( count = 0; count < rows; count++ )
1004  {
1005  FT_Byte* cur = line;
1006  FT_Byte* limit = line + line_len;
1007 
1008 
1009  for ( ; cur < limit; cur++ )
1010  if ( cur[0] )
1011  goto Found_Top;
1012 
1013  /* the current line was empty - skip to next one */
1014  line = limit;
1015  }
1016 
1017  Found_Top:
1018  /* check that we have at least one filled line */
1019  if ( count >= rows )
1020  goto Empty_Bitmap;
1021 
1022  /* now, crop the empty upper lines */
1023  if ( count > 0 )
1024  {
1025  line = (FT_Byte*)map->buffer;
1026 
1027  FT_MEM_MOVE( line, line + count * line_len,
1028  ( rows - count ) * line_len );
1029 
1030  metrics->height = (FT_Byte)( metrics->height - count );
1031  metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count );
1032  metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count );
1033 
1034  map->rows -= count;
1035  rows -= count;
1036  }
1037  }
1038 
1039  /***********************************************************************/
1040  /* */
1041  /* second, crop the lower lines */
1042  /* */
1043  {
1044  line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
1045 
1046  for ( count = 0; count < rows; count++ )
1047  {
1048  FT_Byte* cur = line;
1049  FT_Byte* limit = line + line_len;
1050 
1051 
1052  for ( ; cur < limit; cur++ )
1053  if ( cur[0] )
1054  goto Found_Bottom;
1055 
1056  /* the current line was empty - skip to previous one */
1057  line -= line_len;
1058  }
1059 
1060  Found_Bottom:
1061  if ( count > 0 )
1062  {
1063  metrics->height = (FT_Byte)( metrics->height - count );
1064  rows -= count;
1065  map->rows -= count;
1066  }
1067  }
1068 
1069  /***********************************************************************/
1070  /* */
1071  /* third, get rid of the space on the left side of the glyph */
1072  /* */
1073  do
1074  {
1075  FT_Byte* limit;
1076 
1077 
1078  line = (FT_Byte*)map->buffer;
1079  limit = line + rows * line_len;
1080 
1081  for ( ; line < limit; line += line_len )
1082  if ( line[0] & 0x80 )
1083  goto Found_Left;
1084 
1085  /* shift the whole glyph one pixel to the left */
1086  line = (FT_Byte*)map->buffer;
1087  limit = line + rows * line_len;
1088 
1089  for ( ; line < limit; line += line_len )
1090  {
1091  FT_Int n, width = map->width;
1092  FT_Byte old;
1093  FT_Byte* cur = line;
1094 
1095 
1096  old = (FT_Byte)(cur[0] << 1);
1097  for ( n = 8; n < width; n += 8 )
1098  {
1099  FT_Byte val;
1100 
1101 
1102  val = cur[1];
1103  cur[0] = (FT_Byte)( old | ( val >> 7 ) );
1104  old = (FT_Byte)( val << 1 );
1105  cur++;
1106  }
1107  cur[0] = old;
1108  }
1109 
1110  map->width--;
1111  metrics->horiBearingX++;
1112  metrics->vertBearingX++;
1113  metrics->width--;
1114 
1115  } while ( map->width > 0 );
1116 
1117  Found_Left:
1118 
1119  /***********************************************************************/
1120  /* */
1121  /* finally, crop the bitmap width to get rid of the space on the right */
1122  /* side of the glyph. */
1123  /* */
1124  do
1125  {
1126  FT_Int right = map->width - 1;
1127  FT_Byte* limit;
1128  FT_Byte mask;
1129 
1130 
1131  line = (FT_Byte*)map->buffer + ( right >> 3 );
1132  limit = line + rows * line_len;
1133  mask = (FT_Byte)( 0x80 >> ( right & 7 ) );
1134 
1135  for ( ; line < limit; line += line_len )
1136  if ( line[0] & mask )
1137  goto Found_Right;
1138 
1139  /* crop the whole glyph to the right */
1140  map->width--;
1141  metrics->width--;
1142 
1143  } while ( map->width > 0 );
1144 
1145  Found_Right:
1146  /* all right, the bitmap was cropped */
1147  return;
1148 
1149  Empty_Bitmap:
1150  map->width = 0;
1151  map->rows = 0;
1152  map->pitch = 0;
1154  }
1155 
1156 
1157  static FT_Error
1158  Load_SBit_Single( FT_Bitmap* map,
1159  FT_Int x_offset,
1160  FT_Int y_offset,
1161  FT_Int pix_bits,
1162  FT_UShort image_format,
1163  TT_SBit_Metrics metrics,
1164  FT_Stream stream )
1165  {
1166  FT_Error error;
1167 
1168 
1169  /* check that the source bitmap fits into the target pixmap */
1170  if ( x_offset < 0 || x_offset + metrics->width > map->width ||
1171  y_offset < 0 || y_offset + metrics->height > map->rows )
1172  {
1173  error = FT_THROW( Invalid_Argument );
1174 
1175  goto Exit;
1176  }
1177 
1178  {
1179  FT_Int glyph_width = metrics->width;
1180  FT_Int glyph_height = metrics->height;
1181  FT_Int glyph_size;
1182  FT_Int line_bits = pix_bits * glyph_width;
1183  FT_Bool pad_bytes = 0;
1184 
1185 
1186  /* compute size of glyph image */
1187  switch ( image_format )
1188  {
1189  case 1: /* byte-padded formats */
1190  case 6:
1191  {
1192  FT_Int line_length;
1193 
1194 
1195  switch ( pix_bits )
1196  {
1197  case 1:
1198  line_length = ( glyph_width + 7 ) >> 3;
1199  break;
1200  case 2:
1201  line_length = ( glyph_width + 3 ) >> 2;
1202  break;
1203  case 4:
1204  line_length = ( glyph_width + 1 ) >> 1;
1205  break;
1206  default:
1207  line_length = glyph_width;
1208  }
1209 
1210  glyph_size = glyph_height * line_length;
1211  pad_bytes = 1;
1212  }
1213  break;
1214 
1215  case 2:
1216  case 5:
1217  case 7:
1218  line_bits = glyph_width * pix_bits;
1219  glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
1220  break;
1221 
1222  default: /* invalid format */
1223  return FT_THROW( Invalid_File_Format );
1224  }
1225 
1226  /* Now read data and draw glyph into target pixmap */
1227  if ( FT_FRAME_ENTER( glyph_size ) )
1228  goto Exit;
1229 
1230  /* don't forget to multiply `x_offset' by `map->pix_bits' as */
1231  /* the sbit blitter doesn't make a difference between pixmap */
1232  /* depths. */
1233  blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
1234  x_offset * pix_bits, y_offset, metrics->height );
1235 
1236  FT_FRAME_EXIT();
1237  }
1238 
1239  Exit:
1240  return error;
1241  }
1242 
1243 
1244  static FT_Error
1245  Load_SBit_Image( TT_SBit_Strike strike,
1246  TT_SBit_Range range,
1247  FT_ULong ebdt_pos,
1248  FT_ULong glyph_offset,
1249  FT_GlyphSlot slot,
1250  FT_Int x_offset,
1251  FT_Int y_offset,
1252  FT_Stream stream,
1253  TT_SBit_Metrics metrics,
1254  FT_Int depth )
1255  {
1256  FT_Memory memory = stream->memory;
1257  FT_Bitmap* map = &slot->bitmap;
1258  FT_Error error;
1259 
1260 
1261  /* place stream at beginning of glyph data and read metrics */
1262  if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) )
1263  goto Exit;
1264 
1265  error = tt_load_sbit_metrics( stream, range, metrics );
1266  if ( error )
1267  goto Exit;
1268 
1269  /* This function is recursive. At the top-level call, we */
1270  /* compute the dimensions of the higher-level glyph to */
1271  /* allocate the final pixmap buffer. */
1272  if ( depth == 0 )
1273  {
1274  FT_Long size;
1275 
1276 
1277  map->width = metrics->width;
1278  map->rows = metrics->height;
1279 
1280  switch ( strike->bit_depth )
1281  {
1282  case 1:
1284  map->pitch = ( map->width + 7 ) >> 3;
1285  break;
1286 
1287  case 2:
1289  map->pitch = ( map->width + 3 ) >> 2;
1290  break;
1291 
1292  case 4:
1294  map->pitch = ( map->width + 1 ) >> 1;
1295  break;
1296 
1297  case 8:
1299  map->pitch = map->width;
1300  break;
1301 
1302  default:
1303  return FT_THROW( Invalid_File_Format );
1304  }
1305 
1306  size = map->rows * map->pitch;
1307 
1308  /* check that there is no empty image */
1309  if ( size == 0 )
1310  goto Exit; /* exit successfully! */
1311 
1312  error = ft_glyphslot_alloc_bitmap( slot, size );
1313  if (error)
1314  goto Exit;
1315  }
1316 
1317  switch ( range->image_format )
1318  {
1319  case 1: /* single sbit image - load it */
1320  case 2:
1321  case 5:
1322  case 6:
1323  case 7:
1324  return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
1325  range->image_format, metrics, stream );
1326 
1327  case 8: /* compound format */
1328  if ( FT_STREAM_SKIP( 1L ) )
1329  {
1330  error = FT_THROW( Invalid_Stream_Skip );
1331  goto Exit;
1332  }
1333  /* fallthrough */
1334 
1335  case 9:
1336  break;
1337 
1338  default: /* invalid image format */
1339  return FT_THROW( Invalid_File_Format );
1340  }
1341 
1342  /* All right, we have a compound format. First of all, read */
1343  /* the array of elements. */
1344  {
1346  TT_SBit_Component comp;
1347  FT_UShort num_components, count;
1348 
1349 
1350  if ( FT_READ_USHORT( num_components ) ||
1351  FT_NEW_ARRAY( components, num_components ) )
1352  goto Exit;
1353 
1354  count = num_components;
1355 
1356  if ( FT_FRAME_ENTER( 4L * num_components ) )
1357  goto Fail_Memory;
1358 
1359  for ( comp = components; count > 0; count--, comp++ )
1360  {
1361  comp->glyph_code = FT_GET_USHORT();
1362  comp->x_offset = FT_GET_CHAR();
1363  comp->y_offset = FT_GET_CHAR();
1364  }
1365 
1366  FT_FRAME_EXIT();
1367 
1368  /* Now recursively load each element glyph */
1369  count = num_components;
1370  comp = components;
1371  for ( ; count > 0; count--, comp++ )
1372  {
1373  TT_SBit_Range elem_range;
1374  TT_SBit_MetricsRec elem_metrics;
1375  FT_ULong elem_offset;
1376 
1377 
1378  /* find the range for this element */
1379  error = find_sbit_range( comp->glyph_code,
1380  strike,
1381  &elem_range,
1382  &elem_offset );
1383  if ( error )
1384  goto Fail_Memory;
1385 
1386  /* now load the element, recursively */
1387  error = Load_SBit_Image( strike,
1388  elem_range,
1389  ebdt_pos,
1390  elem_offset,
1391  slot,
1392  x_offset + comp->x_offset,
1393  y_offset + comp->y_offset,
1394  stream,
1395  &elem_metrics,
1396  depth + 1 );
1397  if ( error )
1398  goto Fail_Memory;
1399  }
1400 
1401  Fail_Memory:
1402  FT_FREE( components );
1403  }
1404 
1405  Exit:
1406  return error;
1407  }
1408 
1409 
1410  /*************************************************************************/
1411  /* */
1412  /* <Function> */
1413  /* tt_face_load_sbit_image */
1414  /* */
1415  /* <Description> */
1416  /* Loads a given glyph sbit image from the font resource. This also */
1417  /* returns its metrics. */
1418  /* */
1419  /* <Input> */
1420  /* face :: The target face object. */
1421  /* */
1422  /* strike_index :: The current strike index. */
1423  /* */
1424  /* glyph_index :: The current glyph index. */
1425  /* */
1426  /* load_flags :: The glyph load flags (the code checks for the flag */
1427  /* FT_LOAD_CROP_BITMAP). */
1428  /* */
1429  /* stream :: The input stream. */
1430  /* */
1431  /* <Output> */
1432  /* map :: The target pixmap. */
1433  /* */
1434  /* metrics :: A big sbit metrics structure for the glyph image. */
1435  /* */
1436  /* <Return> */
1437  /* FreeType error code. 0 means success. Returns an error if no */
1438  /* glyph sbit exists for the index. */
1439  /* */
1440  /* <Note> */
1441  /* The `map.buffer' field is always freed before the glyph is loaded. */
1442  /* */
1445  FT_ULong strike_index,
1446  FT_UInt glyph_index,
1447  FT_UInt load_flags,
1448  FT_Stream stream,
1449  FT_Bitmap *map,
1450  TT_SBit_MetricsRec *metrics )
1451  {
1452  FT_Error error;
1453  FT_ULong ebdt_pos, glyph_offset;
1454 
1455  TT_SBit_Strike strike;
1457 
1458 
1459  /* Check whether there is a glyph sbit for the current index */
1460  error = tt_find_sbit_image( face, glyph_index, strike_index,
1461  &range, &strike, &glyph_offset );
1462  if ( error )
1463  goto Exit;
1464 
1465  /* now, find the location of the `EBDT' table in */
1466  /* the font file */
1467  error = face->goto_table( face, TTAG_EBDT, stream, 0 );
1468  if ( error )
1469  error = face->goto_table( face, TTAG_bdat, stream, 0 );
1470  if ( error )
1471  goto Exit;
1472 
1473  ebdt_pos = FT_STREAM_POS();
1474 
1475  error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,
1476  face->root.glyph, 0, 0, stream, metrics, 0 );
1477  if ( error )
1478  goto Exit;
1479 
1480  /* setup vertical metrics if needed */
1481  if ( strike->flags & 1 )
1482  {
1483  /* in case of a horizontal strike only */
1484  FT_Int advance;
1485 
1486 
1487  advance = strike->hori.ascender - strike->hori.descender;
1488 
1489  /* some heuristic values */
1490 
1491  metrics->vertBearingX = (FT_Char)(-metrics->width / 2 );
1492  metrics->vertBearingY = (FT_Char)( ( advance - metrics->height ) / 2 );
1493  metrics->vertAdvance = (FT_Char)( advance * 12 / 10 );
1494  }
1495 
1496  /* Crop the bitmap now, unless specified otherwise */
1497  if ( load_flags & FT_LOAD_CROP_BITMAP )
1498  crop_bitmap( map, metrics );
1499 
1500  Exit:
1501  return error;
1502  }
1503 
1504 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
1505 
1506 
1507 /* END */
GLint GLint GLsizei GLsizei height
local int large
Definition: enough.c:172
int FT_Error
Definition: fttypes.h:296
GLuint GLuint stream
for(n=1;n< outline->n_points;n++)
Definition: ftbbox.c:593
FT_ULong * glyph_offsets
Definition: tttypes.h:602
signed long FT_Long
Definition: fttypes.h:238
unsigned long FT_ULong
Definition: fttypes.h:249
GLint GLint GLsizei GLsizei GLsizei depth
FT_Char horiBearingY
Definition: tttypes.h:441
#define NULL
Definition: ftobjs.h:61
signed int FT_Int
Definition: fttypes.h:216
int rows
Definition: ftimage.h:312
FT_Byte horiAdvance
Definition: tttypes.h:442
unsigned char * cursor
Definition: ftsystem.h:333
FT_Byte y_ppem
Definition: tttypes.h:668
return FT_THROW(Missing_Property)
#define FT_GET_CHAR()
Definition: ftstream.h:286
FT_UShort first_glyph
Definition: tttypes.h:591
unsigned char * buffer
Definition: ftimage.h:315
GLsizei GLsizei GLchar * source
signed char FT_Char
Definition: fttypes.h:139
FT_UShort start_glyph
Definition: tttypes.h:664
GLenum GLenum GLuint components
GLint GLint GLsizei width
tt_face_set_sbit_strike(TT_Face face, FT_Size_Request req, FT_ULong *astrike_index)
Definition: ttsbit0.c:122
int pitch
Definition: ftimage.h:314
return FT_Err_Ok
Definition: ftbbox.c:645
FT_Byte bit_depth
Definition: tttypes.h:670
#define FT_READ_USHORT(var)
Definition: ftstream.h:309
GLenum GLint * range
TT_Loader_GotoTableFunc goto_table
Definition: tttypes.h:1288
#define TTAG_EBLC
Definition: tttags.h:50
TT_SBit_LineMetricsRec hori
Definition: tttypes.h:661
FT_Pos max_advance
Definition: freetype.h:1378
tt_face_load_sbit_image(TT_Face face, FT_ULong strike_index, FT_UInt glyph_index, FT_UInt load_flags, FT_Stream stream, FT_Bitmap *map, TT_SBit_MetricsRec *metrics)
Definition: ttsbit0.c:983
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:104
FT_UShort last_glyph
Definition: tttypes.h:592
FT_ULong ranges_offset
Definition: tttypes.h:657
FT_ULong num_glyphs
Definition: tttypes.h:600
GLenum GLuint GLint GLenum face
FT_Byte x_ppem
Definition: tttypes.h:667
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
unsigned char FT_Byte
Definition: fttypes.h:150
TT_SBit_LineMetricsRec vert
Definition: tttypes.h:662
FT_Bitmap bitmap
Definition: freetype.h:1627
#define FT_STREAM_READ_FIELDS(fields, object)
Definition: ftstream.h:506
FT_Match_Size(FT_Face face, FT_Size_Request req, FT_Bool ignore_width, FT_ULong *size_index)
Definition: ftobjs.c:2491
FT_Char horiBearingX
Definition: tttypes.h:440
FT_Memory memory
Definition: ftsystem.h:332
#define FT_GET_USHORT()
Definition: ftstream.h:289
#define FT_FREE(ptr)
Definition: ftmemory.h:286
GLdouble GLdouble right
#define FT_FRAME_END
Definition: ftstream.h:118
#define FT_STREAM_SKIP(distance)
Definition: ftstream.h:492
#define FT_LOCAL(x)
Definition: ftconfig.h:235
#define FT_FRAME_USHORT(f)
Definition: ftstream.h:123
GLenum GLint GLuint mask
#define FT_LOAD_CROP_BITMAP
Definition: freetype.h:2555
FT_Error error
Definition: cffdrivr.c:411
FT_Char vertBearingX
Definition: tttypes.h:444
ft_glyphslot_alloc_bitmap(FT_GlyphSlot slot, FT_ULong size)
Definition: ftobjs.c:306
#define FT_READ_ULONG(var)
Definition: ftstream.h:313
GLbitfield flags
TT_SBit_MetricsRec metrics
Definition: tttypes.h:599
#define TTAG_bdat
Definition: tttags.h:38
#define TTAG_bloc
Definition: tttags.h:41
GLuint GLfloat * val
FT_Char vertBearingY
Definition: tttypes.h:445
GLdouble n
FT_UShort glyph_code
Definition: tttypes.h:693
int const char * version
Definition: zlib.h:813
FT_UShort end_glyph
Definition: tttypes.h:665
FT_UShort image_format
Definition: tttypes.h:595
FT_Pos descender
Definition: freetype.h:1376
FT_Int num_ranges
Definition: tttypes.h:655
FT_UShort x_ppem
Definition: freetype.h:1369
FT_BEGIN_HEADER tt_face_load_eblc(TT_Face face, FT_Stream stream)
Definition: ttsbit0.c:43
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
int width
Definition: ftimage.h:313
#define FT_BOOL(x)
Definition: fttypes.h:574
FT_FaceRec root
Definition: tttypes.h:1260
#define FT_FRAME_EXIT()
Definition: ftstream.h:514
FT_ULong table_offset
Definition: tttypes.h:605
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:290
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:489
#define FT_STREAM_POS()
Definition: ftstream.h:486
TT_SBit_Range sbit_ranges
Definition: tttypes.h:656
signed long FT_Fixed
Definition: fttypes.h:284
FT_UShort * glyph_codes
Definition: tttypes.h:603
#define FT_FRAME_ULONG(f)
Definition: ftstream.h:121
FT_GlyphSlot glyph
Definition: freetype.h:956
unsigned int FT_UInt
Definition: fttypes.h:227
#define FT_FRAME_SKIP_LONG
Definition: ftstream.h:136
GLenum target
#define FT_FRAME_BYTE(f)
Definition: ftstream.h:126
#define FT_FRAME_CHAR(f)
Definition: ftstream.h:127
char pixel_mode
Definition: ftimage.h:317
tt_face_free_eblc(TT_Face face)
Definition: ttsbit0.c:110
FT_UShort index_format
Definition: tttypes.h:594
GLuint GLuint GLsizei count
#define FT_GET_ULONG()
Definition: ftstream.h:293
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:510
FT_ULong image_offset
Definition: tttypes.h:596
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
#define FT_GET_LONG()
Definition: ftstream.h:292
unsigned short FT_UShort
Definition: fttypes.h:205
#define FT_MEM_MOVE(dest, source, count)
Definition: ftmemory.h:205
GLsizeiptr size
int bit_depth
Definition: readpng.c:72
#define FT_FRAME_START(size)
Definition: ftstream.h:117
GLint limit
FT_Byte vertAdvance
Definition: tttypes.h:446
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:236
FT_ULong image_size
Definition: tttypes.h:598
FT_Memory memory
Definition: freetype.h:963
tt_face_load_strike_metrics(TT_Face face, FT_ULong strike_index, FT_Size_Metrics *metrics)
Definition: ttsbit0.c:131
FT_UShort y_ppem
Definition: freetype.h:1370
#define TTAG_EBDT
Definition: tttags.h:49