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