blob: 7a88294385c2969b185739a5c01a46e9a2aa79c4 [file] [log] [blame]
Werner Lembergf2438e12004-12-14 16:01:29 +00001/***************************************************************************/
2/* */
3/* ftbitmap.c */
4/* */
5/* FreeType utility functions for converting 1bpp, 2bpp, 4bpp, and 8bpp */
6/* bitmaps into 8bpp format (body). */
7/* */
Werner Lembergbe3c9812006-01-27 14:16:16 +00008/* Copyright 2004, 2005, 2006 by */
Werner Lembergf2438e12004-12-14 16:01:29 +00009/* David Turner, Robert Wilhelm, and Werner Lemberg. */
10/* */
11/* This file is part of the FreeType project, and may only be used, */
12/* modified, and distributed under the terms of the FreeType project */
13/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14/* this file you indicate that you have read the license and */
15/* understand and accept it fully. */
16/* */
17/***************************************************************************/
18
19
20#include <ft2build.h>
Werner Lembergb9ee7372005-05-20 21:52:19 +000021#include FT_BITMAP_H
Werner Lembergf2438e12004-12-14 16:01:29 +000022#include FT_INTERNAL_OBJECTS_H
23
24
25 static
26 const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
27
28
29 /* documentation is in ftbitmap.h */
30
31 FT_EXPORT_DEF( void )
32 FT_Bitmap_New( FT_Bitmap *abitmap )
33 {
34 *abitmap = null_bitmap;
35 }
36
37
38 /* documentation is in ftbitmap.h */
39
40 FT_EXPORT_DEF( FT_Error )
Werner Lembergb9ee7372005-05-20 21:52:19 +000041 FT_Bitmap_Copy( FT_Library library,
42 const FT_Bitmap *source,
43 FT_Bitmap *target)
44 {
45 FT_Memory memory = library->memory;
46 FT_Error error = FT_Err_Ok;
47 FT_Int pitch = source->pitch;
48 FT_ULong size;
49
50
51 if ( source == target )
52 return FT_Err_Ok;
53
54 if ( source->buffer == NULL )
55 {
56 *target = *source;
57
58 return FT_Err_Ok;
59 }
60
61 if ( pitch < 0 )
62 pitch = -pitch;
63 size = (FT_ULong)( pitch * source->rows );
64
65 if ( target->buffer )
66 {
67 FT_Int target_pitch = target->pitch;
68 FT_ULong target_size;
69
70
71 if ( target_pitch < 0 )
72 target_pitch = -target_pitch;
73 target_size = (FT_ULong)( target_pitch * target->rows );
74
75 if ( target_size != size )
David Turner6a681fa2006-01-27 12:11:22 +000076 (void)FT_QREALLOC( target->buffer, target_size, size );
Werner Lembergb9ee7372005-05-20 21:52:19 +000077 }
78 else
David Turner6a681fa2006-01-27 12:11:22 +000079 (void)FT_QALLOC( target->buffer, size );
Werner Lembergb9ee7372005-05-20 21:52:19 +000080
81 if ( !error )
82 {
83 unsigned char *p;
84
85
86 p = target->buffer;
87 *target = *source;
88 target->buffer = p;
89
90 FT_MEM_COPY( target->buffer, source->buffer, size );
91 }
92
93 return error;
94 }
95
96
Werner Lembergafb2ba52005-05-25 05:51:01 +000097 static FT_Error
98 ft_bitmap_assure_buffer( FT_Memory memory,
99 FT_Bitmap* bitmap,
100 FT_UInt xpixels,
101 FT_UInt ypixels )
102 {
103 FT_Error error;
104 int pitch;
105 int new_pitch;
106 FT_UInt ppb;
107 FT_Int i;
108 unsigned char* buffer;
109
110
111 pitch = bitmap->pitch;
112 if ( pitch < 0 )
113 pitch = -pitch;
114
115 switch ( bitmap->pixel_mode )
116 {
117 case FT_PIXEL_MODE_MONO:
118 ppb = 8;
119 break;
120 case FT_PIXEL_MODE_GRAY2:
121 ppb = 4;
122 break;
123 case FT_PIXEL_MODE_GRAY4:
124 ppb = 2;
125 break;
126 case FT_PIXEL_MODE_GRAY:
Werner Lemberg71d76282005-05-30 07:54:20 +0000127 case FT_PIXEL_MODE_LCD:
128 case FT_PIXEL_MODE_LCD_V:
Werner Lembergafb2ba52005-05-25 05:51:01 +0000129 ppb = 1;
130 break;
131 default:
132 return FT_Err_Invalid_Glyph_Format;
133 }
134
Werner Lemberg71d76282005-05-30 07:54:20 +0000135 /* if no need to allocate memory */
Werner Lembergafb2ba52005-05-25 05:51:01 +0000136 if ( ypixels == 0 && pitch * ppb >= bitmap->width + xpixels )
Werner Lemberg71d76282005-05-30 07:54:20 +0000137 {
138 /* zero the padding */
139 for ( i = 0; i < bitmap->rows; i++ )
140 {
141 unsigned char* last_byte;
142 int bits = xpixels * ( 8 / ppb );
143 int mask = 0;
144
145
146 last_byte = bitmap->buffer + i * pitch + ( bitmap->width - 1 ) / ppb;
147
148 if ( bits >= 8 )
149 {
150 FT_MEM_ZERO( last_byte + 1, bits / 8 );
151 bits %= 8;
152 }
153
154 if ( bits > 0 )
155 {
156 while ( bits-- > 0 )
157 mask |= 1 << bits;
158
159 *last_byte &= ~mask;
160 }
161 }
162
Werner Lembergafb2ba52005-05-25 05:51:01 +0000163 return FT_Err_Ok;
Werner Lemberg71d76282005-05-30 07:54:20 +0000164 }
Werner Lembergafb2ba52005-05-25 05:51:01 +0000165
166 new_pitch = ( bitmap->width + xpixels + ppb - 1 ) / ppb;
167
168 if ( FT_ALLOC( buffer, new_pitch * ( bitmap->rows + ypixels ) ) )
169 return error;
170
171 if ( bitmap->pitch > 0 )
172 {
173 for ( i = 0; i < bitmap->rows; i++ )
174 FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),
175 bitmap->buffer + pitch * i, pitch );
176 }
177 else
178 {
179 for ( i = 0; i < bitmap->rows; i++ )
180 FT_MEM_COPY( buffer + new_pitch * i,
181 bitmap->buffer + pitch * i, pitch );
182 }
183
184 FT_FREE( bitmap->buffer );
185 bitmap->buffer = buffer;
186
187 if ( bitmap->pitch < 0 )
188 new_pitch = -new_pitch;
189
190 /* set pitch only */
191 bitmap->pitch = new_pitch;
192
193 return FT_Err_Ok;
194 }
195
196
197 /* documentation is in ftbitmap.h */
198
199 FT_EXPORT_DEF( FT_Error )
200 FT_Bitmap_Embolden( FT_Library library,
201 FT_Bitmap* bitmap,
202 FT_Pos xStrength,
203 FT_Pos yStrength )
204 {
205 FT_Error error;
206 unsigned char* p;
207 FT_Int i, x, y, pitch;
208 FT_Int xstr, ystr;
209
210
211 if ( !library )
212 return FT_Err_Invalid_Library_Handle;
213
Werner Lemberg38e82be2005-05-30 19:22:44 +0000214 if ( !bitmap || !bitmap->buffer )
Werner Lembergafb2ba52005-05-25 05:51:01 +0000215 return FT_Err_Invalid_Argument;
216
Werner Lemberg71d76282005-05-30 07:54:20 +0000217 xstr = FT_PIX_ROUND( xStrength ) >> 6;
218 ystr = FT_PIX_ROUND( yStrength ) >> 6;
219
Werner Lemberg38e82be2005-05-30 19:22:44 +0000220 if ( xstr == 0 && ystr == 0 )
221 return FT_Err_Ok;
222 else if ( xstr < 0 || ystr < 0 )
223 return FT_Err_Invalid_Argument;
224
Werner Lembergafb2ba52005-05-25 05:51:01 +0000225 switch ( bitmap->pixel_mode )
226 {
227 case FT_PIXEL_MODE_GRAY2:
228 case FT_PIXEL_MODE_GRAY4:
Werner Lemberg38e82be2005-05-30 19:22:44 +0000229 {
230 FT_Bitmap tmp;
231 FT_Int align;
232
233
234 if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )
235 align = ( bitmap->width + xstr + 3 ) / 4;
236 else
237 align = ( bitmap->width + xstr + 1 ) / 2;
238
239 FT_Bitmap_New( &tmp );
240 error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
241
242 if ( error )
243 return error;
244
245 FT_Bitmap_Done( library, bitmap );
246 *bitmap = tmp;
247 }
248 break;
249
250 case FT_PIXEL_MODE_MONO:
251 if ( xstr > 8 )
252 xstr = 8;
253 break;
254
Werner Lemberg71d76282005-05-30 07:54:20 +0000255 case FT_PIXEL_MODE_LCD:
256 xstr *= 3;
257 break;
Werner Lemberg38e82be2005-05-30 19:22:44 +0000258
Werner Lemberg71d76282005-05-30 07:54:20 +0000259 case FT_PIXEL_MODE_LCD_V:
260 ystr *= 3;
261 break;
Werner Lembergafb2ba52005-05-25 05:51:01 +0000262 }
263
Werner Lembergafb2ba52005-05-25 05:51:01 +0000264 error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
265 if ( error )
266 return error;
267
268 pitch = bitmap->pitch;
269 if ( pitch > 0 )
270 p = bitmap->buffer + pitch * ystr;
271 else
272 {
273 pitch = -pitch;
Werner Lembergc162eac2005-05-28 21:52:37 +0000274 p = bitmap->buffer + pitch * ( bitmap->rows - 1 );
Werner Lembergafb2ba52005-05-25 05:51:01 +0000275 }
276
277 /* for each row */
278 for ( y = 0; y < bitmap->rows ; y++ )
279 {
David Turnerc5621622005-06-30 11:46:46 +0000280 /*
Werner Lembergafb2ba52005-05-25 05:51:01 +0000281 * Horizontally:
282 *
283 * From the last pixel on, make each pixel or'ed with the
284 * `xstr' pixels before it.
285 */
286 for ( x = pitch - 1; x >= 0; x-- )
287 {
288 unsigned char tmp;
289
290
291 tmp = p[x];
292 for ( i = 1; i <= xstr; i++ )
293 {
294 if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
295 {
296 p[x] |= tmp >> i;
297
298 /* the maximum value of 8 for `xstr' comes from here */
299 if ( x > 0 )
300 p[x] |= p[x - 1] << ( 8 - i );
Werner Lembergc162eac2005-05-28 21:52:37 +0000301
302#if 0
303 if ( p[x] == 0xff )
304 break;
305#endif
Werner Lembergafb2ba52005-05-25 05:51:01 +0000306 }
Werner Lemberg71d76282005-05-30 07:54:20 +0000307 else
Werner Lembergafb2ba52005-05-25 05:51:01 +0000308 {
309 if ( x - i >= 0 )
310 {
Werner Lemberg71d76282005-05-30 07:54:20 +0000311 if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
Werner Lembergc162eac2005-05-28 21:52:37 +0000312 {
David Turnerc5621622005-06-30 11:46:46 +0000313 p[x] = (unsigned char)(bitmap->num_grays - 1);
Werner Lembergc162eac2005-05-28 21:52:37 +0000314 break;
315 }
Werner Lembergafb2ba52005-05-25 05:51:01 +0000316 else
Werner Lembergc162eac2005-05-28 21:52:37 +0000317 {
David Turnerc5621622005-06-30 11:46:46 +0000318 p[x] = (unsigned char)(p[x] + p[x-i]);
Werner Lemberg71d76282005-05-30 07:54:20 +0000319 if ( p[x] == bitmap->num_grays - 1 )
Werner Lembergc162eac2005-05-28 21:52:37 +0000320 break;
321 }
Werner Lembergafb2ba52005-05-25 05:51:01 +0000322 }
Werner Lembergc162eac2005-05-28 21:52:37 +0000323 else
324 break;
Werner Lembergafb2ba52005-05-25 05:51:01 +0000325 }
326 }
327 }
328
David Turnerc5621622005-06-30 11:46:46 +0000329 /*
Werner Lembergafb2ba52005-05-25 05:51:01 +0000330 * Vertically:
331 *
332 * Make the above `ystr' rows or'ed with it.
333 */
334 for ( x = 1; x <= ystr; x++ )
335 {
336 unsigned char* q;
337
338
339 q = p - bitmap->pitch * x;
340 for ( i = 0; i < pitch; i++ )
341 q[i] |= p[i];
342 }
343
344 p += bitmap->pitch;
345 }
346
347 bitmap->width += xstr;
348 bitmap->rows += ystr;
349
350 return FT_Err_Ok;
351 }
352
353
Werner Lembergb9ee7372005-05-20 21:52:19 +0000354 /* documentation is in ftbitmap.h */
355
356 FT_EXPORT_DEF( FT_Error )
Werner Lembergf2438e12004-12-14 16:01:29 +0000357 FT_Bitmap_Convert( FT_Library library,
358 const FT_Bitmap *source,
359 FT_Bitmap *target,
360 FT_Int alignment )
361 {
Werner Lemberg0f2a4152004-12-28 07:31:35 +0000362 FT_Error error = FT_Err_Ok;
Werner Lembergf2438e12004-12-14 16:01:29 +0000363 FT_Memory memory;
Werner Lembergf2438e12004-12-14 16:01:29 +0000364
365
366 if ( !library )
367 return FT_Err_Invalid_Library_Handle;
368
369 memory = library->memory;
370
371 switch ( source->pixel_mode )
372 {
373 case FT_PIXEL_MODE_MONO:
374 case FT_PIXEL_MODE_GRAY:
375 case FT_PIXEL_MODE_GRAY2:
376 case FT_PIXEL_MODE_GRAY4:
David Turnere99b9a92005-02-10 16:11:29 +0000377 {
378 FT_Int pad;
379 FT_Long old_size;
Werner Lembergf2438e12004-12-14 16:01:29 +0000380
Werner Lemberg0358b212005-02-10 16:59:37 +0000381
David Turnere99b9a92005-02-10 16:11:29 +0000382 old_size = target->rows * target->pitch;
383 if ( old_size < 0 )
384 old_size = -old_size;
Werner Lembergf2438e12004-12-14 16:01:29 +0000385
David Turnere99b9a92005-02-10 16:11:29 +0000386 target->pixel_mode = FT_PIXEL_MODE_GRAY;
387 target->rows = source->rows;
388 target->width = source->width;
389
390 pad = 0;
391 if ( alignment > 0 )
392 {
393 pad = source->width % alignment;
394 if ( pad != 0 )
395 pad = alignment - pad;
396 }
397
398 target->pitch = source->width + pad;
399
Werner Lemberg0358b212005-02-10 16:59:37 +0000400 if ( target->rows * target->pitch > old_size &&
David Turnere99b9a92005-02-10 16:11:29 +0000401 FT_QREALLOC( target->buffer,
Werner Lembergf2438e12004-12-14 16:01:29 +0000402 old_size, target->rows * target->pitch ) )
403 return error;
David Turnere99b9a92005-02-10 16:11:29 +0000404 }
Werner Lembergf2438e12004-12-14 16:01:29 +0000405 break;
406
407 default:
408 error = FT_Err_Invalid_Argument;
409 }
410
Werner Lembergf2438e12004-12-14 16:01:29 +0000411 switch ( source->pixel_mode )
412 {
413 case FT_PIXEL_MODE_MONO:
Werner Lembergf2438e12004-12-14 16:01:29 +0000414 {
David Turnere99b9a92005-02-10 16:11:29 +0000415 FT_Byte* s = source->buffer;
416 FT_Byte* t = target->buffer;
417 FT_Int i;
Werner Lembergf2438e12004-12-14 16:01:29 +0000418
Werner Lemberg0358b212005-02-10 16:59:37 +0000419
David Turnere99b9a92005-02-10 16:11:29 +0000420 target->num_grays = 2;
421
422 for ( i = source->rows; i > 0; i-- )
Werner Lembergf2438e12004-12-14 16:01:29 +0000423 {
David Turnere99b9a92005-02-10 16:11:29 +0000424 FT_Byte* ss = s;
425 FT_Byte* tt = t;
426 FT_Int j;
Werner Lembergf2438e12004-12-14 16:01:29 +0000427
Werner Lemberg0358b212005-02-10 16:59:37 +0000428
David Turnere99b9a92005-02-10 16:11:29 +0000429 /* get the full bytes */
430 for ( j = source->width >> 3; j > 0; j-- )
431 {
432 FT_Int val = ss[0]; /* avoid a byte->int cast on each line */
433
Werner Lemberg0358b212005-02-10 16:59:37 +0000434
David Turnere99b9a92005-02-10 16:11:29 +0000435 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
436 tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
437 tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
438 tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
439 tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
440 tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
441 tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
442 tt[7] = (FT_Byte)( val & 0x01 );
443
444 tt += 8;
445 ss += 1;
446 }
447
448 /* get remaining pixels (if any) */
449 j = source->width & 7;
450 if ( j > 0 )
451 {
452 FT_Int val = *ss;
453
Werner Lemberg0358b212005-02-10 16:59:37 +0000454
David Turnere99b9a92005-02-10 16:11:29 +0000455 for ( ; j > 0; j-- )
456 {
Werner Lemberg0358b212005-02-10 16:59:37 +0000457 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
David Turnere99b9a92005-02-10 16:11:29 +0000458 val <<= 1;
459 tt += 1;
460 }
461 }
462
463 s += source->pitch;
464 t += target->pitch;
Werner Lembergf2438e12004-12-14 16:01:29 +0000465 }
Werner Lembergf2438e12004-12-14 16:01:29 +0000466 }
467 break;
468
David Turnere99b9a92005-02-10 16:11:29 +0000469
Werner Lembergf2438e12004-12-14 16:01:29 +0000470 case FT_PIXEL_MODE_GRAY:
Werner Lembergf2438e12004-12-14 16:01:29 +0000471 {
David Turnere99b9a92005-02-10 16:11:29 +0000472 FT_Int width = source->width;
473 FT_Byte* s = source->buffer;
474 FT_Byte* t = target->buffer;
475 FT_Int s_pitch = source->pitch;
476 FT_Int t_pitch = target->pitch;
477 FT_Int i;
Werner Lembergf2438e12004-12-14 16:01:29 +0000478
Werner Lemberg0358b212005-02-10 16:59:37 +0000479
David Turnere99b9a92005-02-10 16:11:29 +0000480 target->num_grays = 256;
Werner Lembergf2438e12004-12-14 16:01:29 +0000481
David Turnere99b9a92005-02-10 16:11:29 +0000482 for ( i = source->rows; i > 0; i-- )
483 {
484 FT_ARRAY_COPY( t, s, width );
485
486 s += s_pitch;
487 t += t_pitch;
488 }
Werner Lembergf2438e12004-12-14 16:01:29 +0000489 }
490 break;
491
David Turnere99b9a92005-02-10 16:11:29 +0000492
Werner Lembergf2438e12004-12-14 16:01:29 +0000493 case FT_PIXEL_MODE_GRAY2:
Werner Lembergf2438e12004-12-14 16:01:29 +0000494 {
David Turnere99b9a92005-02-10 16:11:29 +0000495 FT_Byte* s = source->buffer;
496 FT_Byte* t = target->buffer;
497 FT_Int i;
Werner Lembergf2438e12004-12-14 16:01:29 +0000498
Werner Lemberg0358b212005-02-10 16:59:37 +0000499
David Turnere99b9a92005-02-10 16:11:29 +0000500 target->num_grays = 4;
501
502 for ( i = source->rows; i > 0; i-- )
Werner Lembergf2438e12004-12-14 16:01:29 +0000503 {
David Turnere99b9a92005-02-10 16:11:29 +0000504 FT_Byte* ss = s;
505 FT_Byte* tt = t;
506 FT_Int j;
Werner Lembergf2438e12004-12-14 16:01:29 +0000507
Werner Lemberg0358b212005-02-10 16:59:37 +0000508
David Turnere99b9a92005-02-10 16:11:29 +0000509 /* get the full bytes */
510 for ( j = source->width >> 2; j > 0; j-- )
511 {
512 FT_Int val = ss[0];
513
Werner Lemberg0358b212005-02-10 16:59:37 +0000514
515 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
516 tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
517 tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
518 tt[3] = (FT_Byte)( ( val & 0x03 ) );
David Turnere99b9a92005-02-10 16:11:29 +0000519
520 ss += 1;
521 tt += 4;
522 }
523
524 j = source->width & 3;
525 if ( j > 0 )
526 {
527 FT_Int val = ss[0];
528
Werner Lemberg0358b212005-02-10 16:59:37 +0000529
David Turnere99b9a92005-02-10 16:11:29 +0000530 for ( ; j > 0; j-- )
531 {
532 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
533 val <<= 2;
534 tt += 1;
535 }
536 }
537
538 s += source->pitch;
539 t += target->pitch;
Werner Lembergf2438e12004-12-14 16:01:29 +0000540 }
Werner Lembergf2438e12004-12-14 16:01:29 +0000541 }
542 break;
543
David Turnere99b9a92005-02-10 16:11:29 +0000544
Werner Lembergf2438e12004-12-14 16:01:29 +0000545 case FT_PIXEL_MODE_GRAY4:
Werner Lembergf2438e12004-12-14 16:01:29 +0000546 {
David Turnere99b9a92005-02-10 16:11:29 +0000547 FT_Byte* s = source->buffer;
548 FT_Byte* t = target->buffer;
549 FT_Int i;
Werner Lembergf2438e12004-12-14 16:01:29 +0000550
Werner Lemberg0358b212005-02-10 16:59:37 +0000551
David Turnere99b9a92005-02-10 16:11:29 +0000552 target->num_grays = 16;
553
554 for ( i = source->rows; i > 0; i-- )
Werner Lembergf2438e12004-12-14 16:01:29 +0000555 {
David Turnere99b9a92005-02-10 16:11:29 +0000556 FT_Byte* ss = s;
557 FT_Byte* tt = t;
558 FT_Int j;
Werner Lembergf2438e12004-12-14 16:01:29 +0000559
Werner Lemberg0358b212005-02-10 16:59:37 +0000560
David Turnere99b9a92005-02-10 16:11:29 +0000561 /* get the full bytes */
562 for ( j = source->width >> 1; j > 0; j-- )
563 {
564 FT_Int val = ss[0];
565
Werner Lemberg0358b212005-02-10 16:59:37 +0000566
567 tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
568 tt[1] = (FT_Byte)( ( val & 0x0F ) );
David Turnere99b9a92005-02-10 16:11:29 +0000569
570 ss += 1;
571 tt += 2;
572 }
573
574 if ( source->width & 1 )
575 tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
576
577 s += source->pitch;
578 t += target->pitch;
Werner Lembergf2438e12004-12-14 16:01:29 +0000579 }
Werner Lembergf2438e12004-12-14 16:01:29 +0000580 }
581 break;
582
Werner Lemberg0358b212005-02-10 16:59:37 +0000583
David Turnere99b9a92005-02-10 16:11:29 +0000584 default:
585 ;
Werner Lembergf2438e12004-12-14 16:01:29 +0000586 }
587
588 return error;
589 }
590
591
592 /* documentation is in ftbitmap.h */
593
594 FT_EXPORT_DEF( FT_Error )
595 FT_Bitmap_Done( FT_Library library,
596 FT_Bitmap *bitmap )
597 {
598 FT_Memory memory;
599
600
601 if ( !library )
602 return FT_Err_Invalid_Library_Handle;
603
604 if ( !bitmap )
605 return FT_Err_Invalid_Argument;
606
607 memory = library->memory;
608
609 FT_FREE( bitmap->buffer );
610 *bitmap = null_bitmap;
611
612 return FT_Err_Ok;
613 }
614
615
616/* END */