• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * ftbitmap.c
4  *
5  *   FreeType utility functions for bitmaps (body).
6  *
7  * Copyright 2004-2018 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  trace_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     FT_Vector  frac_offset;
815 
816     FT_Bool  free_source_bitmap          = 0;
817     FT_Bool  free_target_bitmap_on_error = 0;
818 
819     FT_Pos  source_llx, source_lly, source_urx, source_ury;
820     FT_Pos  target_llx, target_lly, target_urx, target_ury;
821     FT_Pos  final_llx, final_lly, final_urx, final_ury;
822 
823     unsigned int  final_rows, final_width;
824     long          x, y;
825 
826 
827     if ( !library || !target || !source_ || !atarget_offset )
828       return FT_THROW( Invalid_Argument );
829 
830     memory = library->memory;
831 
832     if ( !( target->pixel_mode == FT_PIXEL_MODE_NONE     ||
833             ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
834               target->buffer                           ) ) )
835       return FT_THROW( Invalid_Argument );
836 
837     if ( source_->pixel_mode == FT_PIXEL_MODE_NONE )
838       return FT_Err_Ok;               /* nothing to do */
839 
840     /* pitches must have the same sign */
841     if ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
842          ( source_->pitch ^ target->pitch ) < 0   )
843       return FT_THROW( Invalid_Argument );
844 
845     if ( !( source_->width && source_->rows ) )
846       return FT_Err_Ok;               /* nothing to do */
847 
848     /* we isolate a fractional shift of `source',        */
849     /* to be less than one pixel and always positive;    */
850     /* `source_offset' now holds full-pixel shift values */
851     source_offset.x = FT_PIX_FLOOR( source_offset_.x );
852     frac_offset.x   = source_offset_.x - source_offset.x;
853 
854     source_offset.y = FT_PIX_FLOOR( source_offset_.y );
855     frac_offset.y   = source_offset_.y - source_offset.y;
856 
857     /* assure integer pixel offset for target bitmap */
858     target_offset.x = FT_PIX_FLOOR( atarget_offset->x );
859     target_offset.y = FT_PIX_FLOOR( atarget_offset->y );
860 
861     /* get source bitmap dimensions */
862     source_llx = source_offset.x;
863     if ( FT_LONG_MIN + (FT_Pos)( source_->rows << 6 ) + 64 > source_offset.y )
864     {
865       FT_TRACE5((
866         "FT_Bitmap_Blend: y coordinate overflow in source bitmap\n" ));
867       return FT_THROW( Invalid_Argument );
868     }
869     source_lly = source_offset.y - ( source_->rows << 6 );
870 
871     if ( FT_LONG_MAX - (FT_Pos)( source_->width << 6 ) - 64 < source_llx )
872     {
873       FT_TRACE5((
874         "FT_Bitmap_Blend: x coordinate overflow in source bitmap\n" ));
875       return FT_THROW( Invalid_Argument );
876     }
877     source_urx = source_llx + ( source_->width << 6 );
878     source_ury = source_offset.y;
879 
880     /* get target bitmap dimensions */
881     if ( target->width && target->rows )
882     {
883       target_llx = target_offset.x;
884       if ( FT_LONG_MIN + (FT_Pos)( target->rows << 6 ) > target_offset.y )
885       {
886         FT_TRACE5((
887           "FT_Bitmap_Blend: y coordinate overflow in target bitmap\n" ));
888         return FT_THROW( Invalid_Argument );
889       }
890       target_lly = target_offset.y - ( target->rows << 6 );
891 
892       if ( FT_LONG_MAX - (FT_Pos)( target->width << 6 ) < target_llx )
893       {
894         FT_TRACE5((
895           "FT_Bitmap_Blend: x coordinate overflow in target bitmap\n" ));
896         return FT_THROW( Invalid_Argument );
897       }
898       target_urx = target_llx + ( target->width << 6 );
899       target_ury = target_offset.y;
900     }
901     else
902     {
903       target_llx = FT_LONG_MAX;
904       target_lly = FT_LONG_MAX;
905       target_urx = FT_LONG_MIN;
906       target_ury = FT_LONG_MIN;
907     }
908 
909     /* move upper right corner up and to the right */
910     /* if we have a fractional offset              */
911     if ( source_urx >= target_urx && frac_offset.x )
912       source_urx += 64;
913     if ( source_ury >= target_ury && frac_offset.y )
914       source_ury += 64;
915 
916     /* compute final bitmap dimensions */
917     final_llx = FT_MIN( source_llx, target_llx );
918     final_lly = FT_MIN( source_lly, target_lly );
919     final_urx = FT_MAX( source_urx, target_urx );
920     final_ury = FT_MAX( source_ury, target_ury );
921 
922     final_width = ( final_urx - final_llx ) >> 6;
923     final_rows  = ( final_ury - final_lly ) >> 6;
924 
925 #ifdef FT_DEBUG_LEVEL_TRACE
926     FT_TRACE5(( "FT_Bitmap_Blend:\n"
927                 "  source bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
928       source_llx / 64, source_lly / 64,
929       source_urx / 64, source_ury / 64,
930       source_->width, source_->rows ));
931 
932     if ( frac_offset.x || frac_offset.y )
933       FT_TRACE5(( "    fractional offset: (%d/64, %d/64)\n",
934                   frac_offset.x, frac_offset.y ));
935 
936     if ( target->width && target->rows )
937       FT_TRACE5(( "  target bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
938         target_llx / 64, target_lly / 64,
939         target_urx / 64, target_ury / 64,
940         target->width, target->rows ));
941     else
942       FT_TRACE5(( "  target bitmap: empty\n" ));
943 
944     FT_TRACE5(( "  final bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
945       final_llx / 64, final_lly / 64,
946       final_urx / 64, final_ury / 64,
947       final_width, final_rows ));
948 #endif /* FT_DEBUG_LEVEL_TRACE */
949 
950     /* for blending, set offset vector of final bitmap */
951     /* temporarily to (0,0)                            */
952     source_llx -= final_llx;
953     source_lly -= final_lly;
954 
955     if ( target->width && target->rows )
956     {
957       target_llx -= final_llx;
958       target_lly -= final_lly;
959     }
960 
961     /* set up target bitmap */
962     if ( target->pixel_mode == FT_PIXEL_MODE_NONE )
963     {
964       /* create new empty bitmap */
965       target->width      = final_width;
966       target->rows       = final_rows;
967       target->pixel_mode = FT_PIXEL_MODE_BGRA;
968       target->pitch      = (int)final_width * 4;
969       target->num_grays  = 256;
970 
971       if ( FT_LONG_MAX / target->pitch < (int)target->rows )
972       {
973         FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
974                      final_width, final_rows ));
975         return FT_THROW( Invalid_Argument );
976       }
977 
978       if ( FT_ALLOC( target->buffer, target->pitch * (int)target->rows ) )
979         return error;
980 
981       free_target_bitmap_on_error = 1;
982     }
983     else if ( target->width != final_width ||
984               target->rows  != final_rows  )
985     {
986       /* adjust old bitmap to enlarged size */
987       int  pitch, new_pitch;
988 
989       unsigned char*  buffer = NULL;
990 
991 
992       pitch = target->pitch;
993       if ( pitch < 0 )
994         pitch = -pitch;
995 
996       new_pitch = (int)final_width * 4;
997 
998       if ( FT_LONG_MAX / new_pitch < (int)final_rows )
999       {
1000         FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
1001                      final_width, final_rows ));
1002         return FT_THROW( Invalid_Argument );
1003       }
1004 
1005       /* TODO: provide an in-buffer solution for large bitmaps */
1006       /*       to avoid allocation of a new buffer             */
1007       if ( FT_ALLOC( buffer, new_pitch * (int)final_rows ) )
1008         goto Error;
1009 
1010       /* copy data to new buffer */
1011       x = target_llx >> 6;
1012       y = target_lly >> 6;
1013 
1014       /* the bitmap flow is from top to bottom, */
1015       /* but y is measured from bottom to top   */
1016       if ( target->pitch < 0 )
1017       {
1018         /* XXX */
1019       }
1020       else
1021       {
1022         unsigned char*  p =
1023           target->buffer;
1024         unsigned char*  q =
1025           buffer +
1026           ( final_rows - y - target->rows ) * new_pitch +
1027           x * 4;
1028         unsigned char*  limit_p =
1029           p + pitch * (int)target->rows;
1030 
1031 
1032         while ( p < limit_p )
1033         {
1034           FT_MEM_COPY( q, p, pitch );
1035 
1036           p += pitch;
1037           q += new_pitch;
1038         }
1039       }
1040 
1041       FT_FREE( target->buffer );
1042 
1043       target->width = final_width;
1044       target->rows  = final_rows;
1045 
1046       if ( target->pitch < 0 )
1047         target->pitch = -new_pitch;
1048       else
1049         target->pitch = new_pitch;
1050 
1051       target->buffer = buffer;
1052     }
1053 
1054     /* adjust source bitmap if necessary */
1055     if ( source_->pixel_mode != FT_PIXEL_MODE_GRAY )
1056     {
1057       FT_Bitmap_Init( &source_bitmap );
1058       error = FT_Bitmap_Convert( library, source_, &source_bitmap, 1 );
1059       if ( error )
1060         goto Error;
1061 
1062       source             = &source_bitmap;
1063       free_source_bitmap = 1;
1064     }
1065     else
1066       source = source_;
1067 
1068     /* do blending; the code below returns pre-multiplied channels, */
1069     /* similar to what FreeType gets from `CBDT' tables             */
1070     x = source_llx >> 6;
1071     y = source_lly >> 6;
1072 
1073     /* XXX handle `frac_offset' */
1074 
1075     /* the bitmap flow is from top to bottom, */
1076     /* but y is measured from bottom to top   */
1077     if ( target->pitch < 0 )
1078     {
1079       /* XXX */
1080     }
1081     else
1082     {
1083       unsigned char*  p =
1084         source->buffer;
1085       unsigned char*  q =
1086         target->buffer +
1087         ( target->rows - y - source->rows ) * target->pitch +
1088         x * 4;
1089       unsigned char*  limit_p =
1090         p + source->pitch * (int)source->rows;
1091 
1092 
1093       while ( p < limit_p )
1094       {
1095         unsigned char*  r       = p;
1096         unsigned char*  s       = q;
1097         unsigned char*  limit_r = r + source->width;
1098 
1099 
1100         while ( r < limit_r )
1101         {
1102           int  aa = *r++;
1103           int  fa = color.alpha * aa / 255;
1104 
1105           int  fb = color.blue * fa / 255;
1106           int  fg = color.green * fa / 255;
1107           int  fr = color.red * fa / 255;
1108 
1109           int  ba2 = 255 - fa;
1110 
1111           int  bb = s[0];
1112           int  bg = s[1];
1113           int  br = s[2];
1114           int  ba = s[3];
1115 
1116 
1117           *s++ = (unsigned char)( bb * ba2 / 255 + fb );
1118           *s++ = (unsigned char)( bg * ba2 / 255 + fg );
1119           *s++ = (unsigned char)( br * ba2 / 255 + fr );
1120           *s++ = (unsigned char)( ba * ba2 / 255 + fa );
1121         }
1122 
1123         p += source->pitch;
1124         q += target->pitch;
1125       }
1126     }
1127 
1128     atarget_offset->x = final_llx;
1129     atarget_offset->y = final_lly + ( final_rows << 6 );
1130 
1131   Error:
1132     if ( error && free_target_bitmap_on_error )
1133       FT_Bitmap_Done( library, target );
1134 
1135     if ( free_source_bitmap )
1136       FT_Bitmap_Done( library, &source_bitmap );
1137 
1138     return error;
1139   }
1140 
1141 
1142   /* documentation is in ftbitmap.h */
1143 
1144   FT_EXPORT_DEF( FT_Error )
FT_GlyphSlot_Own_Bitmap(FT_GlyphSlot slot)1145   FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot )
1146   {
1147     if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP   &&
1148          !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
1149     {
1150       FT_Bitmap  bitmap;
1151       FT_Error   error;
1152 
1153 
1154       FT_Bitmap_Init( &bitmap );
1155       error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
1156       if ( error )
1157         return error;
1158 
1159       slot->bitmap = bitmap;
1160       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
1161     }
1162 
1163     return FT_Err_Ok;
1164   }
1165 
1166 
1167   /* documentation is in ftbitmap.h */
1168 
1169   FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Done(FT_Library library,FT_Bitmap * bitmap)1170   FT_Bitmap_Done( FT_Library  library,
1171                   FT_Bitmap  *bitmap )
1172   {
1173     FT_Memory  memory;
1174 
1175 
1176     if ( !library )
1177       return FT_THROW( Invalid_Library_Handle );
1178 
1179     if ( !bitmap )
1180       return FT_THROW( Invalid_Argument );
1181 
1182     memory = library->memory;
1183 
1184     FT_FREE( bitmap->buffer );
1185     *bitmap = null_bitmap;
1186 
1187     return FT_Err_Ok;
1188   }
1189 
1190 
1191 /* END */
1192