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 )
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  static FT_Error
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 )
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
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 )
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 )
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 )
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