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 23namespace 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 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 //------------------------------------------------------------------------ 126 static inline int dbl_to_plain_fx(double d) 127 { 128 return int(d * 65536.0); 129 } 130 131 //------------------------------------------------------------------------ 132 static inline double int26p6_to_dbl(int p) 133 { 134 return double(p) / 64.0; 135 } 136 137 //------------------------------------------------------------------------ 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> 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> 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> 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 //------------------------------------------------------------------------ 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 //------------------------------------------------------------------------ 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 //------------------------------------------------------------------------ 562 void font_engine_freetype_base::resolution(unsigned dpi) 563 { 564 m_resolution = dpi; 565 update_char_size(); 566 } 567 568 569 //------------------------------------------------------------------------ 570 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 //------------------------------------------------------------------------ 582 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 //------------------------------------------------------------------------ 592 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 //------------------------------------------------------------------------ 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 //------------------------------------------------------------------------ 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 //------------------------------------------------------------------------ 735 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 //------------------------------------------------------------------------ 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, m_char_map); 750 if(m_last_error == 0) 751 { 752 update_signature(); 753 return true; 754 } 755 } 756 return false; 757 } 758 759 //------------------------------------------------------------------------ 760 bool font_engine_freetype_base::height(double h) 761 { 762 m_height = int(h * 64.0); 763 if(m_cur_face) 764 { 765 update_char_size(); 766 return true; 767 } 768 return false; 769 } 770 771 //------------------------------------------------------------------------ 772 bool font_engine_freetype_base::width(double w) 773 { 774 m_width = int(w * 64.0); 775 if(m_cur_face) 776 { 777 update_char_size(); 778 return true; 779 } 780 return false; 781 } 782 783 //------------------------------------------------------------------------ 784 void font_engine_freetype_base::hinting(bool h) 785 { 786 m_hinting = h; 787 if(m_cur_face) 788 { 789 update_signature(); 790 } 791 } 792 793 //------------------------------------------------------------------------ 794 void font_engine_freetype_base::flip_y(bool f) 795 { 796 m_flip_y = f; 797 if(m_cur_face) 798 { 799 update_signature(); 800 } 801 } 802 803 //------------------------------------------------------------------------ 804 void font_engine_freetype_base::transform(const trans_affine& affine) 805 { 806 m_affine = affine; 807 if(m_cur_face) 808 { 809 update_signature(); 810 } 811 } 812 813 //------------------------------------------------------------------------ 814 void font_engine_freetype_base::update_signature() 815 { 816 if(m_cur_face && m_name) 817 { 818 unsigned name_len = strlen(m_name); 819 if(name_len > m_name_len) 820 { 821 delete [] m_signature; 822 m_signature = new char [name_len + 32 + 256]; 823 m_name_len = name_len + 32 - 1; 824 } 825 826 unsigned gamma_hash = 0; 827 if(m_glyph_rendering == glyph_ren_native_gray8 || 828 m_glyph_rendering == glyph_ren_agg_mono || 829 m_glyph_rendering == glyph_ren_agg_gray8) 830 { 831 unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale]; 832 unsigned i; 833 for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i) 834 { 835 gamma_table[i] = m_rasterizer.apply_gamma(i); 836 } 837 gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table)); 838 } 839 840 sprintf(m_signature, 841 "%s,%u,%d,%d,%d:%dx%d,%d,%d,%08X", 842 m_name, 843 m_char_map, 844 m_face_index, 845 int(m_glyph_rendering), 846 m_resolution, 847 m_height, 848 m_width, 849 int(m_hinting), 850 int(m_flip_y), 851 gamma_hash); 852 if(m_glyph_rendering == glyph_ren_outline || 853 m_glyph_rendering == glyph_ren_agg_mono || 854 m_glyph_rendering == glyph_ren_agg_gray8) 855 { 856 double mtx[6]; 857 char buf[100]; 858 m_affine.store_to(mtx); 859 sprintf(buf, ",%08X%08X%08X%08X%08X%08X", 860 dbl_to_plain_fx(mtx[0]), 861 dbl_to_plain_fx(mtx[1]), 862 dbl_to_plain_fx(mtx[2]), 863 dbl_to_plain_fx(mtx[3]), 864 dbl_to_plain_fx(mtx[4]), 865 dbl_to_plain_fx(mtx[5])); 866 strcat(m_signature, buf); 867 } 868 ++m_change_stamp; 869 } 870 } 871 872 873 //------------------------------------------------------------------------ 874 void font_engine_freetype_base::update_char_size() 875 { 876 if(m_cur_face) 877 { 878 if(m_resolution) 879 { 880 FT_Set_Char_Size(m_cur_face, 881 m_width, // char_width in 1/64th of points 882 m_height, // char_height in 1/64th of points 883 m_resolution, // horizontal device resolution 884 m_resolution); // vertical device resolution 885 } 886 else 887 { 888 FT_Set_Pixel_Sizes(m_cur_face, 889 m_width >> 6, // pixel_width 890 m_height >> 6); // pixel_height 891 } 892 update_signature(); 893 } 894 } 895 896 897 898 899 900 //------------------------------------------------------------------------ 901 bool font_engine_freetype_base::prepare_glyph(unsigned glyph_code) 902 { 903 m_glyph_index = FT_Get_Char_Index(m_cur_face, glyph_code); 904 m_last_error = FT_Load_Glyph(m_cur_face, 905 m_glyph_index, 906 m_hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING); 907// m_hinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING); 908 if(m_last_error == 0) 909 { 910 switch(m_glyph_rendering) 911 { 912 case glyph_ren_native_mono: 913 m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_MONO); 914 if(m_last_error == 0) 915 { 916 decompose_ft_bitmap_mono(m_cur_face->glyph->bitmap, 917 m_cur_face->glyph->bitmap_left, 918 m_flip_y ? -m_cur_face->glyph->bitmap_top : 919 m_cur_face->glyph->bitmap_top, 920 m_flip_y, 921 m_scanline_bin, 922 m_scanlines_bin); 923 m_bounds.x1 = m_scanlines_bin.min_x(); 924 m_bounds.y1 = m_scanlines_bin.min_y(); 925 m_bounds.x2 = m_scanlines_bin.max_x() + 1; 926 m_bounds.y2 = m_scanlines_bin.max_y() + 1; 927 m_data_size = m_scanlines_bin.byte_size(); 928 m_data_type = glyph_data_mono; 929 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 930 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 931 return true; 932 } 933 break; 934 935 936 case glyph_ren_native_gray8: 937 m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_NORMAL); 938 if(m_last_error == 0) 939 { 940 decompose_ft_bitmap_gray8(m_cur_face->glyph->bitmap, 941 m_cur_face->glyph->bitmap_left, 942 m_flip_y ? -m_cur_face->glyph->bitmap_top : 943 m_cur_face->glyph->bitmap_top, 944 m_flip_y, 945 m_rasterizer, 946 m_scanline_aa, 947 m_scanlines_aa); 948 m_bounds.x1 = m_scanlines_aa.min_x(); 949 m_bounds.y1 = m_scanlines_aa.min_y(); 950 m_bounds.x2 = m_scanlines_aa.max_x() + 1; 951 m_bounds.y2 = m_scanlines_aa.max_y() + 1; 952 m_data_size = m_scanlines_aa.byte_size(); 953 m_data_type = glyph_data_gray8; 954 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 955 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 956 return true; 957 } 958 break; 959 960 961 case glyph_ren_outline: 962 if(m_last_error == 0) 963 { 964 if(m_flag32) 965 { 966 m_path32.remove_all(); 967 if(decompose_ft_outline(m_cur_face->glyph->outline, 968 m_flip_y, 969 m_affine, 970 m_path32)) 971 { 972 rect_d bnd = m_path32.bounding_rect(); 973 m_data_size = m_path32.byte_size(); 974 m_data_type = glyph_data_outline; 975 m_bounds.x1 = int(floor(bnd.x1)); 976 m_bounds.y1 = int(floor(bnd.y1)); 977 m_bounds.x2 = int(ceil(bnd.x2)); 978 m_bounds.y2 = int(ceil(bnd.y2)); 979 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 980 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 981 m_affine.transform(&m_advance_x, &m_advance_y); 982 return true; 983 } 984 } 985 else 986 { 987 m_path16.remove_all(); 988 if(decompose_ft_outline(m_cur_face->glyph->outline, 989 m_flip_y, 990 m_affine, 991 m_path16)) 992 { 993 rect_d bnd = m_path16.bounding_rect(); 994 m_data_size = m_path16.byte_size(); 995 m_data_type = glyph_data_outline; 996 m_bounds.x1 = int(floor(bnd.x1)); 997 m_bounds.y1 = int(floor(bnd.y1)); 998 m_bounds.x2 = int(ceil(bnd.x2)); 999 m_bounds.y2 = int(ceil(bnd.y2)); 1000 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 1001 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 1002 m_affine.transform(&m_advance_x, &m_advance_y); 1003 return true; 1004 } 1005 } 1006 } 1007 return false; 1008 1009 case glyph_ren_agg_mono: 1010 if(m_last_error == 0) 1011 { 1012 m_rasterizer.reset(); 1013 if(m_flag32) 1014 { 1015 m_path32.remove_all(); 1016 decompose_ft_outline(m_cur_face->glyph->outline, 1017 m_flip_y, 1018 m_affine, 1019 m_path32); 1020 m_rasterizer.add_path(m_curves32); 1021 } 1022 else 1023 { 1024 m_path16.remove_all(); 1025 decompose_ft_outline(m_cur_face->glyph->outline, 1026 m_flip_y, 1027 m_affine, 1028 m_path16); 1029 m_rasterizer.add_path(m_curves16); 1030 } 1031 m_scanlines_bin.prepare(); // Remove all 1032 render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin); 1033 m_bounds.x1 = m_scanlines_bin.min_x(); 1034 m_bounds.y1 = m_scanlines_bin.min_y(); 1035 m_bounds.x2 = m_scanlines_bin.max_x() + 1; 1036 m_bounds.y2 = m_scanlines_bin.max_y() + 1; 1037 m_data_size = m_scanlines_bin.byte_size(); 1038 m_data_type = glyph_data_mono; 1039 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 1040 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 1041 m_affine.transform(&m_advance_x, &m_advance_y); 1042 return true; 1043 } 1044 return false; 1045 1046 1047 case glyph_ren_agg_gray8: 1048 if(m_last_error == 0) 1049 { 1050 m_rasterizer.reset(); 1051 if(m_flag32) 1052 { 1053 m_path32.remove_all(); 1054 decompose_ft_outline(m_cur_face->glyph->outline, 1055 m_flip_y, 1056 m_affine, 1057 m_path32); 1058 m_rasterizer.add_path(m_curves32); 1059 } 1060 else 1061 { 1062 m_path16.remove_all(); 1063 decompose_ft_outline(m_cur_face->glyph->outline, 1064 m_flip_y, 1065 m_affine, 1066 m_path16); 1067 m_rasterizer.add_path(m_curves16); 1068 } 1069 m_scanlines_aa.prepare(); // Remove all 1070 render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa); 1071 m_bounds.x1 = m_scanlines_aa.min_x(); 1072 m_bounds.y1 = m_scanlines_aa.min_y(); 1073 m_bounds.x2 = m_scanlines_aa.max_x() + 1; 1074 m_bounds.y2 = m_scanlines_aa.max_y() + 1; 1075 m_data_size = m_scanlines_aa.byte_size(); 1076 m_data_type = glyph_data_gray8; 1077 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); 1078 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); 1079 m_affine.transform(&m_advance_x, &m_advance_y); 1080 return true; 1081 } 1082 return false; 1083 } 1084 } 1085 return false; 1086 } 1087 1088 1089 1090 1091 //------------------------------------------------------------------------ 1092 void font_engine_freetype_base::write_glyph_to(int8u* data) const 1093 { 1094 if(data && m_data_size) 1095 { 1096 switch(m_data_type) 1097 { 1098 default: return; 1099 case glyph_data_mono: m_scanlines_bin.serialize(data); break; 1100 case glyph_data_gray8: m_scanlines_aa.serialize(data); break; 1101 case glyph_data_outline: 1102 if(m_flag32) 1103 { 1104 m_path32.serialize(data); 1105 } 1106 else 1107 { 1108 m_path16.serialize(data); 1109 } 1110 break; 1111 case glyph_data_invalid: break; 1112 } 1113 } 1114 } 1115 1116 1117 1118 //------------------------------------------------------------------------ 1119 bool font_engine_freetype_base::add_kerning(unsigned first, unsigned second, 1120 double* x, double* y) 1121 { 1122 if(m_cur_face && first && second && FT_HAS_KERNING(m_cur_face)) 1123 { 1124 FT_Vector delta; 1125 FT_Get_Kerning(m_cur_face, first, second, 1126 FT_KERNING_DEFAULT, &delta); 1127 double dx = int26p6_to_dbl(delta.x); 1128 double dy = int26p6_to_dbl(delta.y); 1129 if(m_glyph_rendering == glyph_ren_outline || 1130 m_glyph_rendering == glyph_ren_agg_mono || 1131 m_glyph_rendering == glyph_ren_agg_gray8) 1132 { 1133 m_affine.transform_2x2(&dx, &dy); 1134 } 1135 *x += dx; 1136 *y += dy; 1137 1138 return true; 1139 } 1140 return false; 1141 } 1142 1143 1144 1145} 1146 1147 1148