[FREETYPE] Update to v2.6.2. CORE-10614
[reactos.git] / reactos / lib / 3rdparty / freetype / src / pfr / pfrsbit.c
1 /***************************************************************************/
2 /* */
3 /* pfrsbit.c */
4 /* */
5 /* FreeType PFR bitmap loader (body). */
6 /* */
7 /* Copyright 2002-2015 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_UInt width; /* width in pixels/bits */
43 FT_UInt rows; /* number of remaining rows to scan */
44 FT_UInt 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 * (FT_Int)( 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_UInt n, reload;
74 FT_UInt 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_UInt)( 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 phase, count, counts[2];
128 FT_UInt n, reload;
129 FT_UInt left = writer->width;
130 FT_Byte* cur = writer->line;
131 FT_UInt mask = 0x80;
132 FT_UInt c = 0;
133
134
135 n = writer->total;
136
137 phase = 1;
138 counts[0] = 0;
139 counts[1] = 0;
140 count = 0;
141 reload = 1;
142
143 for ( ; n > 0; n-- )
144 {
145 if ( reload )
146 {
147 do
148 {
149 if ( phase )
150 {
151 FT_Int v;
152
153
154 if ( p >= limit )
155 break;
156
157 v = *p++;
158 counts[0] = v >> 4;
159 counts[1] = v & 15;
160 phase = 0;
161 count = counts[0];
162 }
163 else
164 {
165 phase = 1;
166 count = counts[1];
167 }
168
169 } while ( count == 0 );
170 }
171
172 if ( phase )
173 c |= mask;
174
175 mask >>= 1;
176
177 if ( --left <= 0 )
178 {
179 cur[0] = (FT_Byte)c;
180 left = writer->width;
181 mask = 0x80;
182
183 writer->line += writer->pitch;
184 cur = writer->line;
185 c = 0;
186 }
187 else if ( mask == 0 )
188 {
189 cur[0] = (FT_Byte)c;
190 mask = 0x80;
191 c = 0;
192 cur++;
193 }
194
195 reload = ( --count <= 0 );
196 }
197
198 if ( mask != 0x80 )
199 cur[0] = (FT_Byte) c;
200 }
201
202
203 static void
204 pfr_bitwriter_decode_rle2( PFR_BitWriter writer,
205 FT_Byte* p,
206 FT_Byte* limit )
207 {
208 FT_Int phase, count;
209 FT_UInt n, reload;
210 FT_UInt left = writer->width;
211 FT_Byte* cur = writer->line;
212 FT_UInt mask = 0x80;
213 FT_UInt c = 0;
214
215
216 n = writer->total;
217
218 phase = 1;
219 count = 0;
220 reload = 1;
221
222 for ( ; n > 0; n-- )
223 {
224 if ( reload )
225 {
226 do
227 {
228 if ( p >= limit )
229 break;
230
231 count = *p++;
232 phase = phase ^ 1;
233
234 } while ( count == 0 );
235 }
236
237 if ( phase )
238 c |= mask;
239
240 mask >>= 1;
241
242 if ( --left <= 0 )
243 {
244 cur[0] = (FT_Byte)c;
245 c = 0;
246 mask = 0x80;
247 left = writer->width;
248
249 writer->line += writer->pitch;
250 cur = writer->line;
251 }
252 else if ( mask == 0 )
253 {
254 cur[0] = (FT_Byte)c;
255 c = 0;
256 mask = 0x80;
257 cur++;
258 }
259
260 reload = ( --count <= 0 );
261 }
262
263 if ( mask != 0x80 )
264 cur[0] = (FT_Byte) c;
265 }
266
267
268 /*************************************************************************/
269 /*************************************************************************/
270 /***** *****/
271 /***** BITMAP DATA DECODING *****/
272 /***** *****/
273 /*************************************************************************/
274 /*************************************************************************/
275
276 static void
277 pfr_lookup_bitmap_data( FT_Byte* base,
278 FT_Byte* limit,
279 FT_UInt count,
280 FT_UInt flags,
281 FT_UInt char_code,
282 FT_ULong* found_offset,
283 FT_ULong* found_size )
284 {
285 FT_UInt left, right, char_len;
286 FT_Bool two = FT_BOOL( flags & 1 );
287 FT_Byte* buff;
288
289
290 char_len = 4;
291 if ( two ) char_len += 1;
292 if ( flags & 2 ) char_len += 1;
293 if ( flags & 4 ) char_len += 1;
294
295 left = 0;
296 right = count;
297
298 while ( left < right )
299 {
300 FT_UInt middle, code;
301
302
303 middle = ( left + right ) >> 1;
304 buff = base + middle * char_len;
305
306 /* check that we are not outside of the table -- */
307 /* this is possible with broken fonts... */
308 if ( buff + char_len > limit )
309 goto Fail;
310
311 if ( two )
312 code = PFR_NEXT_USHORT( buff );
313 else
314 code = PFR_NEXT_BYTE( buff );
315
316 if ( code == char_code )
317 goto Found_It;
318
319 if ( code < char_code )
320 left = middle;
321 else
322 right = middle;
323 }
324
325 Fail:
326 /* Not found */
327 *found_size = 0;
328 *found_offset = 0;
329 return;
330
331 Found_It:
332 if ( flags & 2 )
333 *found_size = PFR_NEXT_USHORT( buff );
334 else
335 *found_size = PFR_NEXT_BYTE( buff );
336
337 if ( flags & 4 )
338 *found_offset = PFR_NEXT_ULONG( buff );
339 else
340 *found_offset = PFR_NEXT_USHORT( buff );
341 }
342
343
344 /* load bitmap metrics. `*padvance' must be set to the default value */
345 /* before calling this function */
346 /* */
347 static FT_Error
348 pfr_load_bitmap_metrics( FT_Byte** pdata,
349 FT_Byte* limit,
350 FT_Long scaled_advance,
351 FT_Long *axpos,
352 FT_Long *aypos,
353 FT_UInt *axsize,
354 FT_UInt *aysize,
355 FT_Long *aadvance,
356 FT_UInt *aformat )
357 {
358 FT_Error error = FT_Err_Ok;
359 FT_Byte flags;
360 FT_Char c;
361 FT_Byte b;
362 FT_Byte* p = *pdata;
363 FT_Long xpos, ypos, advance;
364 FT_UInt xsize, ysize;
365
366
367 PFR_CHECK( 1 );
368 flags = PFR_NEXT_BYTE( p );
369
370 xpos = 0;
371 ypos = 0;
372 xsize = 0;
373 ysize = 0;
374 advance = 0;
375
376 switch ( flags & 3 )
377 {
378 case 0:
379 PFR_CHECK( 1 );
380 c = PFR_NEXT_INT8( p );
381 xpos = c >> 4;
382 ypos = ( (FT_Char)( c << 4 ) ) >> 4;
383 break;
384
385 case 1:
386 PFR_CHECK( 2 );
387 xpos = PFR_NEXT_INT8( p );
388 ypos = PFR_NEXT_INT8( p );
389 break;
390
391 case 2:
392 PFR_CHECK( 4 );
393 xpos = PFR_NEXT_SHORT( p );
394 ypos = PFR_NEXT_SHORT( p );
395 break;
396
397 case 3:
398 PFR_CHECK( 6 );
399 xpos = PFR_NEXT_LONG( p );
400 ypos = PFR_NEXT_LONG( p );
401 break;
402
403 default:
404 ;
405 }
406
407 flags >>= 2;
408 switch ( flags & 3 )
409 {
410 case 0:
411 /* blank image */
412 xsize = 0;
413 ysize = 0;
414 break;
415
416 case 1:
417 PFR_CHECK( 1 );
418 b = PFR_NEXT_BYTE( p );
419 xsize = ( b >> 4 ) & 0xF;
420 ysize = b & 0xF;
421 break;
422
423 case 2:
424 PFR_CHECK( 2 );
425 xsize = PFR_NEXT_BYTE( p );
426 ysize = PFR_NEXT_BYTE( p );
427 break;
428
429 case 3:
430 PFR_CHECK( 4 );
431 xsize = PFR_NEXT_USHORT( p );
432 ysize = PFR_NEXT_USHORT( p );
433 break;
434
435 default:
436 ;
437 }
438
439 flags >>= 2;
440 switch ( flags & 3 )
441 {
442 case 0:
443 advance = scaled_advance;
444 break;
445
446 case 1:
447 PFR_CHECK( 1 );
448 advance = PFR_NEXT_INT8( p ) << 8;
449 break;
450
451 case 2:
452 PFR_CHECK( 2 );
453 advance = PFR_NEXT_SHORT( p );
454 break;
455
456 case 3:
457 PFR_CHECK( 3 );
458 advance = PFR_NEXT_LONG( p );
459 break;
460
461 default:
462 ;
463 }
464
465 *axpos = xpos;
466 *aypos = ypos;
467 *axsize = xsize;
468 *aysize = ysize;
469 *aadvance = advance;
470 *aformat = flags >> 2;
471 *pdata = p;
472
473 Exit:
474 return error;
475
476 Too_Short:
477 error = FT_THROW( Invalid_Table );
478 FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
479 goto Exit;
480 }
481
482
483 static FT_Error
484 pfr_load_bitmap_bits( FT_Byte* p,
485 FT_Byte* limit,
486 FT_UInt format,
487 FT_Bool decreasing,
488 FT_Bitmap* target )
489 {
490 FT_Error error = FT_Err_Ok;
491 PFR_BitWriterRec writer;
492
493
494 if ( target->rows > 0 && target->width > 0 )
495 {
496 pfr_bitwriter_init( &writer, target, decreasing );
497
498 switch ( format )
499 {
500 case 0: /* packed bits */
501 pfr_bitwriter_decode_bytes( &writer, p, limit );
502 break;
503
504 case 1: /* RLE1 */
505 pfr_bitwriter_decode_rle1( &writer, p, limit );
506 break;
507
508 case 2: /* RLE2 */
509 pfr_bitwriter_decode_rle2( &writer, p, limit );
510 break;
511
512 default:
513 ;
514 }
515 }
516
517 return error;
518 }
519
520
521 /*************************************************************************/
522 /*************************************************************************/
523 /***** *****/
524 /***** BITMAP LOADING *****/
525 /***** *****/
526 /*************************************************************************/
527 /*************************************************************************/
528
529 FT_LOCAL( FT_Error )
530 pfr_slot_load_bitmap( PFR_Slot glyph,
531 PFR_Size size,
532 FT_UInt glyph_index )
533 {
534 FT_Error error;
535 PFR_Face face = (PFR_Face) glyph->root.face;
536 FT_Stream stream = face->root.stream;
537 PFR_PhyFont phys = &face->phy_font;
538 FT_ULong gps_offset;
539 FT_ULong gps_size;
540 PFR_Char character;
541 PFR_Strike strike;
542
543
544 character = &phys->chars[glyph_index];
545
546 /* look up a bitmap strike corresponding to the current */
547 /* character dimensions */
548 {
549 FT_UInt n;
550
551
552 strike = phys->strikes;
553 for ( n = 0; n < phys->num_strikes; n++ )
554 {
555 if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
556 strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
557 goto Found_Strike;
558
559 strike++;
560 }
561
562 /* couldn't find it */
563 return FT_THROW( Invalid_Argument );
564 }
565
566 Found_Strike:
567
568 /* now look up 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 (FT_Long)phys->outline_resolution,
613 (FT_Long)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 (FT_Long)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 * Before allocating the target bitmap, we check whether the given
636 * bitmap dimensions are valid, depending on the image format.
637 *
638 * Format 0: We have a stream of pixels (with 8 pixels per byte).
639 *
640 * (xsize * ysize + 7) / 8 <= gps_size
641 *
642 * Format 1: Run-length encoding; the high nibble holds the number of
643 * white bits, the low nibble the number of black bits. In
644 * other words, a single byte can represent at most 15
645 * pixels.
646 *
647 * xsize * ysize <= 15 * gps_size
648 *
649 * Format 2: Run-length encoding; the high byte holds the number of
650 * white bits, the low byte the number of black bits. In
651 * other words, two bytes can represent at most 255 pixels.
652 *
653 * xsize * ysize <= 255 * (gps_size + 1) / 2
654 */
655 switch ( format )
656 {
657 case 0:
658 if ( ( (FT_ULong)xsize * ysize + 7 ) / 8 > gps_size )
659 error = FT_THROW( Invalid_Table );
660 break;
661 case 1:
662 if ( (FT_ULong)xsize * ysize > 15 * gps_size )
663 error = FT_THROW( Invalid_Table );
664 break;
665 case 2:
666 if ( (FT_ULong)xsize * ysize > 255 * ( ( gps_size + 1 ) / 2 ) )
667 error = FT_THROW( Invalid_Table );
668 break;
669 default:
670 FT_ERROR(( "pfr_slot_load_bitmap: invalid image type\n" ));
671 error = FT_THROW( Invalid_Table );
672 }
673
674 if ( error )
675 {
676 if ( FT_ERR_EQ( error, Invalid_Table ) )
677 FT_ERROR(( "pfr_slot_load_bitmap: invalid bitmap dimensions\n" ));
678 goto Exit;
679 }
680
681 /*
682 * XXX: on 16bit systems we return an error for huge bitmaps
683 * that cause size truncation, because truncated
684 * size properties make bitmap glyphs broken.
685 */
686 if ( xpos > FT_INT_MAX ||
687 xpos < FT_INT_MIN ||
688 ysize > FT_INT_MAX ||
689 ypos > FT_INT_MAX - (FT_Long)ysize ||
690 ypos + (FT_Long)ysize < FT_INT_MIN )
691 {
692 FT_TRACE1(( "pfr_slot_load_bitmap:" ));
693 FT_TRACE1(( "huge bitmap glyph %dx%d over FT_GlyphSlot\n",
694 xpos, ypos ));
695 error = FT_THROW( Invalid_Pixel_Size );
696 }
697
698 if ( !error )
699 {
700 glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
701
702 /* Set up glyph bitmap and metrics */
703
704 /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
705 glyph->root.bitmap.width = xsize;
706 glyph->root.bitmap.rows = ysize;
707 glyph->root.bitmap.pitch = (FT_Int)( xsize + 7 ) >> 3;
708 glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
709
710 /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
711 glyph->root.metrics.width = (FT_Pos)xsize << 6;
712 glyph->root.metrics.height = (FT_Pos)ysize << 6;
713 glyph->root.metrics.horiBearingX = xpos << 6;
714 glyph->root.metrics.horiBearingY = ypos << 6;
715 glyph->root.metrics.horiAdvance = FT_PIX_ROUND( ( advance >> 2 ) );
716 glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
717 glyph->root.metrics.vertBearingY = 0;
718 glyph->root.metrics.vertAdvance = size->root.metrics.height;
719
720 /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */
721 glyph->root.bitmap_left = (FT_Int)xpos;
722 glyph->root.bitmap_top = (FT_Int)( ypos + (FT_Long)ysize );
723
724 /* Allocate and read bitmap data */
725 {
726 FT_ULong len = (FT_ULong)glyph->root.bitmap.pitch * ysize;
727
728
729 error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
730 if ( !error )
731 error = pfr_load_bitmap_bits(
732 p,
733 stream->limit,
734 format,
735 FT_BOOL(face->header.color_flags & 2),
736 &glyph->root.bitmap );
737 }
738 }
739
740 FT_FRAME_EXIT();
741 }
742
743 Exit:
744 return error;
745 }
746
747
748 /* END */