[FREETYPE]
[reactos.git] / reactos / lib / 3rdparty / freetype / src / base / ftbitmap.c
1 /***************************************************************************/
2 /* */
3 /* ftbitmap.c */
4 /* */
5 /* FreeType utility functions for bitmaps (body). */
6 /* */
7 /* Copyright 2004-2009, 2011, 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 <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21
22 #include FT_BITMAP_H
23 #include FT_IMAGE_H
24 #include FT_INTERNAL_OBJECTS_H
25
26
27 static
28 const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
29
30
31 /* documentation is in ftbitmap.h */
32
33 FT_EXPORT_DEF( void )
34 FT_Bitmap_New( FT_Bitmap *abitmap )
35 {
36 *abitmap = null_bitmap;
37 }
38
39
40 /* documentation is in ftbitmap.h */
41
42 FT_EXPORT_DEF( FT_Error )
43 FT_Bitmap_Copy( FT_Library library,
44 const FT_Bitmap *source,
45 FT_Bitmap *target)
46 {
47 FT_Memory memory = library->memory;
48 FT_Error error = FT_Err_Ok;
49 FT_Int pitch = source->pitch;
50 FT_ULong size;
51
52
53 if ( source == target )
54 return FT_Err_Ok;
55
56 if ( source->buffer == NULL )
57 {
58 *target = *source;
59
60 return FT_Err_Ok;
61 }
62
63 if ( pitch < 0 )
64 pitch = -pitch;
65 size = (FT_ULong)( pitch * source->rows );
66
67 if ( target->buffer )
68 {
69 FT_Int target_pitch = target->pitch;
70 FT_ULong target_size;
71
72
73 if ( target_pitch < 0 )
74 target_pitch = -target_pitch;
75 target_size = (FT_ULong)( target_pitch * target->rows );
76
77 if ( target_size != size )
78 (void)FT_QREALLOC( target->buffer, target_size, size );
79 }
80 else
81 (void)FT_QALLOC( target->buffer, size );
82
83 if ( !error )
84 {
85 unsigned char *p;
86
87
88 p = target->buffer;
89 *target = *source;
90 target->buffer = p;
91
92 FT_MEM_COPY( target->buffer, source->buffer, size );
93 }
94
95 return error;
96 }
97
98
99 static FT_Error
100 ft_bitmap_assure_buffer( FT_Memory memory,
101 FT_Bitmap* bitmap,
102 FT_UInt xpixels,
103 FT_UInt ypixels )
104 {
105 FT_Error error;
106 int pitch;
107 int new_pitch;
108 FT_UInt bpp;
109 FT_Int i, width, height;
110 unsigned char* buffer = NULL;
111
112
113 width = bitmap->width;
114 height = bitmap->rows;
115 pitch = bitmap->pitch;
116 if ( pitch < 0 )
117 pitch = -pitch;
118
119 switch ( bitmap->pixel_mode )
120 {
121 case FT_PIXEL_MODE_MONO:
122 bpp = 1;
123 new_pitch = ( width + xpixels + 7 ) >> 3;
124 break;
125 case FT_PIXEL_MODE_GRAY2:
126 bpp = 2;
127 new_pitch = ( width + xpixels + 3 ) >> 2;
128 break;
129 case FT_PIXEL_MODE_GRAY4:
130 bpp = 4;
131 new_pitch = ( width + xpixels + 1 ) >> 1;
132 break;
133 case FT_PIXEL_MODE_GRAY:
134 case FT_PIXEL_MODE_LCD:
135 case FT_PIXEL_MODE_LCD_V:
136 bpp = 8;
137 new_pitch = ( width + xpixels );
138 break;
139 default:
140 return FT_THROW( Invalid_Glyph_Format );
141 }
142
143 /* if no need to allocate memory */
144 if ( ypixels == 0 && new_pitch <= pitch )
145 {
146 /* zero the padding */
147 FT_Int bit_width = pitch * 8;
148 FT_Int bit_last = ( width + xpixels ) * bpp;
149
150
151 if ( bit_last < bit_width )
152 {
153 FT_Byte* line = bitmap->buffer + ( bit_last >> 3 );
154 FT_Byte* end = bitmap->buffer + pitch;
155 FT_Int shift = bit_last & 7;
156 FT_UInt mask = 0xFF00U >> shift;
157 FT_Int count = height;
158
159
160 for ( ; count > 0; count--, line += pitch, end += pitch )
161 {
162 FT_Byte* write = line;
163
164
165 if ( shift > 0 )
166 {
167 write[0] = (FT_Byte)( write[0] & mask );
168 write++;
169 }
170 if ( write < end )
171 FT_MEM_ZERO( write, end-write );
172 }
173 }
174
175 return FT_Err_Ok;
176 }
177
178 if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )
179 return error;
180
181 if ( bitmap->pitch > 0 )
182 {
183 FT_Int len = ( width * bpp + 7 ) >> 3;
184
185
186 for ( i = 0; i < bitmap->rows; i++ )
187 FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),
188 bitmap->buffer + pitch * i, len );
189 }
190 else
191 {
192 FT_Int len = ( width * bpp + 7 ) >> 3;
193
194
195 for ( i = 0; i < bitmap->rows; i++ )
196 FT_MEM_COPY( buffer + new_pitch * i,
197 bitmap->buffer + pitch * i, len );
198 }
199
200 FT_FREE( bitmap->buffer );
201 bitmap->buffer = buffer;
202
203 if ( bitmap->pitch < 0 )
204 new_pitch = -new_pitch;
205
206 /* set pitch only, width and height are left untouched */
207 bitmap->pitch = new_pitch;
208
209 return FT_Err_Ok;
210 }
211
212
213 /* documentation is in ftbitmap.h */
214
215 FT_EXPORT_DEF( FT_Error )
216 FT_Bitmap_Embolden( FT_Library library,
217 FT_Bitmap* bitmap,
218 FT_Pos xStrength,
219 FT_Pos yStrength )
220 {
221 FT_Error error;
222 unsigned char* p;
223 FT_Int i, x, y, pitch;
224 FT_Int xstr, ystr;
225
226
227 if ( !library )
228 return FT_THROW( Invalid_Library_Handle );
229
230 if ( !bitmap || !bitmap->buffer )
231 return FT_THROW( Invalid_Argument );
232
233 if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
234 ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
235 return FT_THROW( Invalid_Argument );
236
237 xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
238 ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;
239
240 if ( xstr == 0 && ystr == 0 )
241 return FT_Err_Ok;
242 else if ( xstr < 0 || ystr < 0 )
243 return FT_THROW( Invalid_Argument );
244
245 switch ( bitmap->pixel_mode )
246 {
247 case FT_PIXEL_MODE_GRAY2:
248 case FT_PIXEL_MODE_GRAY4:
249 {
250 FT_Bitmap tmp;
251 FT_Int align;
252
253
254 if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )
255 align = ( bitmap->width + xstr + 3 ) / 4;
256 else
257 align = ( bitmap->width + xstr + 1 ) / 2;
258
259 FT_Bitmap_New( &tmp );
260
261 error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
262 if ( error )
263 return error;
264
265 FT_Bitmap_Done( library, bitmap );
266 *bitmap = tmp;
267 }
268 break;
269
270 case FT_PIXEL_MODE_MONO:
271 if ( xstr > 8 )
272 xstr = 8;
273 break;
274
275 case FT_PIXEL_MODE_LCD:
276 xstr *= 3;
277 break;
278
279 case FT_PIXEL_MODE_LCD_V:
280 ystr *= 3;
281 break;
282
283 case FT_PIXEL_MODE_BGRA:
284 /* We don't embolden color glyphs. */
285 return FT_Err_Ok;
286 }
287
288 error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
289 if ( error )
290 return error;
291
292 pitch = bitmap->pitch;
293 if ( pitch > 0 )
294 p = bitmap->buffer + pitch * ystr;
295 else
296 {
297 pitch = -pitch;
298 p = bitmap->buffer + pitch * ( bitmap->rows - 1 );
299 }
300
301 /* for each row */
302 for ( y = 0; y < bitmap->rows ; y++ )
303 {
304 /*
305 * Horizontally:
306 *
307 * From the last pixel on, make each pixel or'ed with the
308 * `xstr' pixels before it.
309 */
310 for ( x = pitch - 1; x >= 0; x-- )
311 {
312 unsigned char tmp;
313
314
315 tmp = p[x];
316 for ( i = 1; i <= xstr; i++ )
317 {
318 if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
319 {
320 p[x] |= tmp >> i;
321
322 /* the maximum value of 8 for `xstr' comes from here */
323 if ( x > 0 )
324 p[x] |= p[x - 1] << ( 8 - i );
325
326 #if 0
327 if ( p[x] == 0xff )
328 break;
329 #endif
330 }
331 else
332 {
333 if ( x - i >= 0 )
334 {
335 if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
336 {
337 p[x] = (unsigned char)(bitmap->num_grays - 1);
338 break;
339 }
340 else
341 {
342 p[x] = (unsigned char)(p[x] + p[x-i]);
343 if ( p[x] == bitmap->num_grays - 1 )
344 break;
345 }
346 }
347 else
348 break;
349 }
350 }
351 }
352
353 /*
354 * Vertically:
355 *
356 * Make the above `ystr' rows or'ed with it.
357 */
358 for ( x = 1; x <= ystr; x++ )
359 {
360 unsigned char* q;
361
362
363 q = p - bitmap->pitch * x;
364 for ( i = 0; i < pitch; i++ )
365 q[i] |= p[i];
366 }
367
368 p += bitmap->pitch;
369 }
370
371 bitmap->width += xstr;
372 bitmap->rows += ystr;
373
374 return FT_Err_Ok;
375 }
376
377
378 FT_Byte
379 ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra )
380 {
381 FT_Long a = bgra[3];
382 FT_Long b = bgra[0];
383 FT_Long g = bgra[1];
384 FT_Long r = bgra[2];
385 FT_Long l;
386
387
388 /*
389 * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722
390 * coefficients for RGB channels *on the linear colors*.
391 * A gamma of 2.2 is fair to assume. And then, we need to
392 * undo the premultiplication too.
393 *
394 * http://accessibility.kde.org/hsl-adjusted.php
395 *
396 * We do the computation with integers only.
397 */
398
399 /* Undo premultification, get the number in a 16.16 form. */
400 b = FT_MulDiv( b, 65536, a );
401 g = FT_MulDiv( g, 65536, a );
402 r = FT_MulDiv( r, 65536, a );
403 a = a * 256;
404
405 /* Apply gamma of 2.0 instead of 2.2. */
406 b = FT_MulFix( b, b );
407 g = FT_MulFix( g, g );
408 r = FT_MulFix( r, r );
409
410 /* Apply coefficients. */
411 b = FT_MulFix( b, 4731 /* 0.0722 * 65536 */ );
412 g = FT_MulFix( g, 46871 /* 0.7152 * 65536 */ );
413 r = FT_MulFix( r, 13933 /* 0.2126 * 65536 */ );
414
415 l = r + g + b;
416
417 /*
418 * Final transparency can be determined this way:
419 *
420 * - If alpha is zero, we want 0.
421 * - If alpha is zero and luminosity is zero, we want 255.
422 * - If alpha is zero and luminosity is one, we want 0.
423 *
424 * So the formula is a * (1 - l).
425 */
426
427 return (FT_Byte)( FT_MulFix( 65535 - l, a ) >> 8 );
428 }
429
430
431 /* documentation is in ftbitmap.h */
432
433 FT_EXPORT_DEF( FT_Error )
434 FT_Bitmap_Convert( FT_Library library,
435 const FT_Bitmap *source,
436 FT_Bitmap *target,
437 FT_Int alignment )
438 {
439 FT_Error error = FT_Err_Ok;
440 FT_Memory memory;
441
442
443 if ( !library )
444 return FT_THROW( Invalid_Library_Handle );
445
446 memory = library->memory;
447
448 switch ( source->pixel_mode )
449 {
450 case FT_PIXEL_MODE_MONO:
451 case FT_PIXEL_MODE_GRAY:
452 case FT_PIXEL_MODE_GRAY2:
453 case FT_PIXEL_MODE_GRAY4:
454 case FT_PIXEL_MODE_LCD:
455 case FT_PIXEL_MODE_LCD_V:
456 case FT_PIXEL_MODE_BGRA:
457 {
458 FT_Int pad;
459 FT_Long old_size;
460
461
462 old_size = target->rows * target->pitch;
463 if ( old_size < 0 )
464 old_size = -old_size;
465
466 target->pixel_mode = FT_PIXEL_MODE_GRAY;
467 target->rows = source->rows;
468 target->width = source->width;
469
470 pad = 0;
471 if ( alignment > 0 )
472 {
473 pad = source->width % alignment;
474 if ( pad != 0 )
475 pad = alignment - pad;
476 }
477
478 target->pitch = source->width + pad;
479
480 if ( target->pitch > 0 &&
481 (FT_ULong)target->rows > FT_ULONG_MAX / target->pitch )
482 return FT_THROW( Invalid_Argument );
483
484 if ( target->rows * target->pitch > old_size &&
485 FT_QREALLOC( target->buffer,
486 old_size, target->rows * target->pitch ) )
487 return error;
488 }
489 break;
490
491 default:
492 error = FT_THROW( Invalid_Argument );
493 }
494
495 switch ( source->pixel_mode )
496 {
497 case FT_PIXEL_MODE_MONO:
498 {
499 FT_Byte* s = source->buffer;
500 FT_Byte* t = target->buffer;
501 FT_Int i;
502
503
504 target->num_grays = 2;
505
506 for ( i = source->rows; i > 0; i-- )
507 {
508 FT_Byte* ss = s;
509 FT_Byte* tt = t;
510 FT_Int j;
511
512
513 /* get the full bytes */
514 for ( j = source->width >> 3; j > 0; j-- )
515 {
516 FT_Int val = ss[0]; /* avoid a byte->int cast on each line */
517
518 tt[0] = (FT_Byte)( ( val & 0x80 ) ? 0xff : 0);
519 tt[1] = (FT_Byte)( ( val & 0x40 ) ? 0xff : 0);
520 tt[2] = (FT_Byte)( ( val & 0x20 ) ? 0xff : 0);
521 tt[3] = (FT_Byte)( ( val & 0x10 ) ? 0xff : 0);
522 tt[4] = (FT_Byte)( ( val & 0x08 ) ? 0xff : 0);
523 tt[5] = (FT_Byte)( ( val & 0x04 ) ? 0xff : 0);
524 tt[6] = (FT_Byte)( ( val & 0x02 ) ? 0xff : 0);
525 tt[7] = (FT_Byte)( ( val & 0x01 ) ? 0xff : 0);
526
527
528 tt += 8;
529 ss += 1;
530 }
531
532 /* get remaining pixels (if any) */
533 j = source->width & 7;
534 if ( j > 0 )
535 {
536 FT_Int val = *ss;
537
538
539 for ( ; j > 0; j-- )
540 {
541 tt[0] = (FT_Byte)( ( val & 0x80 ) ? 0xff : 0);
542 val <<= 1;
543 tt += 1;
544 }
545 }
546
547 s += source->pitch;
548 t += target->pitch;
549 }
550 }
551 break;
552
553
554 case FT_PIXEL_MODE_GRAY:
555 case FT_PIXEL_MODE_LCD:
556 case FT_PIXEL_MODE_LCD_V:
557 {
558 FT_Int width = source->width;
559 FT_Byte* s = source->buffer;
560 FT_Byte* t = target->buffer;
561 FT_Int s_pitch = source->pitch;
562 FT_Int t_pitch = target->pitch;
563 FT_Int i;
564
565
566 target->num_grays = 256;
567
568 for ( i = source->rows; i > 0; i-- )
569 {
570 FT_ARRAY_COPY( t, s, width );
571
572 s += s_pitch;
573 t += t_pitch;
574 }
575 }
576 break;
577
578
579 case FT_PIXEL_MODE_GRAY2:
580 {
581 FT_Byte* s = source->buffer;
582 FT_Byte* t = target->buffer;
583 FT_Int i;
584
585
586 target->num_grays = 4;
587
588 for ( i = source->rows; i > 0; i-- )
589 {
590 FT_Byte* ss = s;
591 FT_Byte* tt = t;
592 FT_Int j;
593
594
595 /* get the full bytes */
596 for ( j = source->width >> 2; j > 0; j-- )
597 {
598 FT_Int val = ss[0];
599
600
601 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
602 tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
603 tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
604 tt[3] = (FT_Byte)( ( val & 0x03 ) );
605
606 ss += 1;
607 tt += 4;
608 }
609
610 j = source->width & 3;
611 if ( j > 0 )
612 {
613 FT_Int val = ss[0];
614
615
616 for ( ; j > 0; j-- )
617 {
618 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
619 val <<= 2;
620 tt += 1;
621 }
622 }
623
624 s += source->pitch;
625 t += target->pitch;
626 }
627 }
628 break;
629
630
631 case FT_PIXEL_MODE_GRAY4:
632 {
633 FT_Byte* s = source->buffer;
634 FT_Byte* t = target->buffer;
635 FT_Int i;
636
637
638 target->num_grays = 16;
639
640 for ( i = source->rows; i > 0; i-- )
641 {
642 FT_Byte* ss = s;
643 FT_Byte* tt = t;
644 FT_Int j;
645
646
647 /* get the full bytes */
648 for ( j = source->width >> 1; j > 0; j-- )
649 {
650 FT_Int val = ss[0];
651
652
653 tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
654 tt[1] = (FT_Byte)( ( val & 0x0F ) );
655
656 ss += 1;
657 tt += 2;
658 }
659
660 if ( source->width & 1 )
661 tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
662
663 s += source->pitch;
664 t += target->pitch;
665 }
666 }
667 break;
668
669 case FT_PIXEL_MODE_BGRA:
670 {
671 FT_Byte* s = source->buffer;
672 FT_Byte* t = target->buffer;
673 FT_Int s_pitch = source->pitch;
674 FT_Int t_pitch = target->pitch;
675 FT_Int i;
676
677
678 target->num_grays = 256;
679
680 for ( i = source->rows; i > 0; i-- )
681 {
682 FT_Byte* ss = s;
683 FT_Byte* tt = t;
684 FT_Int j;
685
686
687 for ( j = source->width; j > 0; j-- )
688 {
689 tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss );
690
691 ss += 4;
692 tt += 1;
693 }
694
695 s += s_pitch;
696 t += t_pitch;
697 }
698 }
699 break;
700
701 default:
702 ;
703 }
704
705 return error;
706 }
707
708
709 /* documentation is in ftbitmap.h */
710
711 FT_EXPORT_DEF( FT_Error )
712 FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot )
713 {
714 if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP &&
715 !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
716 {
717 FT_Bitmap bitmap;
718 FT_Error error;
719
720
721 FT_Bitmap_New( &bitmap );
722 error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
723 if ( error )
724 return error;
725
726 slot->bitmap = bitmap;
727 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
728 }
729
730 return FT_Err_Ok;
731 }
732
733
734 /* documentation is in ftbitmap.h */
735
736 FT_EXPORT_DEF( FT_Error )
737 FT_Bitmap_Done( FT_Library library,
738 FT_Bitmap *bitmap )
739 {
740 FT_Memory memory;
741
742
743 if ( !library )
744 return FT_THROW( Invalid_Library_Handle );
745
746 if ( !bitmap )
747 return FT_THROW( Invalid_Argument );
748
749 memory = library->memory;
750
751 FT_FREE( bitmap->buffer );
752 *bitmap = null_bitmap;
753
754 return FT_Err_Ok;
755 }
756
757
758 /* END */