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