1 /* 2 * Copyright 2007, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Maxim Shemanarev <mcseemagg@yahoo.com> 7 * Stephan Aßmus <superstippi@gmx.de> 8 * Anthony Lee <don.anthony.lee@gmail.com> 9 * Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk> 10 */ 11 12 //---------------------------------------------------------------------------- 13 // Anti-Grain Geometry - Version 2.4 14 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 15 // 16 // Permission to copy, use, modify, sell and distribute this software 17 // is granted provided this copyright notice appears in all copies. 18 // This software is provided "as is" without express or implied 19 // warranty, and with no claim as to its suitability for any purpose. 20 // 21 //---------------------------------------------------------------------------- 22 // Contact: mcseem@antigrain.com 23 // mcseemagg@yahoo.com 24 // http://www.antigrain.com 25 //---------------------------------------------------------------------------- 26 27 28 #include "FontEngine.h" 29 30 #include FT_GLYPH_H 31 #include FT_OUTLINE_H 32 #include FT_LCD_FILTER_H 33 34 #include <stdio.h> 35 36 #include <agg_bitset_iterator.h> 37 #include <agg_renderer_scanline.h> 38 39 #include "GlobalSubpixelSettings.h" 40 41 42 static const bool kFlipY = true; 43 44 45 static inline double 46 int26p6_to_dbl(int p) 47 { 48 return double(p) / 64.0; 49 } 50 51 52 static inline int 53 dbl_to_int26p6(double p) 54 { 55 return int(p * 64.0 + 0.5); 56 } 57 58 59 template<class PathStorage> 60 bool 61 decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path) 62 { 63 typedef typename PathStorage::value_type value_type; 64 65 FT_Vector v_last; 66 FT_Vector v_control; 67 FT_Vector v_start; 68 double x1, y1, x2, y2, x3, y3; 69 70 FT_Vector* point; 71 FT_Vector* limit; 72 char* tags; 73 74 int n; // index of contour in outline 75 int first; // index of first point in contour 76 char tag; // current point's state 77 78 first = 0; 79 80 for (n = 0; n < outline.n_contours; n++) { 81 int last; // index of last point in contour 82 83 last = outline.contours[n]; 84 limit = outline.points + last; 85 86 v_start = outline.points[first]; 87 v_last = outline.points[last]; 88 89 v_control = v_start; 90 91 point = outline.points + first; 92 tags = outline.tags + first; 93 tag = FT_CURVE_TAG(tags[0]); 94 95 // A contour cannot start with a cubic control point! 96 if (tag == FT_CURVE_TAG_CUBIC) 97 return false; 98 99 // check first point to determine origin 100 if ( tag == FT_CURVE_TAG_CONIC) { 101 // first point is conic control. Yes, this happens. 102 if (FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) { 103 // start at last point if it is on the curve 104 v_start = v_last; 105 limit--; 106 } else { 107 // if both first and last points are conic, 108 // start at their middle and record its position 109 // for closure 110 v_start.x = (v_start.x + v_last.x) / 2; 111 v_start.y = (v_start.y + v_last.y) / 2; 112 113 v_last = v_start; 114 } 115 point--; 116 tags--; 117 } 118 119 x1 = int26p6_to_dbl(v_start.x); 120 y1 = int26p6_to_dbl(v_start.y); 121 if (flip_y) y1 = -y1; 122 path.move_to(value_type(dbl_to_int26p6(x1)), 123 value_type(dbl_to_int26p6(y1))); 124 125 while(point < limit) { 126 point++; 127 tags++; 128 129 tag = FT_CURVE_TAG(tags[0]); 130 switch(tag) { 131 case FT_CURVE_TAG_ON: { // emit a single line_to 132 x1 = int26p6_to_dbl(point->x); 133 y1 = int26p6_to_dbl(point->y); 134 if (flip_y) y1 = -y1; 135 path.line_to(value_type(dbl_to_int26p6(x1)), 136 value_type(dbl_to_int26p6(y1))); 137 //path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y)); 138 continue; 139 } 140 141 case FT_CURVE_TAG_CONIC: { // consume conic arcs 142 v_control.x = point->x; 143 v_control.y = point->y; 144 145 Do_Conic: 146 if (point < limit) { 147 FT_Vector vec; 148 FT_Vector v_middle; 149 150 point++; 151 tags++; 152 tag = FT_CURVE_TAG(tags[0]); 153 154 vec.x = point->x; 155 vec.y = point->y; 156 157 if (tag == FT_CURVE_TAG_ON) { 158 x1 = int26p6_to_dbl(v_control.x); 159 y1 = int26p6_to_dbl(v_control.y); 160 x2 = int26p6_to_dbl(vec.x); 161 y2 = int26p6_to_dbl(vec.y); 162 if (flip_y) { y1 = -y1; y2 = -y2; } 163 path.curve3(value_type(dbl_to_int26p6(x1)), 164 value_type(dbl_to_int26p6(y1)), 165 value_type(dbl_to_int26p6(x2)), 166 value_type(dbl_to_int26p6(y2))); 167 continue; 168 } 169 170 if (tag != FT_CURVE_TAG_CONIC) 171 return false; 172 173 v_middle.x = (v_control.x + vec.x) / 2; 174 v_middle.y = (v_control.y + vec.y) / 2; 175 176 x1 = int26p6_to_dbl(v_control.x); 177 y1 = int26p6_to_dbl(v_control.y); 178 x2 = int26p6_to_dbl(v_middle.x); 179 y2 = int26p6_to_dbl(v_middle.y); 180 if (flip_y) { y1 = -y1; y2 = -y2; } 181 path.curve3(value_type(dbl_to_int26p6(x1)), 182 value_type(dbl_to_int26p6(y1)), 183 value_type(dbl_to_int26p6(x2)), 184 value_type(dbl_to_int26p6(y2))); 185 186 //path.curve3(conv(v_control.x), 187 // flip_y ? -conv(v_control.y) : conv(v_control.y), 188 // conv(v_middle.x), 189 // flip_y ? -conv(v_middle.y) : conv(v_middle.y)); 190 191 v_control = vec; 192 goto Do_Conic; 193 } 194 195 x1 = int26p6_to_dbl(v_control.x); 196 y1 = int26p6_to_dbl(v_control.y); 197 x2 = int26p6_to_dbl(v_start.x); 198 y2 = int26p6_to_dbl(v_start.y); 199 if (flip_y) { y1 = -y1; y2 = -y2; } 200 path.curve3(value_type(dbl_to_int26p6(x1)), 201 value_type(dbl_to_int26p6(y1)), 202 value_type(dbl_to_int26p6(x2)), 203 value_type(dbl_to_int26p6(y2))); 204 205 //path.curve3(conv(v_control.x), 206 // flip_y ? -conv(v_control.y) : conv(v_control.y), 207 // conv(v_start.x), 208 // flip_y ? -conv(v_start.y) : conv(v_start.y)); 209 goto Close; 210 } 211 212 default: { // FT_CURVE_TAG_CUBIC 213 FT_Vector vec1, vec2; 214 215 if (point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC) 216 return false; 217 218 vec1.x = point[0].x; 219 vec1.y = point[0].y; 220 vec2.x = point[1].x; 221 vec2.y = point[1].y; 222 223 point += 2; 224 tags += 2; 225 226 if (point <= limit) { 227 FT_Vector vec; 228 229 vec.x = point->x; 230 vec.y = point->y; 231 232 x1 = int26p6_to_dbl(vec1.x); 233 y1 = int26p6_to_dbl(vec1.y); 234 x2 = int26p6_to_dbl(vec2.x); 235 y2 = int26p6_to_dbl(vec2.y); 236 x3 = int26p6_to_dbl(vec.x); 237 y3 = int26p6_to_dbl(vec.y); 238 if (flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } 239 path.curve4(value_type(dbl_to_int26p6(x1)), 240 value_type(dbl_to_int26p6(y1)), 241 value_type(dbl_to_int26p6(x2)), 242 value_type(dbl_to_int26p6(y2)), 243 value_type(dbl_to_int26p6(x3)), 244 value_type(dbl_to_int26p6(y3))); 245 246 //path.curve4(conv(vec1.x), 247 // flip_y ? -conv(vec1.y) : conv(vec1.y), 248 // conv(vec2.x), 249 // flip_y ? -conv(vec2.y) : conv(vec2.y), 250 // conv(vec.x), 251 // flip_y ? -conv(vec.y) : conv(vec.y)); 252 continue; 253 } 254 255 x1 = int26p6_to_dbl(vec1.x); 256 y1 = int26p6_to_dbl(vec1.y); 257 x2 = int26p6_to_dbl(vec2.x); 258 y2 = int26p6_to_dbl(vec2.y); 259 x3 = int26p6_to_dbl(v_start.x); 260 y3 = int26p6_to_dbl(v_start.y); 261 if (flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } 262 path.curve4(value_type(dbl_to_int26p6(x1)), 263 value_type(dbl_to_int26p6(y1)), 264 value_type(dbl_to_int26p6(x2)), 265 value_type(dbl_to_int26p6(y2)), 266 value_type(dbl_to_int26p6(x3)), 267 value_type(dbl_to_int26p6(y3))); 268 269 //path.curve4(conv(vec1.x), 270 // flip_y ? -conv(vec1.y) : conv(vec1.y), 271 // conv(vec2.x), 272 // flip_y ? -conv(vec2.y) : conv(vec2.y), 273 // conv(v_start.x), 274 // flip_y ? -conv(v_start.y) : conv(v_start.y)); 275 goto Close; 276 } 277 } 278 } 279 280 path.close_polygon(); 281 282 Close: 283 first = last + 1; 284 } 285 286 return true; 287 } 288 289 290 template<class Scanline, class ScanlineStorage> 291 void 292 decompose_ft_bitmap_mono(const FT_Bitmap& bitmap, int x, int y, 293 bool flip_y, Scanline& sl, ScanlineStorage& storage) 294 { 295 const uint8* buf = (const uint8*)bitmap.buffer; 296 int pitch = bitmap.pitch; 297 sl.reset(x, x + bitmap.width); 298 storage.prepare(); 299 if (flip_y) { 300 buf += bitmap.pitch * (bitmap.rows - 1); 301 y += bitmap.rows; 302 pitch = -pitch; 303 } 304 for (unsigned int i = 0; i < bitmap.rows; i++) { 305 sl.reset_spans(); 306 agg::bitset_iterator bits(buf, 0); 307 for (unsigned int j = 0; j < bitmap.width; j++) { 308 if (bits.bit()) 309 sl.add_cell(x + j, agg::cover_full); 310 ++bits; 311 } 312 buf += pitch; 313 if (sl.num_spans()) { 314 sl.finalize(y - i - 1); 315 storage.render(sl); 316 } 317 } 318 } 319 320 321 template<class Scanline, class ScanlineStorage> 322 void 323 decompose_ft_bitmap_gray8(const FT_Bitmap& bitmap, int x, int y, 324 bool flip_y, Scanline& sl, ScanlineStorage& storage) 325 { 326 const uint8* buf = (const uint8*)bitmap.buffer; 327 int pitch = bitmap.pitch; 328 sl.reset(x, x + bitmap.width); 329 storage.prepare(); 330 if (flip_y) { 331 buf += bitmap.pitch * (bitmap.rows - 1); 332 y += bitmap.rows; 333 pitch = -pitch; 334 } 335 for (unsigned int i = 0; i < bitmap.rows; i++) { 336 sl.reset_spans(); 337 338 if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { 339 // font has built-in mono bitmap 340 agg::bitset_iterator bits(buf, 0); 341 for (unsigned int j = 0; j < bitmap.width; j++) { 342 if (bits.bit()) 343 sl.add_cell(x + j, agg::cover_full); 344 ++bits; 345 } 346 } else { 347 const uint8* p = buf; 348 for (unsigned int j = 0; j < bitmap.width; j++) { 349 if (*p) 350 sl.add_cell(x + j, *p); 351 ++p; 352 } 353 } 354 355 buf += pitch; 356 if (sl.num_spans()) { 357 sl.finalize(y - i - 1); 358 storage.render(sl); 359 } 360 } 361 } 362 363 364 template<class Scanline, class ScanlineStorage> 365 void 366 decompose_ft_bitmap_subpix(const FT_Bitmap& bitmap, int x, int y, 367 bool flip_y, Scanline& sl, ScanlineStorage& storage) 368 { 369 const uint8* buf = (const uint8*)bitmap.buffer; 370 int pitch = bitmap.pitch; 371 if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) 372 sl.reset(x, x + bitmap.width); 373 else 374 sl.reset(x, x + bitmap.width / 3); 375 storage.prepare(); 376 377 if (flip_y) { 378 buf += bitmap.pitch * (bitmap.rows - 1); 379 y += bitmap.rows; 380 pitch = -pitch; 381 } 382 383 for (unsigned int i = 0; i < bitmap.rows; i++) { 384 sl.reset_spans(); 385 386 if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { 387 // font has built-in mono bitmap 388 agg::bitset_iterator bits(buf, 0); 389 for (unsigned int j = 0; j < bitmap.width; j++) { 390 if (bits.bit()) { 391 sl.add_cell(x + j, 392 agg::cover_full, agg::cover_full, agg::cover_full); 393 } 394 ++bits; 395 } 396 } else { 397 const uint8* p = buf; 398 int w = bitmap.width / 3; 399 400 for (int j = 0; j < w; j++) { 401 if (p[0] || p[1] || p[2]) 402 sl.add_cell(x + j, p[0], p[1], p[2]); 403 p += 3; 404 } 405 } 406 407 buf += pitch; 408 if (sl.num_spans()) { 409 sl.finalize(y - i - 1); 410 storage.render(sl); 411 } 412 } 413 } 414 415 416 // #pragma mark - 417 418 419 FontEngine::FontEngine() 420 : 421 fLastError(0), 422 fLibraryInitialized(false), 423 fLibrary(0), 424 fFace(NULL), 425 426 fGlyphRendering(glyph_ren_native_gray8), 427 fHinting(true), 428 429 fDataSize(0), 430 fDataType(glyph_data_invalid), 431 fBounds(1, 1, 0, 0), 432 fAdvanceX(0.0), 433 fAdvanceY(0.0), 434 fInsetLeft(0.0), 435 fInsetRight(0.0), 436 437 fPath(), 438 fCurves(fPath), 439 fScanlineAA(), 440 fScanlineBin(), 441 fScanlineSubpix(), 442 fScanlineStorageAA(), 443 fScanlineStorageBin(), 444 fScanlineStorageSubpix() 445 { 446 fCurves.approximation_scale(4.0); 447 448 fLastError = FT_Init_FreeType(&fLibrary); 449 if (fLastError == 0) 450 fLibraryInitialized = true; 451 } 452 453 454 FontEngine::~FontEngine() 455 { 456 FT_Done_Face(fFace); 457 458 if (fLibraryInitialized) 459 FT_Done_FreeType(fLibrary); 460 } 461 462 463 unsigned 464 FontEngine::CountFaces() const 465 { 466 if (fFace) 467 return fFace->num_faces; 468 469 return 0; 470 } 471 472 473 uint32 474 FontEngine::GlyphIndexForGlyphCode(uint32 glyphCode) const 475 { 476 return FT_Get_Char_Index(fFace, glyphCode); 477 } 478 479 480 bool 481 FontEngine::PrepareGlyph(uint32 glyphIndex) 482 { 483 FT_Int32 loadFlags = fHinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING; 484 loadFlags |= fGlyphRendering == glyph_ren_subpix ? 485 FT_LOAD_TARGET_LCD : FT_LOAD_TARGET_NORMAL; 486 487 // Load unscaled and without hinting to get precise advance values 488 // for B_CHAR_SPACING 489 fLastError = FT_Load_Glyph(fFace, glyphIndex, loadFlags 490 | FT_LOAD_NO_HINTING | FT_LOAD_NO_SCALE); 491 492 FT_UShort units_per_EM = fFace->units_per_EM; 493 if (!FT_IS_SCALABLE(fFace)) 494 units_per_EM = 1; 495 fPreciseAdvanceX = (double)fFace->glyph->advance.x / units_per_EM; 496 fPreciseAdvanceY = (double)fFace->glyph->advance.y / units_per_EM; 497 498 // Need to load again with hinting. 499 fLastError = FT_Load_Glyph(fFace, glyphIndex, loadFlags); 500 501 if (fLastError != 0) 502 return false; 503 504 fAdvanceX = int26p6_to_dbl(fFace->glyph->advance.x); 505 fAdvanceY = int26p6_to_dbl(fFace->glyph->advance.y); 506 507 fInsetLeft = int26p6_to_dbl(fFace->glyph->metrics.horiBearingX); 508 fInsetRight = int26p6_to_dbl(fFace->glyph->metrics.horiBearingX 509 + fFace->glyph->metrics.width - fFace->glyph->metrics.horiAdvance); 510 511 switch(fGlyphRendering) { 512 case glyph_ren_native_mono: 513 fLastError = FT_Render_Glyph(fFace->glyph, FT_RENDER_MODE_MONO); 514 if (fLastError == 0) { 515 decompose_ft_bitmap_mono(fFace->glyph->bitmap, 516 fFace->glyph->bitmap_left, kFlipY ? 517 -fFace->glyph->bitmap_top : fFace->glyph->bitmap_top, 518 kFlipY, fScanlineBin, fScanlineStorageBin); 519 fBounds.x1 = fScanlineStorageBin.min_x(); 520 fBounds.y1 = fScanlineStorageBin.min_y(); 521 fBounds.x2 = fScanlineStorageBin.max_x(); 522 fBounds.y2 = fScanlineStorageBin.max_y(); 523 fDataSize = fScanlineStorageBin.byte_size(); 524 fDataType = glyph_data_mono; 525 return true; 526 } 527 break; 528 529 530 case glyph_ren_native_gray8: 531 fLastError = FT_Render_Glyph(fFace->glyph, FT_RENDER_MODE_NORMAL); 532 if (fLastError == 0) { 533 decompose_ft_bitmap_gray8(fFace->glyph->bitmap, 534 fFace->glyph->bitmap_left, kFlipY ? 535 -fFace->glyph->bitmap_top : fFace->glyph->bitmap_top, 536 kFlipY, fScanlineAA, fScanlineStorageAA); 537 fBounds.x1 = fScanlineStorageAA.min_x(); 538 fBounds.y1 = fScanlineStorageAA.min_y(); 539 fBounds.x2 = fScanlineStorageAA.max_x(); 540 fBounds.y2 = fScanlineStorageAA.max_y(); 541 fDataSize = fScanlineStorageAA.byte_size(); 542 fDataType = glyph_data_gray8; 543 return true; 544 } 545 break; 546 547 548 case glyph_ren_subpix: 549 fLastError = FT_Render_Glyph(fFace->glyph, FT_RENDER_MODE_LCD); 550 if (fLastError == 0) { 551 decompose_ft_bitmap_subpix(fFace->glyph->bitmap, 552 fFace->glyph->bitmap_left, kFlipY ? 553 -fFace->glyph->bitmap_top : fFace->glyph->bitmap_top, 554 kFlipY, fScanlineSubpix, fScanlineStorageSubpix); 555 fBounds.x1 = fScanlineStorageSubpix.min_x(); 556 fBounds.y1 = fScanlineStorageSubpix.min_y(); 557 fBounds.x2 = fScanlineStorageSubpix.max_x(); 558 fBounds.y2 = fScanlineStorageSubpix.max_y(); 559 fDataSize = fScanlineStorageSubpix.byte_size(); 560 fDataType = glyph_data_subpix; 561 return true; 562 } 563 break; 564 565 566 case glyph_ren_outline: 567 fPath.remove_all(); 568 if (decompose_ft_outline(fFace->glyph->outline, kFlipY, fPath)) { 569 agg::rect_d bounds = fPath.bounding_rect(); 570 fBounds.x1 = int(floor(bounds.x1)); 571 fBounds.y1 = int(floor(bounds.y1)); 572 fBounds.x2 = int(ceil(bounds.x2)); 573 fBounds.y2 = int(ceil(bounds.y2)); 574 fDataSize = fPath.byte_size(); 575 fDataType = glyph_data_outline; 576 return true; 577 } 578 break; 579 } 580 return false; 581 } 582 583 // #pragma mark - 584 585 // WriteGlyphTo 586 void 587 FontEngine::WriteGlyphTo(uint8* data) const 588 { 589 if (data && fDataSize) { 590 switch(fDataType) { 591 case glyph_data_mono: 592 fScanlineStorageBin.serialize(data); 593 break; 594 595 case glyph_data_gray8: 596 fScanlineStorageAA.serialize(data); 597 break; 598 599 case glyph_data_subpix: 600 fScanlineStorageSubpix.serialize(data); 601 break; 602 603 case glyph_data_outline: 604 fPath.serialize(data); 605 break; 606 607 case glyph_data_invalid: 608 default: 609 break; 610 } 611 } 612 } 613 614 615 // GetKerning 616 bool 617 FontEngine::GetKerning(uint32 first, uint32 second, double* x, double* y) 618 { 619 if (fFace && first && second && FT_HAS_KERNING(fFace)) { 620 FT_Vector delta; 621 FT_Get_Kerning(fFace, first, second, FT_KERNING_DEFAULT, &delta); 622 623 double dx = int26p6_to_dbl(delta.x); 624 double dy = int26p6_to_dbl(delta.y); 625 626 *x += dx; 627 *y += dy; 628 629 return true; 630 } 631 return false; 632 } 633 634 635 // #pragma mark - 636 637 638 bool 639 FontEngine::Init(const char* fontFilePath, unsigned faceIndex, double size, 640 FT_Encoding charMap, glyph_rendering ren_type, bool hinting, 641 const void* fontFileBuffer, const long fontFileBufferSize) 642 { 643 if (!fLibraryInitialized) 644 return false; 645 646 fHinting = hinting; 647 648 fLastError = 0; 649 650 FT_Done_Face(fFace); 651 if (fontFileBuffer && fontFileBufferSize) { 652 fLastError = FT_New_Memory_Face(fLibrary, 653 (const FT_Byte*)fontFileBuffer, fontFileBufferSize, 654 faceIndex, &fFace); 655 } else { 656 fLastError = FT_New_Face(fLibrary, fontFilePath, faceIndex, &fFace); 657 } 658 659 if (fLastError != 0) 660 return false; 661 662 switch(ren_type) { 663 case glyph_ren_native_mono: 664 fGlyphRendering = glyph_ren_native_mono; 665 break; 666 667 case glyph_ren_native_gray8: 668 fGlyphRendering = glyph_ren_native_gray8; 669 break; 670 671 case glyph_ren_subpix: 672 fGlyphRendering = glyph_ren_subpix; 673 break; 674 675 case glyph_ren_outline: 676 if (FT_IS_SCALABLE(fFace)) 677 fGlyphRendering = glyph_ren_outline; 678 else 679 fGlyphRendering = glyph_ren_native_gray8; 680 break; 681 } 682 683 FT_Set_Pixel_Sizes(fFace, 684 unsigned(size * 64.0) >> 6, // pixel_width 685 unsigned(size * 64.0) >> 6); // pixel_height 686 687 if (charMap != FT_ENCODING_NONE) { 688 fLastError = FT_Select_Charmap(fFace, charMap); 689 } else { 690 if (FT_Select_Charmap(fFace, FT_ENCODING_UNICODE) != 0) 691 fLastError = FT_Select_Charmap(fFace, FT_ENCODING_NONE); 692 } 693 694 return fLastError == 0; 695 } 696 697