1 /****************************************************************************
2  *
3  * ftbitmap.c
4  *
5  *   FreeType utility functions for bitmaps (body).
6  *
7  * Copyright (C) 2004-2019 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   /**************************************************************************
28    *
29    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
30    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
31    * messages during execution.
32    */
33 #undef  FT_COMPONENT
34 #define FT_COMPONENT  bitmap
35 
36 
37   static
38   const FT_Bitmap  null_bitmap = { 0, 0, 0, NULL, 0, 0, 0, NULL };
39 
40 
41   /* documentation is in ftbitmap.h */
42 
43   FT_EXPORT_DEF( void )
FT_Bitmap_Init(FT_Bitmap * abitmap)44   FT_Bitmap_Init( FT_Bitmap  *abitmap )
45   {
46     if ( abitmap )
47       *abitmap = null_bitmap;
48   }
49 
50 
51   /* deprecated function name; retained for ABI compatibility */
52 
53   FT_EXPORT_DEF( void )
FT_Bitmap_New(FT_Bitmap * abitmap)54   FT_Bitmap_New( FT_Bitmap  *abitmap )
55   {
56     if ( abitmap )
57       *abitmap = null_bitmap;
58   }
59 
60 
61   /* documentation is in ftbitmap.h */
62 
63   FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Copy(FT_Library library,const FT_Bitmap * source,FT_Bitmap * target)64   FT_Bitmap_Copy( FT_Library        library,
65                   const FT_Bitmap  *source,
66                   FT_Bitmap        *target)
67   {
68     FT_Memory  memory;
69     FT_Error   error  = FT_Err_Ok;
70 
71     FT_Int    pitch;
72     FT_ULong  size;
73 
74     FT_Int  source_pitch_sign, target_pitch_sign;
75 
76 
77     if ( !library )
78       return FT_THROW( Invalid_Library_Handle );
79 
80     if ( !source || !target )
81       return FT_THROW( Invalid_Argument );
82 
83     if ( source == target )
84       return FT_Err_Ok;
85 
86     source_pitch_sign = source->pitch < 0 ? -1 : 1;
87     target_pitch_sign = target->pitch < 0 ? -1 : 1;
88 
89     if ( !source->buffer )
90     {
91       *target = *source;
92       if ( source_pitch_sign != target_pitch_sign )
93         target->pitch = -target->pitch;
94 
95       return FT_Err_Ok;
96     }
97 
98     memory = library->memory;
99     pitch  = source->pitch;
100 
101     if ( pitch < 0 )
102       pitch = -pitch;
103     size = (FT_ULong)pitch * source->rows;
104 
105     if ( target->buffer )
106     {
107       FT_Int    target_pitch = target->pitch;
108       FT_ULong  target_size;
109 
110 
111       if ( target_pitch < 0 )
112         target_pitch = -target_pitch;
113       target_size = (FT_ULong)target_pitch * target->rows;
114 
115       if ( target_size != size )
116         (void)FT_QREALLOC( target->buffer, target_size, size );
117     }
118     else
119       (void)FT_QALLOC( target->buffer, size );
120 
121     if ( !error )
122     {
123       unsigned char *p;
124 
125 
126       p = target->buffer;
127       *target = *source;
128       target->buffer = p;
129 
130       if ( source_pitch_sign == target_pitch_sign )
131         FT_MEM_COPY( target->buffer, source->buffer, size );
132       else
133       {
134         /* take care of bitmap flow */
135         FT_UInt   i;
136         FT_Byte*  s = source->buffer;
137         FT_Byte*  t = target->buffer;
138 
139 
140         t += (FT_ULong)pitch * ( target->rows - 1 );
141 
142         for ( i = target->rows; i > 0; i-- )
143         {
144           FT_ARRAY_COPY( t, s, pitch );
145 
146           s += pitch;
147           t -= pitch;
148         }
149       }
150     }
151 
152     return error;
153   }
154 
155 
156   /* Enlarge `bitmap' horizontally and vertically by `xpixels' */
157   /* and `ypixels', respectively.                              */
158 
159   static FT_Error
ft_bitmap_assure_buffer(FT_Memory memory,FT_Bitmap * bitmap,FT_UInt xpixels,FT_UInt ypixels)160   ft_bitmap_assure_buffer( FT_Memory   memory,
161                            FT_Bitmap*  bitmap,
162                            FT_UInt     xpixels,
163                            FT_UInt     ypixels )
164   {
165     FT_Error        error;
166     unsigned int    pitch;
167     unsigned int    new_pitch;
168     FT_UInt         bpp;
169     FT_UInt         width, height;
170     unsigned char*  buffer = NULL;
171 
172 
173     width  = bitmap->width;
174     height = bitmap->rows;
175     pitch  = (unsigned int)FT_ABS( bitmap->pitch );
176 
177     switch ( bitmap->pixel_mode )
178     {
179     case FT_PIXEL_MODE_MONO:
180       bpp       = 1;
181       new_pitch = ( width + xpixels + 7 ) >> 3;
182       break;
183     case FT_PIXEL_MODE_GRAY2:
184       bpp       = 2;
185       new_pitch = ( width + xpixels + 3 ) >> 2;
186       break;
187     case FT_PIXEL_MODE_GRAY4:
188       bpp       = 4;
189       new_pitch = ( width + xpixels + 1 ) >> 1;
190       break;
191     case FT_PIXEL_MODE_GRAY:
192     case FT_PIXEL_MODE_LCD:
193     case FT_PIXEL_MODE_LCD_V:
194       bpp       = 8;
195       new_pitch = width + xpixels;
196       break;
197     default:
198       return FT_THROW( Invalid_Glyph_Format );
199     }
200 
201     /* if no need to allocate memory */
202     if ( ypixels == 0 && new_pitch <= pitch )
203     {
204       /* zero the padding */
205       FT_UInt  bit_width = pitch * 8;
206       FT_UInt  bit_last  = ( width + xpixels ) * bpp;
207 
208 
209       if ( bit_last < bit_width )
210       {
211         FT_Byte*  line  = bitmap->buffer + ( bit_last >> 3 );
212         FT_Byte*  end   = bitmap->buffer + pitch;
213         FT_UInt   shift = bit_last & 7;
214         FT_UInt   mask  = 0xFF00U >> shift;
215         FT_UInt   count = height;
216 
217 
218         for ( ; count > 0; count--, line += pitch, end += pitch )
219         {
220           FT_Byte*  write = line;
221 
222 
223           if ( shift > 0 )
224           {
225             write[0] = (FT_Byte)( write[0] & mask );
226             write++;
227           }
228           if ( write < end )
229             FT_MEM_ZERO( write, end - write );
230         }
231       }
232 
233       return FT_Err_Ok;
234     }
235 
236     /* otherwise allocate new buffer */
237     if ( FT_QALLOC_MULT( buffer, bitmap->rows + ypixels, new_pitch ) )
238       return error;
239 
240     /* new rows get added at the top of the bitmap, */
241     /* thus take care of the flow direction         */
242     if ( bitmap->pitch > 0 )
243     {
244       FT_UInt  len = ( width * bpp + 7 ) >> 3;
245 
246       unsigned char*  in  = bitmap->buffer;
247       unsigned char*  out = buffer;
248 
249       unsigned char*  limit = bitmap->buffer + pitch * bitmap->rows;
250       unsigned int    delta = new_pitch - len;
251 
252 
253       FT_MEM_ZERO( out, new_pitch * ypixels );
254       out += new_pitch * ypixels;
255 
256       while ( in < limit )
257       {
258         FT_MEM_COPY( out, in, len );
259         in  += pitch;
260         out += len;
261 
262         /* we use FT_QALLOC_MULT, which doesn't zero out the buffer;      */
263         /* consequently, we have to manually zero out the remaining bytes */
264         FT_MEM_ZERO( out, delta );
265         out += delta;
266       }
267     }
268     else
269     {
270       FT_UInt  len = ( width * bpp + 7 ) >> 3;
271 
272       unsigned char*  in  = bitmap->buffer;
273       unsigned char*  out = buffer;
274 
275       unsigned char*  limit = bitmap->buffer + pitch * bitmap->rows;
276       unsigned int    delta = new_pitch - len;
277 
278 
279       while ( in < limit )
280       {
281         FT_MEM_COPY( out, in, len );
282         in  += pitch;
283         out += len;
284 
285         FT_MEM_ZERO( out, delta );
286         out += delta;
287       }
288 
289       FT_MEM_ZERO( out, new_pitch * ypixels );
290     }
291 
292     FT_FREE( bitmap->buffer );
293     bitmap->buffer = buffer;
294 
295     /* set pitch only, width and height are left untouched */
296     if ( bitmap->pitch < 0 )
297       bitmap->pitch = -(int)new_pitch;
298     else
299       bitmap->pitch = (int)new_pitch;
300 
301     return FT_Err_Ok;
302   }
303 
304 
305   /* documentation is in ftbitmap.h */
306 
307   FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Embolden(FT_Library library,FT_Bitmap * bitmap,FT_Pos xStrength,FT_Pos yStrength)308   FT_Bitmap_Embolden( FT_Library  library,
309                       FT_Bitmap*  bitmap,
310                       FT_Pos      xStrength,
311                       FT_Pos      yStrength )
312   {
313     FT_Error        error;
314     unsigned char*  p;
315     FT_Int          i, x, pitch;
316     FT_UInt         y;
317     FT_Int          xstr, ystr;
318 
319 
320     if ( !library )
321       return FT_THROW( Invalid_Library_Handle );
322 
323     if ( !bitmap || !bitmap->buffer )
324       return FT_THROW( Invalid_Argument );
325 
326     if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
327          ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
328       return FT_THROW( Invalid_Argument );
329 
330     xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
331     ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;
332 
333     if ( xstr == 0 && ystr == 0 )
334       return FT_Err_Ok;
335     else if ( xstr < 0 || ystr < 0 )
336       return FT_THROW( Invalid_Argument );
337 
338     switch ( bitmap->pixel_mode )
339     {
340     case FT_PIXEL_MODE_GRAY2:
341     case FT_PIXEL_MODE_GRAY4:
342       {
343         FT_Bitmap  tmp;
344 
345 
346         /* convert to 8bpp */
347         FT_Bitmap_Init( &tmp );
348         error = FT_Bitmap_Convert( library, bitmap, &tmp, 1 );
349         if ( error )
350           return error;
351 
352         FT_Bitmap_Done( library, bitmap );
353         *bitmap = tmp;
354       }
355       break;
356 
357     case FT_PIXEL_MODE_MONO:
358       if ( xstr > 8 )
359         xstr = 8;
360       break;
361 
362     case FT_PIXEL_MODE_LCD:
363       xstr *= 3;
364       break;
365 
366     case FT_PIXEL_MODE_LCD_V:
367       ystr *= 3;
368       break;
369 
370     case FT_PIXEL_MODE_BGRA:
371       /* We don't embolden color glyphs. */
372       return FT_Err_Ok;
373     }
374 
375     error = ft_bitmap_assure_buffer( library->memory, bitmap,
376                                      (FT_UInt)xstr, (FT_UInt)ystr );
377     if ( error )
378       return error;
379 
380     /* take care of bitmap flow */
381     pitch = bitmap->pitch;
382     if ( pitch > 0 )
383       p = bitmap->buffer + pitch * ystr;
384     else
385     {
386       pitch = -pitch;
387       p = bitmap->buffer + (FT_UInt)pitch * ( bitmap->rows - 1 );
388     }
389 
390     /* for each row */
391     for ( y = 0; y < bitmap->rows; y++ )
392     {
393       /*
394        * Horizontally:
395        *
396        * From the last pixel on, make each pixel or'ed with the
397        * `xstr' pixels before it.
398        */
399       for ( x = pitch - 1; x >= 0; x-- )
400       {
401         unsigned char  tmp;
402 
403 
404         tmp = p[x];
405         for ( i = 1; i <= xstr; i++ )
406         {
407           if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
408           {
409             p[x] |= tmp >> i;
410 
411             /* the maximum value of 8 for `xstr' comes from here */
412             if ( x > 0 )
413               p[x] |= p[x - 1] << ( 8 - i );
414 
415 #if 0
416             if ( p[x] == 0xFF )
417               break;
418 #endif
419           }
420           else
421           {
422             if ( x - i >= 0 )
423             {
424               if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
425               {
426                 p[x] = (unsigned char)( bitmap->num_grays - 1 );
427                 break;
428               }
429               else
430               {
431                 p[x] = (unsigned char)( p[x] + p[x - i] );
432                 if ( p[x] == bitmap->num_grays - 1 )
433                   break;
434               }
435             }
436             else
437               break;
438           }
439         }
440       }
441 
442       /*
443        * Vertically:
444        *
445        * Make the above `ystr' rows or'ed with it.
446        */
447       for ( x = 1; x <= ystr; x++ )
448       {
449         unsigned char*  q;
450 
451 
452         q = p - bitmap->pitch * x;
453         for ( i = 0; i < pitch; i++ )
454           q[i] |= p[i];
455       }
456 
457       p += bitmap->pitch;
458     }
459 
460     bitmap->width += (FT_UInt)xstr;
461     bitmap->rows += (FT_UInt)ystr;
462 
463     return FT_Err_Ok;
464   }
465 
466 
467   static FT_Byte
ft_gray_for_premultiplied_srgb_bgra(const FT_Byte * bgra)468   ft_gray_for_premultiplied_srgb_bgra( const FT_Byte*  bgra )
469   {
470     FT_UInt  a = bgra[3];
471     FT_UInt  l;
472 
473 
474     /* Short-circuit transparent color to avoid division by zero. */
475     if ( !a )
476       return 0;
477 
478     /*
479      * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722
480      * coefficients for RGB channels *on the linear colors*.
481      * A gamma of 2.2 is fair to assume.  And then, we need to
482      * undo the premultiplication too.
483      *
484      *   https://accessibility.kde.org/hsl-adjusted.php
485      *
486      * We do the computation with integers only, applying a gamma of 2.0.
487      * We guarantee 32-bit arithmetic to avoid overflow but the resulting
488      * luminosity fits into 16 bits.
489      *
490      */
491 
492     l = (  4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] +
493           46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] +
494           13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16;
495 
496     /*
497      * Final transparency can be determined as follows.
498      *
499      * - If alpha is zero, we want 0.
500      * - If alpha is zero and luminosity is zero, we want 255.
501      * - If alpha is zero and luminosity is one, we want 0.
502      *
503      * So the formula is a * (1 - l) = a - l * a.
504      *
505      * We still need to undo premultiplication by dividing l by a*a.
506      *
507      */
508 
509     return (FT_Byte)( a - l / a );
510   }
511 
512 
513   /* documentation is in ftbitmap.h */
514 
515   FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Convert(FT_Library library,const FT_Bitmap * source,FT_Bitmap * target,FT_Int alignment)516   FT_Bitmap_Convert( FT_Library        library,
517                      const FT_Bitmap  *source,
518                      FT_Bitmap        *target,
519                      FT_Int            alignment )
520   {
521     FT_Error   error = FT_Err_Ok;
522     FT_Memory  memory;
523 
524     FT_Byte*  s;
525     FT_Byte*  t;
526 
527 
528     if ( !library )
529       return FT_THROW( Invalid_Library_Handle );
530 
531     if ( !source || !target )
532       return FT_THROW( Invalid_Argument );
533 
534     memory = library->memory;
535 
536     switch ( source->pixel_mode )
537     {
538     case FT_PIXEL_MODE_MONO:
539     case FT_PIXEL_MODE_GRAY:
540     case FT_PIXEL_MODE_GRAY2:
541     case FT_PIXEL_MODE_GRAY4:
542     case FT_PIXEL_MODE_LCD:
543     case FT_PIXEL_MODE_LCD_V:
544     case FT_PIXEL_MODE_BGRA:
545       {
546         FT_Int    pad, old_target_pitch, target_pitch;
547         FT_ULong  old_size;
548 
549 
550         old_target_pitch = target->pitch;
551         if ( old_target_pitch < 0 )
552           old_target_pitch = -old_target_pitch;
553 
554         old_size = target->rows * (FT_UInt)old_target_pitch;
555 
556         target->pixel_mode = FT_PIXEL_MODE_GRAY;
557         target->rows       = source->rows;
558         target->width      = source->width;
559 
560         pad = 0;
561         if ( alignment > 0 )
562         {
563           pad = (FT_Int)source->width % alignment;
564           if ( pad != 0 )
565             pad = alignment - pad;
566         }
567 
568         target_pitch = (FT_Int)source->width + pad;
569 
570         if ( target_pitch > 0                                               &&
571              (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch )
572           return FT_THROW( Invalid_Argument );
573 
574         if ( FT_QREALLOC( target->buffer,
575                           old_size, target->rows * (FT_UInt)target_pitch ) )
576           return error;
577 
578         target->pitch = target->pitch < 0 ? -target_pitch : target_pitch;
579       }
580       break;
581 
582     default:
583       error = FT_THROW( Invalid_Argument );
584     }
585 
586     s = source->buffer;
587     t = target->buffer;
588 
589     /* take care of bitmap flow */
590     if ( source->pitch < 0 )
591       s -= source->pitch * (FT_Int)( source->rows - 1 );
592     if ( target->pitch < 0 )
593       t -= target->pitch * (FT_Int)( target->rows - 1 );
594 
595     switch ( source->pixel_mode )
596     {
597     case FT_PIXEL_MODE_MONO:
598       {
599         FT_UInt  i;
600 
601 
602         target->num_grays = 2;
603 
604         for ( i = source->rows; i > 0; i-- )
605         {
606           FT_Byte*  ss = s;
607           FT_Byte*  tt = t;
608           FT_UInt   j;
609 
610 
611           /* get the full bytes */
612           for ( j = source->width >> 3; j > 0; j-- )
613           {
614             FT_Int  val = ss[0]; /* avoid a byte->int cast on each line */
615 
616 
617             tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
618             tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
619             tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
620             tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
621             tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
622             tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
623             tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
624             tt[7] = (FT_Byte)(   val & 0x01 );
625 
626             tt += 8;
627             ss += 1;
628           }
629 
630           /* get remaining pixels (if any) */
631           j = source->width & 7;
632           if ( j > 0 )
633           {
634             FT_Int  val = *ss;
635 
636 
637             for ( ; j > 0; j-- )
638             {
639               tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
640               val <<= 1;
641               tt   += 1;
642             }
643           }
644 
645           s += source->pitch;
646           t += target->pitch;
647         }
648       }
649       break;
650 
651 
652     case FT_PIXEL_MODE_GRAY:
653     case FT_PIXEL_MODE_LCD:
654     case FT_PIXEL_MODE_LCD_V:
655       {
656         FT_UInt  width = source->width;
657         FT_UInt  i;
658 
659 
660         target->num_grays = 256;
661 
662         for ( i = source->rows; i > 0; i-- )
663         {
664           FT_ARRAY_COPY( t, s, width );
665 
666           s += source->pitch;
667           t += target->pitch;
668         }
669       }
670       break;
671 
672 
673     case FT_PIXEL_MODE_GRAY2:
674       {
675         FT_UInt  i;
676 
677 
678         target->num_grays = 4;
679 
680         for ( i = source->rows; i > 0; i-- )
681         {
682           FT_Byte*  ss = s;
683           FT_Byte*  tt = t;
684           FT_UInt   j;
685 
686 
687           /* get the full bytes */
688           for ( j = source->width >> 2; j > 0; j-- )
689           {
690             FT_Int  val = ss[0];
691 
692 
693             tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
694             tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
695             tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
696             tt[3] = (FT_Byte)( ( val & 0x03 ) );
697 
698             ss += 1;
699             tt += 4;
700           }
701 
702           j = source->width & 3;
703           if ( j > 0 )
704           {
705             FT_Int  val = ss[0];
706 
707 
708             for ( ; j > 0; j-- )
709             {
710               tt[0]  = (FT_Byte)( ( val & 0xC0 ) >> 6 );
711               val  <<= 2;
712               tt    += 1;
713             }
714           }
715 
716           s += source->pitch;
717           t += target->pitch;
718         }
719       }
720       break;
721 
722 
723     case FT_PIXEL_MODE_GRAY4:
724       {
725         FT_UInt  i;
726 
727 
728         target->num_grays = 16;
729 
730         for ( i = source->rows; i > 0; i-- )
731         {
732           FT_Byte*  ss = s;
733           FT_Byte*  tt = t;
734           FT_UInt   j;
735 
736 
737           /* get the full bytes */
738           for ( j = source->width >> 1; j > 0; j-- )
739           {
740             FT_Int  val = ss[0];
741 
742 
743             tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
744             tt[1] = (FT_Byte)( ( val & 0x0F ) );
745 
746             ss += 1;
747             tt += 2;
748           }
749 
750           if ( source->width & 1 )
751             tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
752 
753           s += source->pitch;
754           t += target->pitch;
755         }
756       }
757       break;
758 
759 
760     case FT_PIXEL_MODE_BGRA:
761       {
762         FT_UInt  i;
763 
764 
765         target->num_grays = 256;
766 
767         for ( i = source->rows; i > 0; i-- )
768         {
769           FT_Byte*  ss = s;
770           FT_Byte*  tt = t;
771           FT_UInt   j;
772 
773 
774           for ( j = source->width; j > 0; j-- )
775           {
776             tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss );
777 
778             ss += 4;
779             tt += 1;
780           }
781 
782           s += source->pitch;
783           t += target->pitch;
784         }
785       }
786       break;
787 
788     default:
789       ;
790     }
791 
792     return error;
793   }
794 
795 
796   /* documentation is in ftbitmap.h */
797 
798   FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Blend(FT_Library library,const FT_Bitmap * source_,const FT_Vector source_offset_,FT_Bitmap * target,FT_Vector * atarget_offset,FT_Color color)799   FT_Bitmap_Blend( FT_Library        library,
800                    const FT_Bitmap*  source_,
801                    const FT_Vector   source_offset_,
802                    FT_Bitmap*        target,
803                    FT_Vector        *atarget_offset,
804                    FT_Color          color )
805   {
806     FT_Error   error = FT_Err_Ok;
807     FT_Memory  memory;
808 
809     FT_Bitmap         source_bitmap;
810     const FT_Bitmap*  source;
811 
812     FT_Vector  source_offset;
813     FT_Vector  target_offset;
814 
815     FT_Bool  free_source_bitmap          = 0;
816     FT_Bool  free_target_bitmap_on_error = 0;
817 
818     FT_Pos  source_llx, source_lly, source_urx, source_ury;
819     FT_Pos  target_llx, target_lly, target_urx, target_ury;
820     FT_Pos  final_llx, final_lly, final_urx, final_ury;
821 
822     unsigned int  final_rows, final_width;
823     long          x, y;
824 
825 
826     if ( !library || !target || !source_ || !atarget_offset )
827       return FT_THROW( Invalid_Argument );
828 
829     memory = library->memory;
830 
831     if ( !( target->pixel_mode == FT_PIXEL_MODE_NONE     ||
832             ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
833               target->buffer                           ) ) )
834       return FT_THROW( Invalid_Argument );
835 
836     if ( source_->pixel_mode == FT_PIXEL_MODE_NONE )
837       return FT_Err_Ok;               /* nothing to do */
838 
839     /* pitches must have the same sign */
840     if ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
841          ( source_->pitch ^ target->pitch ) < 0   )
842       return FT_THROW( Invalid_Argument );
843 
844     if ( !( source_->width && source_->rows ) )
845       return FT_Err_Ok;               /* nothing to do */
846 
847     /* assure integer pixel offsets */
848     source_offset.x = FT_PIX_FLOOR( source_offset_.x );
849     source_offset.y = FT_PIX_FLOOR( source_offset_.y );
850     target_offset.x = FT_PIX_FLOOR( atarget_offset->x );
851     target_offset.y = FT_PIX_FLOOR( atarget_offset->y );
852 
853     /* get source bitmap dimensions */
854     source_llx = source_offset.x;
855     if ( FT_LONG_MIN + (FT_Pos)( source_->rows << 6 ) + 64 > source_offset.y )
856     {
857       FT_TRACE5((
858         "FT_Bitmap_Blend: y coordinate overflow in source bitmap\n" ));
859       return FT_THROW( Invalid_Argument );
860     }
861     source_lly = source_offset.y - ( source_->rows << 6 );
862 
863     if ( FT_LONG_MAX - (FT_Pos)( source_->width << 6 ) - 64 < source_llx )
864     {
865       FT_TRACE5((
866         "FT_Bitmap_Blend: x coordinate overflow in source bitmap\n" ));
867       return FT_THROW( Invalid_Argument );
868     }
869     source_urx = source_llx + ( source_->width << 6 );
870     source_ury = source_offset.y;
871 
872     /* get target bitmap dimensions */
873     if ( target->width && target->rows )
874     {
875       target_llx = target_offset.x;
876       if ( FT_LONG_MIN + (FT_Pos)( target->rows << 6 ) > target_offset.y )
877       {
878         FT_TRACE5((
879           "FT_Bitmap_Blend: y coordinate overflow in target bitmap\n" ));
880         return FT_THROW( Invalid_Argument );
881       }
882       target_lly = target_offset.y - ( target->rows << 6 );
883 
884       if ( FT_LONG_MAX - (FT_Pos)( target->width << 6 ) < target_llx )
885       {
886         FT_TRACE5((
887           "FT_Bitmap_Blend: x coordinate overflow in target bitmap\n" ));
888         return FT_THROW( Invalid_Argument );
889       }
890       target_urx = target_llx + ( target->width << 6 );
891       target_ury = target_offset.y;
892     }
893     else
894     {
895       target_llx = FT_LONG_MAX;
896       target_lly = FT_LONG_MAX;
897       target_urx = FT_LONG_MIN;
898       target_ury = FT_LONG_MIN;
899     }
900 
901     /* compute final bitmap dimensions */
902     final_llx = FT_MIN( source_llx, target_llx );
903     final_lly = FT_MIN( source_lly, target_lly );
904     final_urx = FT_MAX( source_urx, target_urx );
905     final_ury = FT_MAX( source_ury, target_ury );
906 
907     final_width = ( final_urx - final_llx ) >> 6;
908     final_rows  = ( final_ury - final_lly ) >> 6;
909 
910 #ifdef FT_DEBUG_LEVEL_TRACE
911     FT_TRACE5(( "FT_Bitmap_Blend:\n"
912                 "  source bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
913       source_llx / 64, source_lly / 64,
914       source_urx / 64, source_ury / 64,
915       source_->width, source_->rows ));
916 
917     if ( target->width && target->rows )
918       FT_TRACE5(( "  target bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
919         target_llx / 64, target_lly / 64,
920         target_urx / 64, target_ury / 64,
921         target->width, target->rows ));
922     else
923       FT_TRACE5(( "  target bitmap: empty\n" ));
924 
925     if ( final_width && final_rows )
926       FT_TRACE5(( "  final bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
927         final_llx / 64, final_lly / 64,
928         final_urx / 64, final_ury / 64,
929         final_width, final_rows ));
930     else
931       FT_TRACE5(( "  final bitmap: empty\n" ));
932 #endif /* FT_DEBUG_LEVEL_TRACE */
933 
934     if ( !( final_width && final_rows ) )
935       return FT_Err_Ok;               /* nothing to do */
936 
937     /* for blending, set offset vector of final bitmap */
938     /* temporarily to (0,0)                            */
939     source_llx -= final_llx;
940     source_lly -= final_lly;
941 
942     if ( target->width && target->rows )
943     {
944       target_llx -= final_llx;
945       target_lly -= final_lly;
946     }
947 
948     /* set up target bitmap */
949     if ( target->pixel_mode == FT_PIXEL_MODE_NONE )
950     {
951       /* create new empty bitmap */
952       target->width      = final_width;
953       target->rows       = final_rows;
954       target->pixel_mode = FT_PIXEL_MODE_BGRA;
955       target->pitch      = (int)final_width * 4;
956       target->num_grays  = 256;
957 
958       if ( FT_LONG_MAX / target->pitch < (int)target->rows )
959       {
960         FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
961                      final_width, final_rows ));
962         return FT_THROW( Invalid_Argument );
963       }
964 
965       if ( FT_ALLOC( target->buffer, target->pitch * (int)target->rows ) )
966         return error;
967 
968       free_target_bitmap_on_error = 1;
969     }
970     else if ( target->width != final_width ||
971               target->rows  != final_rows  )
972     {
973       /* adjust old bitmap to enlarged size */
974       int  pitch, new_pitch;
975 
976       unsigned char*  buffer = NULL;
977 
978 
979       pitch = target->pitch;
980 
981       if ( pitch < 0 )
982         pitch = -pitch;
983 
984       new_pitch = (int)final_width * 4;
985 
986       if ( FT_LONG_MAX / new_pitch < (int)final_rows )
987       {
988         FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
989                      final_width, final_rows ));
990         return FT_THROW( Invalid_Argument );
991       }
992 
993       /* TODO: provide an in-buffer solution for large bitmaps */
994       /*       to avoid allocation of a new buffer             */
995       if ( FT_ALLOC( buffer, new_pitch * (int)final_rows ) )
996         goto Error;
997 
998       /* copy data to new buffer */
999       x = target_llx >> 6;
1000       y = target_lly >> 6;
1001 
1002       /* the bitmap flow is from top to bottom, */
1003       /* but y is measured from bottom to top   */
1004       if ( target->pitch < 0 )
1005       {
1006         /* XXX */
1007       }
1008       else
1009       {
1010         unsigned char*  p =
1011           target->buffer;
1012         unsigned char*  q =
1013           buffer +
1014           ( final_rows - y - target->rows ) * new_pitch +
1015           x * 4;
1016         unsigned char*  limit_p =
1017           p + pitch * (int)target->rows;
1018 
1019 
1020         while ( p < limit_p )
1021         {
1022           FT_MEM_COPY( q, p, pitch );
1023 
1024           p += pitch;
1025           q += new_pitch;
1026         }
1027       }
1028 
1029       FT_FREE( target->buffer );
1030 
1031       target->width = final_width;
1032       target->rows  = final_rows;
1033 
1034       if ( target->pitch < 0 )
1035         target->pitch = -new_pitch;
1036       else
1037         target->pitch = new_pitch;
1038 
1039       target->buffer = buffer;
1040     }
1041 
1042     /* adjust source bitmap if necessary */
1043     if ( source_->pixel_mode != FT_PIXEL_MODE_GRAY )
1044     {
1045       FT_Bitmap_Init( &source_bitmap );
1046       error = FT_Bitmap_Convert( library, source_, &source_bitmap, 1 );
1047       if ( error )
1048         goto Error;
1049 
1050       source             = &source_bitmap;
1051       free_source_bitmap = 1;
1052     }
1053     else
1054       source = source_;
1055 
1056     /* do blending; the code below returns pre-multiplied channels, */
1057     /* similar to what FreeType gets from `CBDT' tables             */
1058     x = source_llx >> 6;
1059     y = source_lly >> 6;
1060 
1061     /* the bitmap flow is from top to bottom, */
1062     /* but y is measured from bottom to top   */
1063     if ( target->pitch < 0 )
1064     {
1065       /* XXX */
1066     }
1067     else
1068     {
1069       unsigned char*  p =
1070         source->buffer;
1071       unsigned char*  q =
1072         target->buffer +
1073         ( target->rows - y - source->rows ) * target->pitch +
1074         x * 4;
1075       unsigned char*  limit_p =
1076         p + source->pitch * (int)source->rows;
1077 
1078 
1079       while ( p < limit_p )
1080       {
1081         unsigned char*  r       = p;
1082         unsigned char*  s       = q;
1083         unsigned char*  limit_r = r + source->width;
1084 
1085 
1086         while ( r < limit_r )
1087         {
1088           int  aa = *r++;
1089           int  fa = color.alpha * aa / 255;
1090 
1091           int  fb = color.blue * fa / 255;
1092           int  fg = color.green * fa / 255;
1093           int  fr = color.red * fa / 255;
1094 
1095           int  ba2 = 255 - fa;
1096 
1097           int  bb = s[0];
1098           int  bg = s[1];
1099           int  br = s[2];
1100           int  ba = s[3];
1101 
1102 
1103           *s++ = (unsigned char)( bb * ba2 / 255 + fb );
1104           *s++ = (unsigned char)( bg * ba2 / 255 + fg );
1105           *s++ = (unsigned char)( br * ba2 / 255 + fr );
1106           *s++ = (unsigned char)( ba * ba2 / 255 + fa );
1107         }
1108 
1109         p += source->pitch;
1110         q += target->pitch;
1111       }
1112     }
1113 
1114     atarget_offset->x = final_llx;
1115     atarget_offset->y = final_lly + ( final_rows << 6 );
1116 
1117   Error:
1118     if ( error && free_target_bitmap_on_error )
1119       FT_Bitmap_Done( library, target );
1120 
1121     if ( free_source_bitmap )
1122       FT_Bitmap_Done( library, &source_bitmap );
1123 
1124     return error;
1125   }
1126 
1127 
1128   /* documentation is in ftbitmap.h */
1129 
1130   FT_EXPORT_DEF( FT_Error )
FT_GlyphSlot_Own_Bitmap(FT_GlyphSlot slot)1131   FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot )
1132   {
1133     if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP   &&
1134          !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
1135     {
1136       FT_Bitmap  bitmap;
1137       FT_Error   error;
1138 
1139 
1140       FT_Bitmap_Init( &bitmap );
1141       error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
1142       if ( error )
1143         return error;
1144 
1145       slot->bitmap = bitmap;
1146       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
1147     }
1148 
1149     return FT_Err_Ok;
1150   }
1151 
1152 
1153   /* documentation is in ftbitmap.h */
1154 
1155   FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Done(FT_Library library,FT_Bitmap * bitmap)1156   FT_Bitmap_Done( FT_Library  library,
1157                   FT_Bitmap  *bitmap )
1158   {
1159     FT_Memory  memory;
1160 
1161 
1162     if ( !library )
1163       return FT_THROW( Invalid_Library_Handle );
1164 
1165     if ( !bitmap )
1166       return FT_THROW( Invalid_Argument );
1167 
1168     memory = library->memory;
1169 
1170     FT_FREE( bitmap->buffer );
1171     *bitmap = null_bitmap;
1172 
1173     return FT_Err_Ok;
1174   }
1175 
1176 
1177 /* END */
1178