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