1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.4 3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 16 17 #include <stdio.h> 18 #include "agg_font_freetype.h" 19 #include "agg_bitset_iterator.h" 20 #include "agg_renderer_scanline.h" 21 22 23 namespace agg 24 { 25 26 //------------------------------------------------------------------------------ 27 // 28 // This code implements the AUTODIN II polynomial 29 // The variable corresponding to the macro argument "crc" should 30 // be an unsigned long. 31 // Oroginal code by Spencer Garrett <srg@quick.com> 32 // 33 34 // generated using the AUTODIN II polynomial 35 // x^32 + x^26 + x^23 + x^22 + x^16 + 36 // x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 37 // 38 //------------------------------------------------------------------------------ 39 40 static const unsigned crc32tab[256] = 41 { 42 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 43 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 44 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 45 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 46 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 47 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 48 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 49 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 50 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 51 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 52 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 53 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 54 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 55 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 56 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 57 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 58 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 59 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 60 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 61 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 62 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 63 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 64 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 65 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 66 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 67 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 68 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 69 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 70 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 71 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 72 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 73 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 74 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 75 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 76 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 77 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 78 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 79 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 80 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 81 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 82 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 83 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 84 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 85 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 86 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 87 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 88 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 89 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 90 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 91 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 92 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 93 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 94 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 95 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 96 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 97 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 98 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 99 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 100 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 101 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 102 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 103 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 104 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 105 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, 106 }; 107 108 109 //------------------------------------------------------------------------------ 110 calc_crc32(const unsigned char * buf,unsigned size)111 static unsigned calc_crc32(const unsigned char* buf, unsigned size) 112 { 113 unsigned crc = (unsigned)~0; 114 const unsigned char* p; 115 unsigned len = 0; 116 unsigned nr = size; 117 118 for (len += nr, p = buf; nr--; ++p) 119 { 120 crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff]; 121 } 122 return ~crc; 123 } 124 125 //------------------------------------------------------------------------ dbl_to_plain_fx(double d)126 static inline int dbl_to_plain_fx(double d) 127 { 128 return int(d * 65536.0); 129 } 130 131 //------------------------------------------------------------------------ int26p6_to_dbl(int p)132 static inline double int26p6_to_dbl(int p) 133 { 134 return double(p) / 64.0; 135 } 136 137 //------------------------------------------------------------------------ dbl_to_int26p6(double p)138 static inline int dbl_to_int26p6(double p) 139 { 140 return int(p * 64.0 + 0.5); 141 } 142 143 144 //------------------------------------------------------------------------ 145 template<class PathStorage> decompose_ft_outline(const FT_Outline & outline,bool flip_y,const trans_affine & mtx,PathStorage & path)146 bool decompose_ft_outline(const FT_Outline& outline, 147 bool flip_y, 148 const trans_affine& mtx, 149 PathStorage& path) 150 { 151 typedef typename PathStorage::value_type value_type; 152 153 FT_Vector v_last; 154 FT_Vector v_control; 155 FT_Vector v_start; 156 double x1, y1, x2, y2, x3, y3; 157 158 FT_Vector* point; 159 FT_Vector* limit; 160 char* tags; 161 162 int n; // index of contour in outline 163 int first; // index of first point in contour 164 char tag; // current point's state 165 166 first = 0; 167 168 for(n = 0; n < outline.n_contours; n++) 169 { 170 int last; // index of last point in contour 171 172 last = outline.contours[n]; 173 limit = outline.points + last; 174 175 v_start = outline.points[first]; 176 v_last = outline.points[last]; 177 178 v_control = v_start; 179 180 point = outline.points + first; 181 tags = outline.tags + first; 182 tag = FT_CURVE_TAG(tags[0]); 183 184 // A contour cannot start with a cubic control point! 185 if(tag == FT_CURVE_TAG_CUBIC) return false; 186 187 // check first point to determine origin 188 if( tag == FT_CURVE_TAG_CONIC) 189 { 190 // first point is conic control. Yes, this happens. 191 if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) 192 { 193 // start at last point if it is on the curve 194 v_start = v_last; 195 limit--; 196 } 197 else 198 { 199 // if both first and last points are conic, 200 // start at their middle and record its position 201 // for closure 202 v_start.x = (v_start.x + v_last.x) / 2; 203 v_start.y = (v_start.y + v_last.y) / 2; 204 205 v_last = v_start; 206 } 207 point--; 208 tags--; 209 } 210 211 x1 = int26p6_to_dbl(v_start.x); 212 y1 = int26p6_to_dbl(v_start.y); 213 if(flip_y) y1 = -y1; 214 mtx.transform(&x1, &y1); 215 path.move_to(value_type(dbl_to_int26p6(x1)), 216 value_type(dbl_to_int26p6(y1))); 217 218 while(point < limit) 219 { 220 point++; 221 tags++; 222 223 tag = FT_CURVE_TAG(tags[0]); 224 switch(tag) 225 { 226 case FT_CURVE_TAG_ON: // emit a single line_to 227 { 228 x1 = int26p6_to_dbl(point->x); 229 y1 = int26p6_to_dbl(point->y); 230 if(flip_y) y1 = -y1; 231 mtx.transform(&x1, &y1); 232 path.line_to(value_type(dbl_to_int26p6(x1)), 233 value_type(dbl_to_int26p6(y1))); 234 //path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y)); 235 continue; 236 } 237 238 case FT_CURVE_TAG_CONIC: // consume conic arcs 239 { 240 v_control.x = point->x; 241 v_control.y = point->y; 242 243 Do_Conic: 244 if(point < limit) 245 { 246 FT_Vector vec; 247 FT_Vector v_middle; 248 249 point++; 250 tags++; 251 tag = FT_CURVE_TAG(tags[0]); 252 253 vec.x = point->x; 254 vec.y = point->y; 255 256 if(tag == FT_CURVE_TAG_ON) 257 { 258 x1 = int26p6_to_dbl(v_control.x); 259 y1 = int26p6_to_dbl(v_control.y); 260 x2 = int26p6_to_dbl(vec.x); 261 y2 = int26p6_to_dbl(vec.y); 262 if(flip_y) { y1 = -y1; y2 = -y2; } 263 mtx.transform(&x1, &y1); 264 mtx.transform(&x2, &y2); 265 path.curve3(value_type(dbl_to_int26p6(x1)), 266 value_type(dbl_to_int26p6(y1)), 267 value_type(dbl_to_int26p6(x2)), 268 value_type(dbl_to_int26p6(y2))); 269 continue; 270 } 271 272 if(tag != FT_CURVE_TAG_CONIC) return false; 273 274 v_middle.x = (v_control.x + vec.x) / 2; 275 v_middle.y = (v_control.y + vec.y) / 2; 276 277 x1 = int26p6_to_dbl(v_control.x); 278 y1 = int26p6_to_dbl(v_control.y); 279 x2 = int26p6_to_dbl(v_middle.x); 280 y2 = int26p6_to_dbl(v_middle.y); 281 if(flip_y) { y1 = -y1; y2 = -y2; } 282 mtx.transform(&x1, &y1); 283 mtx.transform(&x2, &y2); 284 path.curve3(value_type(dbl_to_int26p6(x1)), 285 value_type(dbl_to_int26p6(y1)), 286 value_type(dbl_to_int26p6(x2)), 287 value_type(dbl_to_int26p6(y2))); 288 289 //path.curve3(conv(v_control.x), 290 // flip_y ? -conv(v_control.y) : conv(v_control.y), 291 // conv(v_middle.x), 292 // flip_y ? -conv(v_middle.y) : conv(v_middle.y)); 293 294 v_control = vec; 295 goto Do_Conic; 296 } 297 298 x1 = int26p6_to_dbl(v_control.x); 299 y1 = int26p6_to_dbl(v_control.y); 300 x2 = int26p6_to_dbl(v_start.x); 301 y2 = int26p6_to_dbl(v_start.y); 302 if(flip_y) { y1 = -y1; y2 = -y2; } 303 mtx.transform(&x1, &y1); 304 mtx.transform(&x2, &y2); 305 path.curve3(value_type(dbl_to_int26p6(x1)), 306 value_type(dbl_to_int26p6(y1)), 307 value_type(dbl_to_int26p6(x2)), 308 value_type(dbl_to_int26p6(y2))); 309 310 //path.curve3(conv(v_control.x), 311 // flip_y ? -conv(v_control.y) : conv(v_control.y), 312 // conv(v_start.x), 313 // flip_y ? -conv(v_start.y) : conv(v_start.y)); 314 goto Close; 315 } 316 317 default: // FT_CURVE_TAG_CUBIC 318 { 319 FT_Vector vec1, vec2; 320 321 if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC) 322 { 323 return false; 324 } 325 326 vec1.x = point[0].x; 327 vec1.y = point[0].y; 328 vec2.x = point[1].x; 329 vec2.y = point[1].y; 330 331 point += 2; 332 tags += 2; 333 334 if(point <= limit) 335 { 336 FT_Vector vec; 337 338 vec.x = point->x; 339 vec.y = point->y; 340 341 x1 = int26p6_to_dbl(vec1.x); 342 y1 = int26p6_to_dbl(vec1.y); 343 x2 = int26p6_to_dbl(vec2.x); 344 y2 = int26p6_to_dbl(vec2.y); 345 x3 = int26p6_to_dbl(vec.x); 346 y3 = int26p6_to_dbl(vec.y); 347 if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } 348 mtx.transform(&x1, &y1); 349 mtx.transform(&x2, &y2); 350 mtx.transform(&x3, &y3); 351 path.curve4(value_type(dbl_to_int26p6(x1)), 352 value_type(dbl_to_int26p6(y1)), 353 value_type(dbl_to_int26p6(x2)), 354 value_type(dbl_to_int26p6(y2)), 355 value_type(dbl_to_int26p6(x3)), 356 value_type(dbl_to_int26p6(y3))); 357 358 //path.curve4(conv(vec1.x), 359 // flip_y ? -conv(vec1.y) : conv(vec1.y), 360 // conv(vec2.x), 361 // flip_y ? -conv(vec2.y) : conv(vec2.y), 362 // conv(vec.x), 363 // flip_y ? -conv(vec.y) : conv(vec.y)); 364 continue; 365 } 366 367 x1 = int26p6_to_dbl(vec1.x); 368 y1 = int26p6_to_dbl(vec1.y); 369 x2 = int26p6_to_dbl(vec2.x); 370 y2 = int26p6_to_dbl(vec2.y); 371 x3 = int26p6_to_dbl(v_start.x); 372 y3 = int26p6_to_dbl(v_start.y); 373 if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } 374 mtx.transform(&x1, &y1); 375 mtx.transform(&x2, &y2); 376 mtx.transform(&x3, &y3); 377 path.curve4(value_type(dbl_to_int26p6(x1)), 378 value_type(dbl_to_int26p6(y1)), 379 value_type(dbl_to_int26p6(x2)), 380 value_type(dbl_to_int26p6(y2)), 381 value_type(dbl_to_int26p6(x3)), 382 value_type(dbl_to_int26p6(y3))); 383 384 //path.curve4(conv(vec1.x), 385 // flip_y ? -conv(vec1.y) : conv(vec1.y), 386 // conv(vec2.x), 387 // flip_y ? -conv(vec2.y) : conv(vec2.y), 388 // conv(v_start.x), 389 // flip_y ? -conv(v_start.y) : conv(v_start.y)); 390 goto Close; 391 } 392 } 393 } 394 395 path.close_polygon(); 396 397 Close: 398 first = last + 1; 399 } 400 401 return true; 402 } 403 404 405 406 //------------------------------------------------------------------------ 407 template<class Scanline, class ScanlineStorage> decompose_ft_bitmap_mono(const FT_Bitmap & bitmap,int x,int y,bool flip_y,Scanline & sl,ScanlineStorage & storage)408 void decompose_ft_bitmap_mono(const FT_Bitmap& bitmap, 409 int x, int y, 410 bool flip_y, 411 Scanline& sl, 412 ScanlineStorage& storage) 413 { 414 int i; 415 const int8u* buf = (const int8u*)bitmap.buffer; 416 int pitch = bitmap.pitch; 417 sl.reset(x, x + bitmap.width); 418 storage.prepare(); 419 if(flip_y) 420 { 421 buf += bitmap.pitch * (bitmap.rows - 1); 422 y += bitmap.rows; 423 pitch = -pitch; 424 } 425 for(i = 0; i < bitmap.rows; i++) 426 { 427 sl.reset_spans(); 428 bitset_iterator bits(buf, 0); 429 int j; 430 for(j = 0; j < bitmap.width; j++) 431 { 432 if(bits.bit()) sl.add_cell(x + j, cover_full); 433 ++bits; 434 } 435 buf += pitch; 436 if(sl.num_spans()) 437 { 438 sl.finalize(y - i - 1); 439 storage.render(sl); 440 } 441 } 442 } 443 444 445 446 //------------------------------------------------------------------------ 447 template<class Rasterizer, class Scanline, class ScanlineStorage> decompose_ft_bitmap_gray8(const FT_Bitmap & bitmap,int x,int y,bool flip_y,Rasterizer & ras,Scanline & sl,ScanlineStorage & storage)448 void decompose_ft_bitmap_gray8(const FT_Bitmap& bitmap, 449 int x, int y, 450 bool flip_y, 451 Rasterizer& ras, 452 Scanline& sl, 453 ScanlineStorage& storage) 454 { 455 int i, j; 456 const int8u* buf = (const int8u*)bitmap.buffer; 457 int pitch = bitmap.pitch; 458 sl.reset(x, x + bitmap.width); 459 storage.prepare(); 460 if(flip_y) 461 { 462 buf += bitmap.pitch * (bitmap.rows - 1); 463 y += bitmap.rows; 464 pitch = -pitch; 465 } 466 for(i = 0; i < bitmap.rows; i++) 467 { 468 sl.reset_spans(); 469 const int8u* p = buf; 470 for(j = 0; j < bitmap.width; j++) 471 { 472 if(*p) sl.add_cell(x + j, ras.apply_gamma(*p)); 473 ++p; 474 } 475 buf += pitch; 476 if(sl.num_spans()) 477 { 478 sl.finalize(y - i - 1); 479 storage.render(sl); 480 } 481 } 482 } 483 484 485 486 487 488 489 490 491 492 493 494 495 496 //------------------------------------------------------------------------ ~font_engine_freetype_base()497 font_engine_freetype_base::~font_engine_freetype_base() 498 { 499 unsigned i; 500 for(i = 0; i < m_num_faces; ++i) 501 { 502 delete [] m_face_names[i]; 503 FT_Done_Face(m_faces[i]); 504 } 505 delete [] m_face_names; 506 delete [] m_faces; 507 delete [] m_signature; 508 if(m_library_initialized) FT_Done_FreeType(m_library); 509 } 510 511 512 //------------------------------------------------------------------------ font_engine_freetype_base(bool flag32,unsigned max_faces)513 font_engine_freetype_base::font_engine_freetype_base(bool flag32, 514 unsigned max_faces) : 515 m_flag32(flag32), 516 m_change_stamp(0), 517 m_last_error(0), 518 m_name(0), 519 m_name_len(256-16-1), 520 m_face_index(0), 521 m_char_map(FT_ENCODING_NONE), 522 m_signature(new char [256+256-16]), 523 m_height(0), 524 m_width(0), 525 m_hinting(true), 526 m_flip_y(false), 527 m_library_initialized(false), 528 m_library(0), 529 m_faces(new FT_Face [max_faces]), 530 m_face_names(new char* [max_faces]), 531 m_num_faces(0), 532 m_max_faces(max_faces), 533 m_cur_face(0), 534 m_resolution(0), 535 m_glyph_rendering(glyph_ren_native_gray8), 536 m_glyph_index(0), 537 m_data_size(0), 538 m_data_type(glyph_data_invalid), 539 m_bounds(1,1,0,0), 540 m_advance_x(0.0), 541 m_advance_y(0.0), 542 543 m_path16(), 544 m_path32(), 545 m_curves16(m_path16), 546 m_curves32(m_path32), 547 m_scanline_aa(), 548 m_scanline_bin(), 549 m_scanlines_aa(), 550 m_scanlines_bin(), 551 m_rasterizer() 552 { 553 m_curves16.approximation_scale(4.0); 554 m_curves32.approximation_scale(4.0); 555 m_last_error = FT_Init_FreeType(&m_library); 556 if(m_last_error == 0) m_library_initialized = true; 557 } 558 559 560 561 //------------------------------------------------------------------------ resolution(unsigned dpi)562 void font_engine_freetype_base::resolution(unsigned dpi) 563 { 564 m_resolution = dpi; 565 update_char_size(); 566 } 567 568 569 //------------------------------------------------------------------------ find_face(const char * face_name) const570 int font_engine_freetype_base::find_face(const char* face_name) const 571 { 572 unsigned i; 573 for(i = 0; i < m_num_faces; ++i) 574 { 575 if(strcmp(face_name, m_face_names[i]) == 0) return i; 576 } 577 return -1; 578 } 579 580 581 //------------------------------------------------------------------------ ascender() const582 double font_engine_freetype_base::ascender() const 583 { 584 if(m_cur_face) 585 { 586 return m_cur_face->ascender * height() / m_cur_face->height; 587 } 588 return 0.0; 589 } 590 591 //------------------------------------------------------------------------ descender() const592 double font_engine_freetype_base::descender() const 593 { 594 if(m_cur_face) 595 { 596 return m_cur_face->descender * height() / m_cur_face->height; 597 } 598 return 0.0; 599 } 600 601 602 //------------------------------------------------------------------------ load_font(const char * font_name,unsigned face_index,glyph_rendering ren_type,const char * font_mem,const long font_mem_size)603 bool font_engine_freetype_base::load_font(const char* font_name, 604 unsigned face_index, 605 glyph_rendering ren_type, 606 const char* font_mem, 607 const long font_mem_size) 608 { 609 bool ret = false; 610 611 if(m_library_initialized) 612 { 613 m_last_error = 0; 614 615 int idx = find_face(font_name); 616 if(idx >= 0) 617 { 618 m_cur_face = m_faces[idx]; 619 m_name = m_face_names[idx]; 620 } 621 else 622 { 623 if(m_num_faces >= m_max_faces) 624 { 625 delete [] m_face_names[0]; 626 FT_Done_Face(m_faces[0]); 627 memcpy(m_faces, 628 m_faces + 1, 629 (m_max_faces - 1) * sizeof(FT_Face)); 630 memcpy(m_face_names, 631 m_face_names + 1, 632 (m_max_faces - 1) * sizeof(char*)); 633 m_num_faces = m_max_faces - 1; 634 } 635 636 if (font_mem && font_mem_size) 637 { 638 m_last_error = FT_New_Memory_Face(m_library, 639 (const FT_Byte*)font_mem, 640 font_mem_size, 641 face_index, 642 &m_faces[m_num_faces]); 643 } 644 else 645 { 646 m_last_error = FT_New_Face(m_library, 647 font_name, 648 face_index, 649 &m_faces[m_num_faces]); 650 } 651 652 if(m_last_error == 0) 653 { 654 m_face_names[m_num_faces] = new char [strlen(font_name) + 1]; 655 strcpy(m_face_names[m_num_faces], font_name); 656 m_cur_face = m_faces[m_num_faces]; 657 m_name = m_face_names[m_num_faces]; 658 ++m_num_faces; 659 } 660 else 661 { 662 m_face_names[m_num_faces] = 0; 663 m_cur_face = 0; 664 m_name = 0; 665 } 666 } 667 668 669 if(m_last_error == 0) 670 { 671 ret = true; 672 673 switch(ren_type) 674 { 675 case glyph_ren_native_mono: 676 m_glyph_rendering = glyph_ren_native_mono; 677 break; 678 679 case glyph_ren_native_gray8: 680 m_glyph_rendering = glyph_ren_native_gray8; 681 break; 682 683 case glyph_ren_outline: 684 if(FT_IS_SCALABLE(m_cur_face)) 685 { 686 m_glyph_rendering = glyph_ren_outline; 687 } 688 else 689 { 690 m_glyph_rendering = glyph_ren_native_gray8; 691 } 692 break; 693 694 case glyph_ren_agg_mono: 695 if(FT_IS_SCALABLE(m_cur_face)) 696 { 697 m_glyph_rendering = glyph_ren_agg_mono; 698 } 699 else 700 { 701 m_glyph_rendering = glyph_ren_native_mono; 702 } 703 break; 704 705 case glyph_ren_agg_gray8: 706 if(FT_IS_SCALABLE(m_cur_face)) 707 { 708 m_glyph_rendering = glyph_ren_agg_gray8; 709 } 710 else 711 { 712 m_glyph_rendering = glyph_ren_native_gray8; 713 } 714 break; 715 } 716 update_signature(); 717 } 718 } 719 return ret; 720 } 721 722 723 //------------------------------------------------------------------------ attach(const char * file_name)724 bool font_engine_freetype_base::attach(const char* file_name) 725 { 726 if(m_cur_face) 727 { 728 m_last_error = FT_Attach_File(m_cur_face, file_name); 729 return m_last_error == 0; 730 } 731 return false; 732 } 733 734 //------------------------------------------------------------------------ num_faces() const735 unsigned font_engine_freetype_base::num_faces() const 736 { 737 if(m_cur_face) 738 { 739 return m_cur_face->num_faces; 740 } 741 return 0; 742 } 743 744 //------------------------------------------------------------------------ char_map(FT_Encoding char_map)745 bool font_engine_freetype_base::char_map(FT_Encoding char_map) 746 { 747 if(m_cur_face) 748 { 749 m_last_error = FT_Select_Charmap(m_cur_face, char_map); 750 if(m_last_error == 0) 751 { 752 m_char_map = char_map; 753 update_signature(); 754 return true; 755 } 756 } 757 return false; 758 } 759 760 //------------------------------------------------------------------------ height(double h)761 bool font_engine_freetype_base::height(double h) 762 { 763 m_height = int(h * 64.0); 764 if(m_cur_face) 765 { 766 update_char_size(); 767 return true; 768 } 769 return false; 770 } 771 772 //------------------------------------------------------------------------ width(double w)773 bool font_engine_freetype_base::width(double w) 774 { 775 m_width = int(w * 64.0); 776 if(m_cur_face) 777 { 778 update_char_size(); 779 return true; 780 } 781 return false; 782 } 783 784 //------------------------------------------------------------------------ hinting(bool h)785 void font_engine_freetype_base::hinting(bool h) 786 { 787 m_hinting = h; 788 if(m_cur_face) 789 { 790 update_signature(); 791 } 792 } 793 794 //------------------------------------------------------------------------ flip_y(bool f)795 void font_engine_freetype_base::flip_y(bool f) 796 { 797 m_flip_y = f; 798 if(m_cur_face) 799 { 800 update_signature(); 801 } 802 } 803 804 //------------------------------------------------------------------------ transform(const trans_affine & affine)805 void font_engine_freetype_base::transform(const trans_affine& affine) 806 { 807 m_affine = affine; 808 if(m_cur_face) 809 { 810 update_signature(); 811 } 812 } 813 814 //------------------------------------------------------------------------ update_signature()815 void font_engine_freetype_base::update_signature() 816 { 817 if(m_cur_face && m_name) 818 { 819 unsigned name_len = strlen(m_name); 820 if(name_len > m_name_len) 821 { 822 delete [] m_signature; 823 m_signature = new char [name_len + 32 + 256]; 824 m_name_len = name_len + 32 - 1; 825 } 826 827 unsigned gamma_hash = 0; 828 if(m_glyph_rendering == glyph_ren_native_gray8 || 829 m_glyph_rendering == glyph_ren_agg_mono || 830 m_glyph_rendering == glyph_ren_agg_gray8) 831 { 832 unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale]; 833 unsigned i; 834 for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i) 835 { 836 gamma_table[i] = m_rasterizer.apply_gamma(i); 837 } 838 gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table)); 839 } 840 841 sprintf(m_signature, 842 "%s,%u,%d,%d,%d:%dx%d,%d,%d,%08X", 843 m_name, 844 m_char_map, 845 m_face_index, 846 int(m_glyph_rendering), 847 m_resolution, 848 m_height, 849 m_width, 850 int(m_hinting), 851 int(m_flip_y), 852 gamma_hash); 853 if(m_glyph_rendering == glyph_ren_outline || 854 m_glyph_rendering == glyph_ren_agg_mono || 855 m_glyph_rendering == glyph_ren_agg_gray8) 856 { 857 double mtx[6]; 858 char buf[100]; 859 m_affine.store_to(mtx); 860 sprintf(buf, ",%08X%08X%08X%08X%08X%08X", 861 dbl_to_plain_fx(mtx[0]), 862 dbl_to_plain_fx(mtx[1]), 863 dbl_to_plain_fx(mtx[2]), 864 dbl_to_plain_fx(mtx[3]), 865 dbl_to_plain_fx(mtx[4]), 866 dbl_to_plain_fx(mtx[5])); 867 strcat(m_signature, buf); 868 } 869 ++m_change_stamp; 870 } 871 } 872 873 874 //------------------------------------------------------------------------ update_char_size()875 void font_engine_freetype_base::update_char_size() 876 { 877 if(m_cur_face) 878 { 879 if(m_resolution) 880 { 881 FT_Set_Char_Size(m_cur_face, 882 m_width, // char_width in 1/64th of points 883 m_height, // char_height in 1/64th of points 884 m_resolution, // horizontal device resolution 885 m_resolution); // vertical device resolution 886 } 887 else 888 { 889 FT_Set_Pixel_Sizes(m_cur_face, 890 m_width >> 6, // pixel_width 891 m_height >> 6); // pixel_height 892 } 893 update_signature(); 894 } 895 } 896 897 898 899 900 901 //------------------------------------------------------------------------ prepare_glyph(unsigned glyph_code)902 bool font_engine_freetype_base::prepare_glyph(unsigned glyph_code) 903 { 904 m_glyph_index = FT_Get_Char_Index(m_cur_face, glyph_code); 905 m_last_error = FT_Load_Glyph(m_cur_face, 906 m_glyph_index, 907 m_hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING); 908 // m_hinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING); 909 if(m_last_error == 0) 910 { 911 switch(m_glyph_rendering) 912 { 913 case glyph_ren_native_mono: 914 m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_MONO); 915 if(m_last_error == 0) 916 { 917 decompose_ft_bitmap_mono(m_cur_face->glyph->bitmap, 918 m_cur_face->glyph->bitmap_left, 919 m_flip_y ? -m_cur_face->glyph->bitmap_top : 920 m_cur_face->glyph->bitmap_top, 921 m_flip_y, 922 m_scanline_bin, 923 m_scanlines_bin); 924 m_bounds.x1 = m_scanlines_bin.min_x(); 925 m_bounds.y1 = m_scanlines_bin.min_y(); 926 m_bounds.x2 = m_scanlines_bin.max_x() + 1; 927 m_bounds.y2 = m_scanlines_bin.max_y() + 1; 928 m_data_size = m_scanlines_bin.byte_size(); 929 m_data_type = glyph_data_mono; 930 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 931 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 932 return true; 933 } 934 break; 935 936 937 case glyph_ren_native_gray8: 938 m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_NORMAL); 939 if(m_last_error == 0) 940 { 941 decompose_ft_bitmap_gray8(m_cur_face->glyph->bitmap, 942 m_cur_face->glyph->bitmap_left, 943 m_flip_y ? -m_cur_face->glyph->bitmap_top : 944 m_cur_face->glyph->bitmap_top, 945 m_flip_y, 946 m_rasterizer, 947 m_scanline_aa, 948 m_scanlines_aa); 949 m_bounds.x1 = m_scanlines_aa.min_x(); 950 m_bounds.y1 = m_scanlines_aa.min_y(); 951 m_bounds.x2 = m_scanlines_aa.max_x() + 1; 952 m_bounds.y2 = m_scanlines_aa.max_y() + 1; 953 m_data_size = m_scanlines_aa.byte_size(); 954 m_data_type = glyph_data_gray8; 955 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 956 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 957 return true; 958 } 959 break; 960 961 962 case glyph_ren_outline: 963 if(m_last_error == 0) 964 { 965 if(m_flag32) 966 { 967 m_path32.remove_all(); 968 if(decompose_ft_outline(m_cur_face->glyph->outline, 969 m_flip_y, 970 m_affine, 971 m_path32)) 972 { 973 rect_d bnd = m_path32.bounding_rect(); 974 m_data_size = m_path32.byte_size(); 975 m_data_type = glyph_data_outline; 976 m_bounds.x1 = int(floor(bnd.x1)); 977 m_bounds.y1 = int(floor(bnd.y1)); 978 m_bounds.x2 = int(ceil(bnd.x2)); 979 m_bounds.y2 = int(ceil(bnd.y2)); 980 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 981 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 982 m_affine.transform(&m_advance_x, &m_advance_y); 983 return true; 984 } 985 } 986 else 987 { 988 m_path16.remove_all(); 989 if(decompose_ft_outline(m_cur_face->glyph->outline, 990 m_flip_y, 991 m_affine, 992 m_path16)) 993 { 994 rect_d bnd = m_path16.bounding_rect(); 995 m_data_size = m_path16.byte_size(); 996 m_data_type = glyph_data_outline; 997 m_bounds.x1 = int(floor(bnd.x1)); 998 m_bounds.y1 = int(floor(bnd.y1)); 999 m_bounds.x2 = int(ceil(bnd.x2)); 1000 m_bounds.y2 = int(ceil(bnd.y2)); 1001 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 1002 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 1003 m_affine.transform(&m_advance_x, &m_advance_y); 1004 return true; 1005 } 1006 } 1007 } 1008 return false; 1009 1010 case glyph_ren_agg_mono: 1011 if(m_last_error == 0) 1012 { 1013 m_rasterizer.reset(); 1014 if(m_flag32) 1015 { 1016 m_path32.remove_all(); 1017 decompose_ft_outline(m_cur_face->glyph->outline, 1018 m_flip_y, 1019 m_affine, 1020 m_path32); 1021 m_rasterizer.add_path(m_curves32); 1022 } 1023 else 1024 { 1025 m_path16.remove_all(); 1026 decompose_ft_outline(m_cur_face->glyph->outline, 1027 m_flip_y, 1028 m_affine, 1029 m_path16); 1030 m_rasterizer.add_path(m_curves16); 1031 } 1032 m_scanlines_bin.prepare(); // Remove all 1033 render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin); 1034 m_bounds.x1 = m_scanlines_bin.min_x(); 1035 m_bounds.y1 = m_scanlines_bin.min_y(); 1036 m_bounds.x2 = m_scanlines_bin.max_x() + 1; 1037 m_bounds.y2 = m_scanlines_bin.max_y() + 1; 1038 m_data_size = m_scanlines_bin.byte_size(); 1039 m_data_type = glyph_data_mono; 1040 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 1041 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 1042 m_affine.transform(&m_advance_x, &m_advance_y); 1043 return true; 1044 } 1045 return false; 1046 1047 1048 case glyph_ren_agg_gray8: 1049 if(m_last_error == 0) 1050 { 1051 m_rasterizer.reset(); 1052 if(m_flag32) 1053 { 1054 m_path32.remove_all(); 1055 decompose_ft_outline(m_cur_face->glyph->outline, 1056 m_flip_y, 1057 m_affine, 1058 m_path32); 1059 m_rasterizer.add_path(m_curves32); 1060 } 1061 else 1062 { 1063 m_path16.remove_all(); 1064 decompose_ft_outline(m_cur_face->glyph->outline, 1065 m_flip_y, 1066 m_affine, 1067 m_path16); 1068 m_rasterizer.add_path(m_curves16); 1069 } 1070 m_scanlines_aa.prepare(); // Remove all 1071 render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa); 1072 m_bounds.x1 = m_scanlines_aa.min_x(); 1073 m_bounds.y1 = m_scanlines_aa.min_y(); 1074 m_bounds.x2 = m_scanlines_aa.max_x() + 1; 1075 m_bounds.y2 = m_scanlines_aa.max_y() + 1; 1076 m_data_size = m_scanlines_aa.byte_size(); 1077 m_data_type = glyph_data_gray8; 1078 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 1079 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 1080 m_affine.transform(&m_advance_x, &m_advance_y); 1081 return true; 1082 } 1083 return false; 1084 } 1085 } 1086 return false; 1087 } 1088 1089 1090 1091 1092 //------------------------------------------------------------------------ write_glyph_to(int8u * data) const1093 void font_engine_freetype_base::write_glyph_to(int8u* data) const 1094 { 1095 if(data && m_data_size) 1096 { 1097 switch(m_data_type) 1098 { 1099 default: return; 1100 case glyph_data_mono: m_scanlines_bin.serialize(data); break; 1101 case glyph_data_gray8: m_scanlines_aa.serialize(data); break; 1102 case glyph_data_outline: 1103 if(m_flag32) 1104 { 1105 m_path32.serialize(data); 1106 } 1107 else 1108 { 1109 m_path16.serialize(data); 1110 } 1111 break; 1112 case glyph_data_invalid: break; 1113 } 1114 } 1115 } 1116 1117 1118 1119 //------------------------------------------------------------------------ add_kerning(unsigned first,unsigned second,double * x,double * y)1120 bool font_engine_freetype_base::add_kerning(unsigned first, unsigned second, 1121 double* x, double* y) 1122 { 1123 if(m_cur_face && first && second && FT_HAS_KERNING(m_cur_face)) 1124 { 1125 FT_Vector delta; 1126 FT_Get_Kerning(m_cur_face, first, second, 1127 FT_KERNING_DEFAULT, &delta); 1128 double dx = int26p6_to_dbl(delta.x); 1129 double dy = int26p6_to_dbl(delta.y); 1130 if(m_glyph_rendering == glyph_ren_outline || 1131 m_glyph_rendering == glyph_ren_agg_mono || 1132 m_glyph_rendering == glyph_ren_agg_gray8) 1133 { 1134 m_affine.transform_2x2(&dx, &dy); 1135 } 1136 *x += dx; 1137 *y += dy; 1138 1139 return true; 1140 } 1141 return false; 1142 } 1143 1144 1145 1146 } 1147 1148 1149