blob: 52bc2c8c39affe3189b6311e396a012f90b0d518 [file] [log] [blame]
Werner Lembergeacb9302002-10-07 10:12:43 +00001/***************************************************************************/
2/* */
3/* pfrsbit.c */
4/* */
5/* FreeType PFR bitmap loader (body). */
6/* */
Werner Lembergf765e442010-06-24 10:34:29 +02007/* Copyright 2002, 2003, 2006, 2009, 2010 by */
Werner Lembergeacb9302002-10-07 10:12:43 +00008/* 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
David Turner80171e02002-10-05 14:57:03 +000019#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
Werner Lembergeacb9302002-10-07 10:12:43 +000029
David Turner80171e02002-10-05 14:57:03 +000030 /*************************************************************************/
31 /*************************************************************************/
32 /***** *****/
33 /***** PFR BIT WRITER *****/
34 /***** *****/
35 /*************************************************************************/
36 /*************************************************************************/
37
Werner Lembergeacb9302002-10-07 10:12:43 +000038 typedef struct PFR_BitWriter_
David Turner80171e02002-10-05 14:57:03 +000039 {
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,
Werner Lemberg0240d292003-06-09 15:54:18 +000052 FT_Bool decreasing )
David Turner80171e02002-10-05 14:57:03 +000053 {
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
Werner Lembergeacb9302002-10-07 10:12:43 +000080
81 n = (FT_Int)( limit - p ) * 8;
David Turner80171e02002-10-05 14:57:03 +000082 if ( n > writer->total )
83 n = writer->total;
84
85 reload = n & 7;
86
87 for ( ; n > 0; n-- )
88 {
Werner Lembergeacb9302002-10-07 10:12:43 +000089 if ( ( n & 7 ) == reload )
David Turner80171e02002-10-05 14:57:03 +000090 val = *p++;
91
92 if ( val & 0x80 )
93 c |= mask;
94
95 val <<= 1;
96 mask >>= 1;
97
98 if ( --left <= 0 )
99 {
Werner Lembergeacb9302002-10-07 10:12:43 +0000100 cur[0] = (FT_Byte)c;
David Turner80171e02002-10-05 14:57:03 +0000101 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 {
David Turner4bdf4352003-01-30 23:24:18 +0000110 cur[0] = (FT_Byte)c;
David Turner80171e02002-10-05 14:57:03 +0000111 mask = 0x80;
112 c = 0;
113 cur ++;
114 }
115 }
116
117 if ( mask != 0x80 )
Werner Lemberg2e573432003-04-23 14:14:06 +0000118 cur[0] = (FT_Byte)c;
David Turner80171e02002-10-05 14:57:03 +0000119 }
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
Werner Lembergeacb9302002-10-07 10:12:43 +0000133
David Turner80171e02002-10-05 14:57:03 +0000134 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
Werner Lembergeacb9302002-10-07 10:12:43 +0000152
David Turner80171e02002-10-05 14:57:03 +0000153 if ( p >= limit )
154 break;
155
156 v = *p++;
Werner Lembergeacb9302002-10-07 10:12:43 +0000157 counts[0] = v >> 4;
158 counts[1] = v & 15;
David Turner80171e02002-10-05 14:57:03 +0000159 phase = 0;
160 count = counts[0];
161 }
162 else
163 {
164 phase = 1;
165 count = counts[1];
166 }
Werner Lembergeacb9302002-10-07 10:12:43 +0000167
168 } while ( count == 0 );
David Turner80171e02002-10-05 14:57:03 +0000169 }
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 {
Werner Lemberg2e573432003-04-23 14:14:06 +0000188 cur[0] = (FT_Byte)c;
David Turner80171e02002-10-05 14:57:03 +0000189 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
Werner Lembergeacb9302002-10-07 10:12:43 +0000213
David Turner80171e02002-10-05 14:57:03 +0000214 n = writer->total;
215
Werner Lembergeacb9302002-10-07 10:12:43 +0000216 phase = 1;
217 count = 0;
218 reload = 1;
David Turner80171e02002-10-05 14:57:03 +0000219
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;
Werner Lembergeacb9302002-10-07 10:12:43 +0000231
232 } while ( count == 0 );
David Turner80171e02002-10-05 14:57:03 +0000233 }
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 {
Werner Lemberg2e573432003-04-23 14:14:06 +0000252 cur[0] = (FT_Byte)c;
David Turner80171e02002-10-05 14:57:03 +0000253 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
Werner Lembergeacb9302002-10-07 10:12:43 +0000275 pfr_lookup_bitmap_data( FT_Byte* base,
276 FT_Byte* limit,
Werner Lemberg0240d292003-06-09 15:54:18 +0000277 FT_UInt count,
278 FT_UInt flags,
Werner Lembergeacb9302002-10-07 10:12:43 +0000279 FT_UInt char_code,
280 FT_ULong* found_offset,
281 FT_ULong* found_size )
David Turner80171e02002-10-05 14:57:03 +0000282 {
Werner Lembergeacb9302002-10-07 10:12:43 +0000283 FT_UInt left, right, char_len;
David Turner4bdf4352003-01-30 23:24:18 +0000284 FT_Bool two = FT_BOOL( flags & 1 );
Werner Lembergeacb9302002-10-07 10:12:43 +0000285 FT_Byte* buff;
286
David Turner80171e02002-10-05 14:57:03 +0000287
288 char_len = 4;
Werner Lembergeacb9302002-10-07 10:12:43 +0000289 if ( two ) char_len += 1;
290 if ( flags & 2 ) char_len += 1;
291 if ( flags & 4 ) char_len += 1;
David Turner80171e02002-10-05 14:57:03 +0000292
Werner Lembergeacb9302002-10-07 10:12:43 +0000293 left = 0;
294 right = count;
David Turner80171e02002-10-05 14:57:03 +0000295
296 while ( left < right )
297 {
298 FT_UInt middle, code;
299
David Turner80171e02002-10-05 14:57:03 +0000300
Werner Lembergeacb9302002-10-07 10:12:43 +0000301 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... */
David Turner80171e02002-10-05 14:57:03 +0000306 if ( buff + char_len > limit )
307 goto Fail;
308
Werner Lembergeacb9302002-10-07 10:12:43 +0000309 if ( two )
310 code = PFR_NEXT_USHORT( buff );
311 else
312 code = PFR_NEXT_BYTE( buff );
David Turner80171e02002-10-05 14:57:03 +0000313
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:
Werner Lembergeacb9302002-10-07 10:12:43 +0000330 if ( flags & 2 )
331 *found_size = PFR_NEXT_USHORT( buff );
332 else
333 *found_size = PFR_NEXT_BYTE( buff );
David Turner80171e02002-10-05 14:57:03 +0000334
Werner Lembergeacb9302002-10-07 10:12:43 +0000335 if ( flags & 4 )
336 *found_offset = PFR_NEXT_ULONG( buff );
337 else
338 *found_offset = PFR_NEXT_USHORT( buff );
David Turner80171e02002-10-05 14:57:03 +0000339 }
340
341
Werner Lembergeacb9302002-10-07 10:12:43 +0000342 /* load bitmap metrics. "*padvance" must be set to the default value */
343 /* before calling this function... */
344 /* */
David Turner80171e02002-10-05 14:57:03 +0000345 static FT_Error
Werner Lembergeacb9302002-10-07 10:12:43 +0000346 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 )
David Turner80171e02002-10-05 14:57:03 +0000355 {
Werner Lembergf765e442010-06-24 10:34:29 +0200356 FT_Error error = PFR_Err_Ok;
Werner Lembergeacb9302002-10-07 10:12:43 +0000357 FT_Byte flags;
358 FT_Char b;
359 FT_Byte* p = *pdata;
360 FT_Long xpos, ypos, advance;
361 FT_UInt xsize, ysize;
David Turner80171e02002-10-05 14:57:03 +0000362
Werner Lembergeacb9302002-10-07 10:12:43 +0000363
364 PFR_CHECK( 1 );
365 flags = PFR_NEXT_BYTE( p );
David Turner80171e02002-10-05 14:57:03 +0000366
367 xpos = 0;
368 ypos = 0;
369 xsize = 0;
370 ysize = 0;
371 advance = 0;
372
Werner Lembergeacb9302002-10-07 10:12:43 +0000373 switch ( flags & 3 )
David Turner80171e02002-10-05 14:57:03 +0000374 {
Werner Lembergeacb9302002-10-07 10:12:43 +0000375 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;
David Turner80171e02002-10-05 14:57:03 +0000381
Werner Lembergeacb9302002-10-07 10:12:43 +0000382 case 1:
383 PFR_CHECK( 2 );
384 xpos = PFR_NEXT_INT8( p );
385 ypos = PFR_NEXT_INT8( p );
386 break;
David Turner80171e02002-10-05 14:57:03 +0000387
Werner Lembergeacb9302002-10-07 10:12:43 +0000388 case 2:
389 PFR_CHECK( 4 );
390 xpos = PFR_NEXT_SHORT( p );
391 ypos = PFR_NEXT_SHORT( p );
392 break;
David Turner80171e02002-10-05 14:57:03 +0000393
Werner Lembergeacb9302002-10-07 10:12:43 +0000394 case 3:
395 PFR_CHECK( 6 );
396 xpos = PFR_NEXT_LONG( p );
397 ypos = PFR_NEXT_LONG( p );
398 break;
David Turner80171e02002-10-05 14:57:03 +0000399
Werner Lembergeacb9302002-10-07 10:12:43 +0000400 default:
401 ;
David Turner80171e02002-10-05 14:57:03 +0000402 }
403
404 flags >>= 2;
Werner Lembergeacb9302002-10-07 10:12:43 +0000405 switch ( flags & 3 )
David Turner80171e02002-10-05 14:57:03 +0000406 {
Werner Lembergeacb9302002-10-07 10:12:43 +0000407 case 0:
408 /* blank image */
409 xsize = 0;
410 ysize = 0;
411 break;
David Turner80171e02002-10-05 14:57:03 +0000412
Werner Lembergeacb9302002-10-07 10:12:43 +0000413 case 1:
414 PFR_CHECK( 1 );
415 b = PFR_NEXT_BYTE( p );
416 xsize = ( b >> 4 ) & 0xF;
417 ysize = b & 0xF;
418 break;
David Turner80171e02002-10-05 14:57:03 +0000419
Werner Lembergeacb9302002-10-07 10:12:43 +0000420 case 2:
421 PFR_CHECK( 2 );
422 xsize = PFR_NEXT_BYTE( p );
423 ysize = PFR_NEXT_BYTE( p );
424 break;
David Turner80171e02002-10-05 14:57:03 +0000425
Werner Lembergeacb9302002-10-07 10:12:43 +0000426 case 3:
427 PFR_CHECK( 4 );
428 xsize = PFR_NEXT_USHORT( p );
429 ysize = PFR_NEXT_USHORT( p );
430 break;
David Turner80171e02002-10-05 14:57:03 +0000431
Werner Lembergeacb9302002-10-07 10:12:43 +0000432 default:
433 ;
David Turner80171e02002-10-05 14:57:03 +0000434 }
435
436 flags >>= 2;
Werner Lembergeacb9302002-10-07 10:12:43 +0000437 switch ( flags & 3 )
David Turner80171e02002-10-05 14:57:03 +0000438 {
Werner Lembergeacb9302002-10-07 10:12:43 +0000439 case 0:
440 advance = scaled_advance;
441 break;
David Turner80171e02002-10-05 14:57:03 +0000442
Werner Lembergeacb9302002-10-07 10:12:43 +0000443 case 1:
444 PFR_CHECK( 1 );
445 advance = PFR_NEXT_INT8( p ) << 8;
446 break;
David Turner80171e02002-10-05 14:57:03 +0000447
Werner Lembergeacb9302002-10-07 10:12:43 +0000448 case 2:
449 PFR_CHECK( 2 );
450 advance = PFR_NEXT_SHORT( p );
451 break;
David Turner80171e02002-10-05 14:57:03 +0000452
Werner Lembergeacb9302002-10-07 10:12:43 +0000453 case 3:
454 PFR_CHECK( 3 );
455 advance = PFR_NEXT_LONG( p );
456 break;
David Turner80171e02002-10-05 14:57:03 +0000457
Werner Lembergeacb9302002-10-07 10:12:43 +0000458 default:
459 ;
David Turner80171e02002-10-05 14:57:03 +0000460 }
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 = PFR_Err_Invalid_Table;
475 FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
476 goto Exit;
477 }
478
479
480 static FT_Error
Werner Lembergeacb9302002-10-07 10:12:43 +0000481 pfr_load_bitmap_bits( FT_Byte* p,
482 FT_Byte* limit,
483 FT_UInt format,
Werner Lemberg0240d292003-06-09 15:54:18 +0000484 FT_Bool decreasing,
Werner Lembergeacb9302002-10-07 10:12:43 +0000485 FT_Bitmap* target )
David Turner80171e02002-10-05 14:57:03 +0000486 {
Werner Lembergf765e442010-06-24 10:34:29 +0200487 FT_Error error = PFR_Err_Ok;
David Turner80171e02002-10-05 14:57:03 +0000488 PFR_BitWriterRec writer;
489
Werner Lembergeacb9302002-10-07 10:12:43 +0000490
David Turner80171e02002-10-05 14:57:03 +0000491 if ( target->rows > 0 && target->width > 0 )
492 {
493 pfr_bitwriter_init( &writer, target, decreasing );
494
Werner Lembergeacb9302002-10-07 10:12:43 +0000495 switch ( format )
David Turner80171e02002-10-05 14:57:03 +0000496 {
Werner Lembergeacb9302002-10-07 10:12:43 +0000497 case 0: /* packed bits */
498 pfr_bitwriter_decode_bytes( &writer, p, limit );
499 break;
David Turner80171e02002-10-05 14:57:03 +0000500
Werner Lembergeacb9302002-10-07 10:12:43 +0000501 case 1: /* RLE1 */
502 pfr_bitwriter_decode_rle1( &writer, p, limit );
503 break;
David Turner80171e02002-10-05 14:57:03 +0000504
Werner Lembergeacb9302002-10-07 10:12:43 +0000505 case 2: /* RLE2 */
506 pfr_bitwriter_decode_rle2( &writer, p, limit );
507 break;
David Turner80171e02002-10-05 14:57:03 +0000508
Werner Lembergeacb9302002-10-07 10:12:43 +0000509 default:
510 FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));
Werner Lemberg779afe42003-06-22 15:33:53 +0000511 error = PFR_Err_Invalid_File_Format;
David Turner80171e02002-10-05 14:57:03 +0000512 }
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
Werner Lembergeacb9302002-10-07 10:12:43 +0000541
David Turner80171e02002-10-05 14:57:03 +0000542 character = &phys->chars[glyph_index];
543
544 /* Look-up a bitmap strike corresponding to the current */
545 /* character dimensions */
David Turner80171e02002-10-05 14:57:03 +0000546 {
Werner Lembergeacb9302002-10-07 10:12:43 +0000547 FT_UInt n;
548
David Turner80171e02002-10-05 14:57:03 +0000549
550 strike = phys->strikes;
551 for ( n = 0; n < phys->num_strikes; n++ )
552 {
Werner Lembergeacb9302002-10-07 10:12:43 +0000553 if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
554 strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
David Turner80171e02002-10-05 14:57:03 +0000555 {
556 goto Found_Strike;
557 }
Werner Lembergeacb9302002-10-07 10:12:43 +0000558
David Turner80171e02002-10-05 14:57:03 +0000559 strike++;
560 }
561
562 /* couldn't find it */
Werner Lemberg779afe42003-06-22 15:33:53 +0000563 return PFR_Err_Invalid_Argument;
David Turner80171e02002-10-05 14:57:03 +0000564 }
565
566 Found_Strike:
567
568 /* Now lookup the glyph's position within the file */
569 {
Werner Lembergeacb9302002-10-07 10:12:43 +0000570 FT_UInt char_len;
571
David Turner80171e02002-10-05 14:57:03 +0000572
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 ) ||
Werner Lembergeacb9302002-10-07 10:12:43 +0000580 FT_FRAME_ENTER( char_len * strike->num_bitmaps ) )
David Turner80171e02002-10-05 14:57:03 +0000581 goto Exit;
582
583 pfr_lookup_bitmap_data( stream->cursor,
584 stream->limit,
585 strike->num_bitmaps,
Werner Lemberg0240d292003-06-09 15:54:18 +0000586 strike->flags,
David Turner80171e02002-10-05 14:57:03 +0000587 character->char_code,
588 &gps_offset,
589 &gps_size );
590
591 FT_FRAME_EXIT();
592
Werner Lembergeacb9302002-10-07 10:12:43 +0000593 if ( gps_size == 0 )
David Turner80171e02002-10-05 14:57:03 +0000594 {
595 /* Could not find a bitmap program string for this glyph */
Werner Lemberg779afe42003-06-22 15:33:53 +0000596 error = PFR_Err_Invalid_Argument;
David Turner80171e02002-10-05 14:57:03 +0000597 goto Exit;
598 }
599 }
600
601 /* get the bitmap metrics */
602 {
Werner Lemberg9045f5b2009-12-03 05:57:30 +0100603 FT_Long xpos = 0, ypos = 0, advance = 0;
604 FT_UInt xsize = 0, ysize = 0, format = 0;
David Turner80171e02002-10-05 14:57:03 +0000605 FT_Byte* p;
606
Werner Lembergeacb9302002-10-07 10:12:43 +0000607
David Turner1ae134a2006-02-21 16:50:17 +0000608 /* 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
Werner Lemberg5edafed2006-02-22 08:23:35 +0000617 /* compute default advance, i.e., scaled advance. This can be */
618 /* overridden in the bitmap header of certain glyphs. */
David Turner1ae134a2006-02-21 16:50:17 +0000619 advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8,
David Turner80171e02002-10-05 14:57:03 +0000620 character->advance,
621 phys->metrics_resolution );
622
David Turner80171e02002-10-05 14:57:03 +0000623 if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
Werner Lembergeacb9302002-10-07 10:12:43 +0000624 FT_FRAME_ENTER( gps_size ) )
David Turner80171e02002-10-05 14:57:03 +0000625 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 );
suzuki toshiyae866cf32009-08-01 00:32:06 +0900633
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 = PFR_Err_Invalid_Pixel_Size;
645 }
646
David Turner80171e02002-10-05 14:57:03 +0000647 if ( !error )
648 {
649 glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
David Turner4bdf4352003-01-30 23:24:18 +0000650
David Turner80171e02002-10-05 14:57:03 +0000651 /* Set up glyph bitmap and metrics */
suzuki toshiyae866cf32009-08-01 00:32:06 +0900652
653 /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
Werner Lembergeacb9302002-10-07 10:12:43 +0000654 glyph->root.bitmap.width = (FT_Int)xsize;
655 glyph->root.bitmap.rows = (FT_Int)ysize;
suzuki toshiyae866cf32009-08-01 00:32:06 +0900656 glyph->root.bitmap.pitch = (FT_Int)( xsize + 7 ) >> 3;
David Turner80171e02002-10-05 14:57:03 +0000657 glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
658
suzuki toshiyae866cf32009-08-01 00:32:06 +0900659 /* 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;
David Turner80171e02002-10-05 14:57:03 +0000662 glyph->root.metrics.horiBearingX = xpos << 6;
663 glyph->root.metrics.horiBearingY = ypos << 6;
David Turner87c0d302003-12-24 01:10:46 +0000664 glyph->root.metrics.horiAdvance = FT_PIX_ROUND( ( advance >> 2 ) );
David Turner80171e02002-10-05 14:57:03 +0000665 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
suzuki toshiyae866cf32009-08-01 00:32:06 +0900669 /* 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);
David Turner80171e02002-10-05 14:57:03 +0000672
673 /* Allocate and read bitmap data */
674 {
Werner Lemberg2e573432003-04-23 14:14:06 +0000675 FT_ULong len = glyph->root.bitmap.pitch * ysize;
676
Werner Lembergeacb9302002-10-07 10:12:43 +0000677
David Turner66cbc202003-03-20 07:04:40 +0000678 error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
679 if ( !error )
David Turner80171e02002-10-05 14:57:03 +0000680 {
Werner Lemberga259b6d2003-09-22 09:53:56 +0000681 error = pfr_load_bitmap_bits(
682 p,
683 stream->limit,
684 format,
685 FT_BOOL(face->header.color_flags & 2),
686 &glyph->root.bitmap );
David Turner80171e02002-10-05 14:57:03 +0000687 }
688 }
689 }
Werner Lembergeacb9302002-10-07 10:12:43 +0000690
David Turner80171e02002-10-05 14:57:03 +0000691 FT_FRAME_EXIT();
692 }
693
694 Exit:
695 return error;
696 }
Werner Lembergeacb9302002-10-07 10:12:43 +0000697
698/* END */