OLD | NEW |
| (Empty) |
1 #if !defined(_FXFT_VERSION_) || _FXFT_VERSION_ == 2501 | |
2 /***************************************************************************/ | |
3 /* */ | |
4 /* ftbitmap.c */ | |
5 /* */ | |
6 /* FreeType utility functions for bitmaps (body). */ | |
7 /* */ | |
8 /* Copyright 2004-2009, 2011, 2013 by */ | |
9 /* 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 #define FT2_BUILD_LIBRARY | |
20 #include "../../include/ft2build.h" | |
21 #include "../../include/freetype/internal/ftdebug.h" | |
22 #include "../../include/freetype/ftbitmap.h" | |
23 #include "../../include/freetype/ftimage.h" | |
24 #include "../../include/freetype/internal/ftobjs.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 #endif | |
760 | |
OLD | NEW |