00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ft2build.h>
00020 #include FT_BITMAP_H
00021 #include FT_IMAGE_H
00022 #include FT_INTERNAL_OBJECTS_H
00023
00024
00025 static
00026 const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
00027
00028
00029
00030
00031 FT_EXPORT_DEF( void )
00032 FT_Bitmap_New( FT_Bitmap *abitmap )
00033 {
00034 *abitmap = null_bitmap;
00035 }
00036
00037
00038
00039
00040 FT_EXPORT_DEF( FT_Error )
00041 FT_Bitmap_Copy( FT_Library library,
00042 const FT_Bitmap *source,
00043 FT_Bitmap *target)
00044 {
00045 FT_Memory memory = library->memory;
00046 FT_Error error = FT_Err_Ok;
00047 FT_Int pitch = source->pitch;
00048 FT_ULong size;
00049
00050
00051 if ( source == target )
00052 return FT_Err_Ok;
00053
00054 if ( source->buffer == NULL )
00055 {
00056 *target = *source;
00057
00058 return FT_Err_Ok;
00059 }
00060
00061 if ( pitch < 0 )
00062 pitch = -pitch;
00063 size = (FT_ULong)( pitch * source->rows );
00064
00065 if ( target->buffer )
00066 {
00067 FT_Int target_pitch = target->pitch;
00068 FT_ULong target_size;
00069
00070
00071 if ( target_pitch < 0 )
00072 target_pitch = -target_pitch;
00073 target_size = (FT_ULong)( target_pitch * target->rows );
00074
00075 if ( target_size != size )
00076 (void)FT_QREALLOC( target->buffer, target_size, size );
00077 }
00078 else
00079 (void)FT_QALLOC( target->buffer, size );
00080
00081 if ( !error )
00082 {
00083 unsigned char *p;
00084
00085
00086 p = target->buffer;
00087 *target = *source;
00088 target->buffer = p;
00089
00090 FT_MEM_COPY( target->buffer, source->buffer, size );
00091 }
00092
00093 return error;
00094 }
00095
00096
00097 static FT_Error
00098 ft_bitmap_assure_buffer( FT_Memory memory,
00099 FT_Bitmap* bitmap,
00100 FT_UInt xpixels,
00101 FT_UInt ypixels )
00102 {
00103 FT_Error error;
00104 int pitch;
00105 int new_pitch;
00106 FT_UInt bpp;
00107 FT_Int i, width, height;
00108 unsigned char* buffer;
00109
00110
00111 width = bitmap->width;
00112 height = bitmap->rows;
00113 pitch = bitmap->pitch;
00114 if ( pitch < 0 )
00115 pitch = -pitch;
00116
00117 switch ( bitmap->pixel_mode )
00118 {
00119 case FT_PIXEL_MODE_MONO:
00120 bpp = 1;
00121 new_pitch = ( width + xpixels + 7 ) >> 3;
00122 break;
00123 case FT_PIXEL_MODE_GRAY2:
00124 bpp = 2;
00125 new_pitch = ( width + xpixels + 3 ) >> 2;
00126 break;
00127 case FT_PIXEL_MODE_GRAY4:
00128 bpp = 4;
00129 new_pitch = ( width + xpixels + 1 ) >> 1;
00130 break;
00131 case FT_PIXEL_MODE_GRAY:
00132 case FT_PIXEL_MODE_LCD:
00133 case FT_PIXEL_MODE_LCD_V:
00134 bpp = 8;
00135 new_pitch = ( width + xpixels );
00136 break;
00137 default:
00138 return FT_Err_Invalid_Glyph_Format;
00139 }
00140
00141
00142 if ( ypixels == 0 && new_pitch <= pitch )
00143 {
00144
00145 FT_Int bit_width = pitch * 8;
00146 FT_Int bit_last = ( width + xpixels ) * bpp;
00147
00148
00149 if ( bit_last < bit_width )
00150 {
00151 FT_Byte* line = bitmap->buffer + ( bit_last >> 3 );
00152 FT_Byte* end = bitmap->buffer + pitch;
00153 FT_Int shift = bit_last & 7;
00154 FT_UInt mask = 0xFF00U >> shift;
00155 FT_Int count = height;
00156
00157
00158 for ( ; count > 0; count--, line += pitch, end += pitch )
00159 {
00160 FT_Byte* write = line;
00161
00162
00163 if ( shift > 0 )
00164 {
00165 write[0] = (FT_Byte)( write[0] & mask );
00166 write++;
00167 }
00168 if ( write < end )
00169 FT_MEM_ZERO( write, end-write );
00170 }
00171 }
00172
00173 return FT_Err_Ok;
00174 }
00175
00176 if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )
00177 return error;
00178
00179 if ( bitmap->pitch > 0 )
00180 {
00181 FT_Int len = ( width * bpp + 7 ) >> 3;
00182
00183
00184 for ( i = 0; i < bitmap->rows; i++ )
00185 FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),
00186 bitmap->buffer + pitch * i, len );
00187 }
00188 else
00189 {
00190 FT_Int len = ( width * bpp + 7 ) >> 3;
00191
00192
00193 for ( i = 0; i < bitmap->rows; i++ )
00194 FT_MEM_COPY( buffer + new_pitch * i,
00195 bitmap->buffer + pitch * i, len );
00196 }
00197
00198 FT_FREE( bitmap->buffer );
00199 bitmap->buffer = buffer;
00200
00201 if ( bitmap->pitch < 0 )
00202 new_pitch = -new_pitch;
00203
00204
00205 bitmap->pitch = new_pitch;
00206
00207 return FT_Err_Ok;
00208 }
00209
00210
00211
00212
00213 FT_EXPORT_DEF( FT_Error )
00214 FT_Bitmap_Embolden( FT_Library library,
00215 FT_Bitmap* bitmap,
00216 FT_Pos xStrength,
00217 FT_Pos yStrength )
00218 {
00219 FT_Error error;
00220 unsigned char* p;
00221 FT_Int i, x, y, pitch;
00222 FT_Int xstr, ystr;
00223
00224
00225 if ( !library )
00226 return FT_Err_Invalid_Library_Handle;
00227
00228 if ( !bitmap || !bitmap->buffer )
00229 return FT_Err_Invalid_Argument;
00230
00231 if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
00232 ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
00233 return FT_Err_Invalid_Argument;
00234
00235 xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
00236 ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;
00237
00238 if ( xstr == 0 && ystr == 0 )
00239 return FT_Err_Ok;
00240 else if ( xstr < 0 || ystr < 0 )
00241 return FT_Err_Invalid_Argument;
00242
00243 switch ( bitmap->pixel_mode )
00244 {
00245 case FT_PIXEL_MODE_GRAY2:
00246 case FT_PIXEL_MODE_GRAY4:
00247 {
00248 FT_Bitmap tmp;
00249 FT_Int align;
00250
00251
00252 if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )
00253 align = ( bitmap->width + xstr + 3 ) / 4;
00254 else
00255 align = ( bitmap->width + xstr + 1 ) / 2;
00256
00257 FT_Bitmap_New( &tmp );
00258
00259 error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
00260 if ( error )
00261 return error;
00262
00263 FT_Bitmap_Done( library, bitmap );
00264 *bitmap = tmp;
00265 }
00266 break;
00267
00268 case FT_PIXEL_MODE_MONO:
00269 if ( xstr > 8 )
00270 xstr = 8;
00271 break;
00272
00273 case FT_PIXEL_MODE_LCD:
00274 xstr *= 3;
00275 break;
00276
00277 case FT_PIXEL_MODE_LCD_V:
00278 ystr *= 3;
00279 break;
00280 }
00281
00282 error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
00283 if ( error )
00284 return error;
00285
00286 pitch = bitmap->pitch;
00287 if ( pitch > 0 )
00288 p = bitmap->buffer + pitch * ystr;
00289 else
00290 {
00291 pitch = -pitch;
00292 p = bitmap->buffer + pitch * ( bitmap->rows - 1 );
00293 }
00294
00295
00296 for ( y = 0; y < bitmap->rows ; y++ )
00297 {
00298
00299
00300
00301
00302
00303
00304 for ( x = pitch - 1; x >= 0; x-- )
00305 {
00306 unsigned char tmp;
00307
00308
00309 tmp = p[x];
00310 for ( i = 1; i <= xstr; i++ )
00311 {
00312 if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
00313 {
00314 p[x] |= tmp >> i;
00315
00316
00317 if ( x > 0 )
00318 p[x] |= p[x - 1] << ( 8 - i );
00319
00320 #if 0
00321 if ( p[x] == 0xff )
00322 break;
00323 #endif
00324 }
00325 else
00326 {
00327 if ( x - i >= 0 )
00328 {
00329 if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
00330 {
00331 p[x] = (unsigned char)(bitmap->num_grays - 1);
00332 break;
00333 }
00334 else
00335 {
00336 p[x] = (unsigned char)(p[x] + p[x-i]);
00337 if ( p[x] == bitmap->num_grays - 1 )
00338 break;
00339 }
00340 }
00341 else
00342 break;
00343 }
00344 }
00345 }
00346
00347
00348
00349
00350
00351
00352 for ( x = 1; x <= ystr; x++ )
00353 {
00354 unsigned char* q;
00355
00356
00357 q = p - bitmap->pitch * x;
00358 for ( i = 0; i < pitch; i++ )
00359 q[i] |= p[i];
00360 }
00361
00362 p += bitmap->pitch;
00363 }
00364
00365 bitmap->width += xstr;
00366 bitmap->rows += ystr;
00367
00368 return FT_Err_Ok;
00369 }
00370
00371
00372
00373
00374 FT_EXPORT_DEF( FT_Error )
00375 FT_Bitmap_Convert( FT_Library library,
00376 const FT_Bitmap *source,
00377 FT_Bitmap *target,
00378 FT_Int alignment )
00379 {
00380 FT_Error error = FT_Err_Ok;
00381 FT_Memory memory;
00382
00383
00384 if ( !library )
00385 return FT_Err_Invalid_Library_Handle;
00386
00387 memory = library->memory;
00388
00389 switch ( source->pixel_mode )
00390 {
00391 case FT_PIXEL_MODE_MONO:
00392 case FT_PIXEL_MODE_GRAY:
00393 case FT_PIXEL_MODE_GRAY2:
00394 case FT_PIXEL_MODE_GRAY4:
00395 case FT_PIXEL_MODE_LCD:
00396 case FT_PIXEL_MODE_LCD_V:
00397 {
00398 FT_Int pad;
00399 FT_Long old_size;
00400
00401
00402 old_size = target->rows * target->pitch;
00403 if ( old_size < 0 )
00404 old_size = -old_size;
00405
00406 target->pixel_mode = FT_PIXEL_MODE_GRAY;
00407 target->rows = source->rows;
00408 target->width = source->width;
00409
00410 pad = 0;
00411 if ( alignment > 0 )
00412 {
00413 pad = source->width % alignment;
00414 if ( pad != 0 )
00415 pad = alignment - pad;
00416 }
00417
00418 target->pitch = source->width + pad;
00419
00420 if ( target->rows * target->pitch > old_size &&
00421 FT_QREALLOC( target->buffer,
00422 old_size, target->rows * target->pitch ) )
00423 return error;
00424 }
00425 break;
00426
00427 default:
00428 error = FT_Err_Invalid_Argument;
00429 }
00430
00431 switch ( source->pixel_mode )
00432 {
00433 case FT_PIXEL_MODE_MONO:
00434 {
00435 FT_Byte* s = source->buffer;
00436 FT_Byte* t = target->buffer;
00437 FT_Int i;
00438
00439
00440 target->num_grays = 2;
00441
00442 for ( i = source->rows; i > 0; i-- )
00443 {
00444 FT_Byte* ss = s;
00445 FT_Byte* tt = t;
00446 FT_Int j;
00447
00448
00449
00450 for ( j = source->width >> 3; j > 0; j-- )
00451 {
00452 FT_Int val = ss[0];
00453
00454
00455 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
00456 tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
00457 tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
00458 tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
00459 tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
00460 tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
00461 tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
00462 tt[7] = (FT_Byte)( val & 0x01 );
00463
00464 tt += 8;
00465 ss += 1;
00466 }
00467
00468
00469 j = source->width & 7;
00470 if ( j > 0 )
00471 {
00472 FT_Int val = *ss;
00473
00474
00475 for ( ; j > 0; j-- )
00476 {
00477 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
00478 val <<= 1;
00479 tt += 1;
00480 }
00481 }
00482
00483 s += source->pitch;
00484 t += target->pitch;
00485 }
00486 }
00487 break;
00488
00489
00490 case FT_PIXEL_MODE_GRAY:
00491 case FT_PIXEL_MODE_LCD:
00492 case FT_PIXEL_MODE_LCD_V:
00493 {
00494 FT_Int width = source->width;
00495 FT_Byte* s = source->buffer;
00496 FT_Byte* t = target->buffer;
00497 FT_Int s_pitch = source->pitch;
00498 FT_Int t_pitch = target->pitch;
00499 FT_Int i;
00500
00501
00502 target->num_grays = 256;
00503
00504 for ( i = source->rows; i > 0; i-- )
00505 {
00506 FT_ARRAY_COPY( t, s, width );
00507
00508 s += s_pitch;
00509 t += t_pitch;
00510 }
00511 }
00512 break;
00513
00514
00515 case FT_PIXEL_MODE_GRAY2:
00516 {
00517 FT_Byte* s = source->buffer;
00518 FT_Byte* t = target->buffer;
00519 FT_Int i;
00520
00521
00522 target->num_grays = 4;
00523
00524 for ( i = source->rows; i > 0; i-- )
00525 {
00526 FT_Byte* ss = s;
00527 FT_Byte* tt = t;
00528 FT_Int j;
00529
00530
00531
00532 for ( j = source->width >> 2; j > 0; j-- )
00533 {
00534 FT_Int val = ss[0];
00535
00536
00537 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
00538 tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
00539 tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
00540 tt[3] = (FT_Byte)( ( val & 0x03 ) );
00541
00542 ss += 1;
00543 tt += 4;
00544 }
00545
00546 j = source->width & 3;
00547 if ( j > 0 )
00548 {
00549 FT_Int val = ss[0];
00550
00551
00552 for ( ; j > 0; j-- )
00553 {
00554 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
00555 val <<= 2;
00556 tt += 1;
00557 }
00558 }
00559
00560 s += source->pitch;
00561 t += target->pitch;
00562 }
00563 }
00564 break;
00565
00566
00567 case FT_PIXEL_MODE_GRAY4:
00568 {
00569 FT_Byte* s = source->buffer;
00570 FT_Byte* t = target->buffer;
00571 FT_Int i;
00572
00573
00574 target->num_grays = 16;
00575
00576 for ( i = source->rows; i > 0; i-- )
00577 {
00578 FT_Byte* ss = s;
00579 FT_Byte* tt = t;
00580 FT_Int j;
00581
00582
00583
00584 for ( j = source->width >> 1; j > 0; j-- )
00585 {
00586 FT_Int val = ss[0];
00587
00588
00589 tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
00590 tt[1] = (FT_Byte)( ( val & 0x0F ) );
00591
00592 ss += 1;
00593 tt += 2;
00594 }
00595
00596 if ( source->width & 1 )
00597 tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
00598
00599 s += source->pitch;
00600 t += target->pitch;
00601 }
00602 }
00603 break;
00604
00605
00606 default:
00607 ;
00608 }
00609
00610 return error;
00611 }
00612
00613
00614
00615
00616 FT_EXPORT_DEF( FT_Error )
00617 FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot )
00618 {
00619 if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP &&
00620 !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
00621 {
00622 FT_Bitmap bitmap;
00623 FT_Error error;
00624
00625
00626 FT_Bitmap_New( &bitmap );
00627 error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
00628 if ( error )
00629 return error;
00630
00631 slot->bitmap = bitmap;
00632 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
00633 }
00634
00635 return FT_Err_Ok;
00636 }
00637
00638
00639
00640
00641 FT_EXPORT_DEF( FT_Error )
00642 FT_Bitmap_Done( FT_Library library,
00643 FT_Bitmap *bitmap )
00644 {
00645 FT_Memory memory;
00646
00647
00648 if ( !library )
00649 return FT_Err_Invalid_Library_Handle;
00650
00651 if ( !bitmap )
00652 return FT_Err_Invalid_Argument;
00653
00654 memory = library->memory;
00655
00656 FT_FREE( bitmap->buffer );
00657 *bitmap = null_bitmap;
00658
00659 return FT_Err_Ok;
00660 }
00661
00662
00663