• 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, 2014 by                               */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
10 /*  This file is part of the FreeType project, and may only be used,       */
11 /*  modified, and distributed under the terms of the FreeType project      */
12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13 /*  this file you indicate that you have read the license and              */
14 /*  understand and accept it fully.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17 
18 
19 #include <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21 
22 #include FT_BITMAP_H
23 #include FT_IMAGE_H
24 #include FT_INTERNAL_OBJECTS_H
25 
26 
27   static
28   const FT_Bitmap  null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
29 
30 
31   /* documentation is in ftbitmap.h */
32 
33   FT_EXPORT_DEF( void )
FT_Bitmap_New(FT_Bitmap * abitmap)34   FT_Bitmap_New( FT_Bitmap  *abitmap )
35   {
36     *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   static 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_Byte   a = bgra[3];
382     FT_ULong  l;
383 
384 
385     /* Short-circuit transparent color to avoid div-by-zero. */
386     if ( !a )
387       return 0;
388 
389     /*
390      * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722
391      * coefficients for RGB channels *on the linear colors*.
392      * A gamma of 2.2 is fair to assume.  And then, we need to
393      * undo the premultiplication too.
394      *
395      * http://accessibility.kde.org/hsl-adjusted.php
396      *
397      * We do the computation with integers only, applying a gamma of 2.0.
398      * The following will never overflow 32 bits; it is a scaled-up
399      * luminosity with premultiplication not yet undone.
400      *
401      */
402 
403     l =  4731UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] +
404         46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] +
405         13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2];
406 
407     /*
408      * Final transparency can be determined as follows.
409      *
410      * - If alpha is zero, we want 0.
411      * - If alpha is zero and luminosity is zero, we want 255.
412      * - If alpha is zero and luminosity is one, we want 0.
413      *
414      * So the formula is a * (1 - l) = a - l * a.
415      *
416      * In the actual code, we undo premultiplication and scale down again.
417      *
418      */
419 
420     return a - (FT_Byte)( ( l / a ) >> 16 );
421   }
422 
423 
424   /* documentation is in ftbitmap.h */
425 
426   FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Convert(FT_Library library,const FT_Bitmap * source,FT_Bitmap * target,FT_Int alignment)427   FT_Bitmap_Convert( FT_Library        library,
428                      const FT_Bitmap  *source,
429                      FT_Bitmap        *target,
430                      FT_Int            alignment )
431   {
432     FT_Error   error = FT_Err_Ok;
433     FT_Memory  memory;
434 
435 
436     if ( !library )
437       return FT_THROW( Invalid_Library_Handle );
438 
439     memory = library->memory;
440 
441     switch ( source->pixel_mode )
442     {
443     case FT_PIXEL_MODE_MONO:
444     case FT_PIXEL_MODE_GRAY:
445     case FT_PIXEL_MODE_GRAY2:
446     case FT_PIXEL_MODE_GRAY4:
447     case FT_PIXEL_MODE_LCD:
448     case FT_PIXEL_MODE_LCD_V:
449     case FT_PIXEL_MODE_BGRA:
450       {
451         FT_Int   pad;
452         FT_Long  old_size;
453 
454 
455         old_size = target->rows * target->pitch;
456         if ( old_size < 0 )
457           old_size = -old_size;
458 
459         target->pixel_mode = FT_PIXEL_MODE_GRAY;
460         target->rows       = source->rows;
461         target->width      = source->width;
462 
463         pad = 0;
464         if ( alignment > 0 )
465         {
466           pad = source->width % alignment;
467           if ( pad != 0 )
468             pad = alignment - pad;
469         }
470 
471         target->pitch = source->width + pad;
472 
473         if ( target->pitch > 0                                     &&
474              (FT_ULong)target->rows > FT_ULONG_MAX / target->pitch )
475           return FT_THROW( Invalid_Argument );
476 
477         if ( target->rows * target->pitch > old_size             &&
478              FT_QREALLOC( target->buffer,
479                           old_size, target->rows * target->pitch ) )
480           return error;
481       }
482       break;
483 
484     default:
485       error = FT_THROW( Invalid_Argument );
486     }
487 
488     switch ( source->pixel_mode )
489     {
490     case FT_PIXEL_MODE_MONO:
491       {
492         FT_Byte*  s = source->buffer;
493         FT_Byte*  t = target->buffer;
494         FT_Int    i;
495 
496 
497         target->num_grays = 2;
498 
499         for ( i = source->rows; i > 0; i-- )
500         {
501           FT_Byte*  ss = s;
502           FT_Byte*  tt = t;
503           FT_Int    j;
504 
505 
506           /* get the full bytes */
507           for ( j = source->width >> 3; j > 0; j-- )
508           {
509             FT_Int  val = ss[0]; /* avoid a byte->int cast on each line */
510 
511 
512             tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
513             tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
514             tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
515             tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
516             tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
517             tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
518             tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
519             tt[7] = (FT_Byte)(   val & 0x01 );
520 
521             tt += 8;
522             ss += 1;
523           }
524 
525           /* get remaining pixels (if any) */
526           j = source->width & 7;
527           if ( j > 0 )
528           {
529             FT_Int  val = *ss;
530 
531 
532             for ( ; j > 0; j-- )
533             {
534               tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
535               val <<= 1;
536               tt   += 1;
537             }
538           }
539 
540           s += source->pitch;
541           t += target->pitch;
542         }
543       }
544       break;
545 
546 
547     case FT_PIXEL_MODE_GRAY:
548     case FT_PIXEL_MODE_LCD:
549     case FT_PIXEL_MODE_LCD_V:
550       {
551         FT_Int    width   = source->width;
552         FT_Byte*  s       = source->buffer;
553         FT_Byte*  t       = target->buffer;
554         FT_Int    s_pitch = source->pitch;
555         FT_Int    t_pitch = target->pitch;
556         FT_Int    i;
557 
558 
559         target->num_grays = 256;
560 
561         for ( i = source->rows; i > 0; i-- )
562         {
563           FT_ARRAY_COPY( t, s, width );
564 
565           s += s_pitch;
566           t += t_pitch;
567         }
568       }
569       break;
570 
571 
572     case FT_PIXEL_MODE_GRAY2:
573       {
574         FT_Byte*  s = source->buffer;
575         FT_Byte*  t = target->buffer;
576         FT_Int    i;
577 
578 
579         target->num_grays = 4;
580 
581         for ( i = source->rows; i > 0; i-- )
582         {
583           FT_Byte*  ss = s;
584           FT_Byte*  tt = t;
585           FT_Int    j;
586 
587 
588           /* get the full bytes */
589           for ( j = source->width >> 2; j > 0; j-- )
590           {
591             FT_Int  val = ss[0];
592 
593 
594             tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
595             tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
596             tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
597             tt[3] = (FT_Byte)( ( val & 0x03 ) );
598 
599             ss += 1;
600             tt += 4;
601           }
602 
603           j = source->width & 3;
604           if ( j > 0 )
605           {
606             FT_Int  val = ss[0];
607 
608 
609             for ( ; j > 0; j-- )
610             {
611               tt[0]  = (FT_Byte)( ( val & 0xC0 ) >> 6 );
612               val  <<= 2;
613               tt    += 1;
614             }
615           }
616 
617           s += source->pitch;
618           t += target->pitch;
619         }
620       }
621       break;
622 
623 
624     case FT_PIXEL_MODE_GRAY4:
625       {
626         FT_Byte*  s = source->buffer;
627         FT_Byte*  t = target->buffer;
628         FT_Int    i;
629 
630 
631         target->num_grays = 16;
632 
633         for ( i = source->rows; i > 0; i-- )
634         {
635           FT_Byte*  ss = s;
636           FT_Byte*  tt = t;
637           FT_Int    j;
638 
639 
640           /* get the full bytes */
641           for ( j = source->width >> 1; j > 0; j-- )
642           {
643             FT_Int  val = ss[0];
644 
645 
646             tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
647             tt[1] = (FT_Byte)( ( val & 0x0F ) );
648 
649             ss += 1;
650             tt += 2;
651           }
652 
653           if ( source->width & 1 )
654             tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
655 
656           s += source->pitch;
657           t += target->pitch;
658         }
659       }
660       break;
661 
662     case FT_PIXEL_MODE_BGRA:
663       {
664         FT_Byte*  s       = source->buffer;
665         FT_Byte*  t       = target->buffer;
666         FT_Int    s_pitch = source->pitch;
667         FT_Int    t_pitch = target->pitch;
668         FT_Int    i;
669 
670 
671         target->num_grays = 256;
672 
673         for ( i = source->rows; i > 0; i-- )
674         {
675           FT_Byte*  ss = s;
676           FT_Byte*  tt = t;
677           FT_Int    j;
678 
679 
680           for ( j = source->width; j > 0; j-- )
681           {
682             tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss );
683 
684             ss += 4;
685             tt += 1;
686           }
687 
688           s += s_pitch;
689           t += t_pitch;
690         }
691       }
692       break;
693 
694     default:
695       ;
696     }
697 
698     return error;
699   }
700 
701 
702   /* documentation is in ftbitmap.h */
703 
704   FT_EXPORT_DEF( FT_Error )
FT_GlyphSlot_Own_Bitmap(FT_GlyphSlot slot)705   FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot )
706   {
707     if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP   &&
708          !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
709     {
710       FT_Bitmap  bitmap;
711       FT_Error   error;
712 
713 
714       FT_Bitmap_New( &bitmap );
715       error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
716       if ( error )
717         return error;
718 
719       slot->bitmap = bitmap;
720       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
721     }
722 
723     return FT_Err_Ok;
724   }
725 
726 
727   /* documentation is in ftbitmap.h */
728 
729   FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Done(FT_Library library,FT_Bitmap * bitmap)730   FT_Bitmap_Done( FT_Library  library,
731                   FT_Bitmap  *bitmap )
732   {
733     FT_Memory  memory;
734 
735 
736     if ( !library )
737       return FT_THROW( Invalid_Library_Handle );
738 
739     if ( !bitmap )
740       return FT_THROW( Invalid_Argument );
741 
742     memory = library->memory;
743 
744     FT_FREE( bitmap->buffer );
745     *bitmap = null_bitmap;
746 
747     return FT_Err_Ok;
748   }
749 
750 
751 /* END */
752