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