Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Side by Side Diff: src/ports/SkFontHost_FreeType.cpp

Issue 2162023002: Correct advances for 'monospace' fonts in PDF. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: CG and GDI as well. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/ports/SkFontHost_mac.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkAdvancedTypefaceMetrics.h" 8 #include "SkAdvancedTypefaceMetrics.h"
9 #include "SkBitmap.h" 9 #include "SkBitmap.h"
10 #include "SkCanvas.h" 10 #include "SkCanvas.h"
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag); 472 SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
473 } 473 }
474 if (!canSubset(face)) { 474 if (!canSubset(face)) {
475 info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>( 475 info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
476 info->fFlags, 476 info->fFlags,
477 SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag); 477 SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag);
478 } 478 }
479 info->fLastGlyphID = face->num_glyphs - 1; 479 info->fLastGlyphID = face->num_glyphs - 1;
480 info->fEmSize = 1000; 480 info->fEmSize = 1000;
481 481
482 bool cid = false;
483 const char* fontType = FT_Get_X11_Font_Format(face); 482 const char* fontType = FT_Get_X11_Font_Format(face);
484 if (strcmp(fontType, "Type 1") == 0) { 483 if (strcmp(fontType, "Type 1") == 0) {
485 info->fType = SkAdvancedTypefaceMetrics::kType1_Font; 484 info->fType = SkAdvancedTypefaceMetrics::kType1_Font;
486 } else if (strcmp(fontType, "CID Type 1") == 0) { 485 } else if (strcmp(fontType, "CID Type 1") == 0) {
487 info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font; 486 info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font;
488 cid = true;
489 } else if (strcmp(fontType, "CFF") == 0) { 487 } else if (strcmp(fontType, "CFF") == 0) {
490 info->fType = SkAdvancedTypefaceMetrics::kCFF_Font; 488 info->fType = SkAdvancedTypefaceMetrics::kCFF_Font;
491 } else if (strcmp(fontType, "TrueType") == 0) { 489 } else if (strcmp(fontType, "TrueType") == 0) {
492 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 490 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
493 cid = true;
494 TT_Header* ttHeader; 491 TT_Header* ttHeader;
495 if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, 492 if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head)) != nu llptr) {
496 ft_sfnt_head)) != nullptr) {
497 info->fEmSize = ttHeader->Units_Per_EM; 493 info->fEmSize = ttHeader->Units_Per_EM;
498 } 494 }
499 } else { 495 } else {
500 info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 496 info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
501 } 497 }
502 498
503 info->fStyle = 0; 499 info->fStyle = 0;
504 if (FT_IS_FIXED_WIDTH(face)) 500 if (FT_IS_FIXED_WIDTH(face)) {
505 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 501 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
506 if (face->style_flags & FT_STYLE_FLAG_ITALIC) 502 }
503 if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
507 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 504 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
505 }
508 506
509 PS_FontInfoRec ps_info; 507 PS_FontInfoRec psFontInfo;
510 TT_Postscript* tt_info; 508 TT_Postscript* postTable;
511 if (FT_Get_PS_Font_Info(face, &ps_info) == 0) { 509 if (FT_Get_PS_Font_Info(face, &psFontInfo) == 0) {
512 info->fItalicAngle = ps_info.italic_angle; 510 info->fItalicAngle = psFontInfo.italic_angle;
513 } else if ((tt_info = 511 } else if ((postTable = (TT_Postscript*)FT_Get_Sfnt_Table(face, ft_sfnt_post )) != nullptr) {
514 (TT_Postscript*)FT_Get_Sfnt_Table(face, 512 info->fItalicAngle = SkFixedToScalar(postTable->italicAngle);
515 ft_sfnt_post)) != nullptr) {
516 info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle);
517 } else { 513 } else {
518 info->fItalicAngle = 0; 514 info->fItalicAngle = 0;
519 } 515 }
520 516
521 info->fAscent = face->ascender; 517 info->fAscent = face->ascender;
522 info->fDescent = face->descender; 518 info->fDescent = face->descender;
523 519
524 // Figure out a good guess for StemV - Min width of i, I, !, 1. 520 // Figure out a good guess for StemV - Min width of i, I, !, 1.
525 // This probably isn't very good with an italic font. 521 // This probably isn't very good with an italic font.
526 int16_t min_width = SHRT_MAX; 522 int16_t min_width = SHRT_MAX;
527 info->fStemV = 0; 523 info->fStemV = 0;
528 char stem_chars[] = {'i', 'I', '!', '1'}; 524 char stem_chars[] = {'i', 'I', '!', '1'};
529 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { 525 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
530 FT_BBox bbox; 526 FT_BBox bbox;
531 if (GetLetterCBox(face, stem_chars[i], &bbox)) { 527 if (GetLetterCBox(face, stem_chars[i], &bbox)) {
532 int16_t width = bbox.xMax - bbox.xMin; 528 int16_t width = bbox.xMax - bbox.xMin;
533 if (width > 0 && width < min_width) { 529 if (width > 0 && width < min_width) {
534 min_width = width; 530 min_width = width;
535 info->fStemV = min_width; 531 info->fStemV = min_width;
536 } 532 }
537 } 533 }
538 } 534 }
539 535
540 TT_PCLT* pclt_info; 536 TT_PCLT* pcltTable;
541 TT_OS2* os2_table; 537 TT_OS2* os2Table;
542 if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != nullptr ) { 538 if ((pcltTable = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != nullptr ) {
543 info->fCapHeight = pclt_info->CapHeight; 539 info->fCapHeight = pcltTable->CapHeight;
544 uint8_t serif_style = pclt_info->SerifStyle & 0x3F; 540 uint8_t serif_style = pcltTable->SerifStyle & 0x3F;
545 if (serif_style >= 2 && serif_style <= 6) 541 if (2 <= serif_style && serif_style <= 6) {
546 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 542 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
547 else if (serif_style >= 9 && serif_style <= 12) 543 } else if (9 <= serif_style && serif_style <= 12) {
548 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 544 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
549 } else if (((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != n ullptr) && 545 }
546 } else if (((os2Table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != nu llptr) &&
550 // sCapHeight is available only when version 2 or later. 547 // sCapHeight is available only when version 2 or later.
551 os2_table->version != 0xFFFF && 548 os2Table->version != 0xFFFF &&
552 os2_table->version >= 2) { 549 os2Table->version >= 2)
553 info->fCapHeight = os2_table->sCapHeight; 550 {
551 info->fCapHeight = os2Table->sCapHeight;
554 } else { 552 } else {
555 // Figure out a good guess for CapHeight: average the height of M and X. 553 // Figure out a good guess for CapHeight: average the height of M and X.
556 FT_BBox m_bbox, x_bbox; 554 FT_BBox m_bbox, x_bbox;
557 bool got_m, got_x; 555 bool got_m, got_x;
558 got_m = GetLetterCBox(face, 'M', &m_bbox); 556 got_m = GetLetterCBox(face, 'M', &m_bbox);
559 got_x = GetLetterCBox(face, 'X', &x_bbox); 557 got_x = GetLetterCBox(face, 'X', &x_bbox);
560 if (got_m && got_x) { 558 if (got_m && got_x) {
561 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - 559 info->fCapHeight = ((m_bbox.yMax - m_bbox.yMin) + (x_bbox.yMax - x_b box.yMin)) / 2;
562 x_bbox.yMin) / 2;
563 } else if (got_m && !got_x) { 560 } else if (got_m && !got_x) {
564 info->fCapHeight = m_bbox.yMax - m_bbox.yMin; 561 info->fCapHeight = m_bbox.yMax - m_bbox.yMin;
565 } else if (!got_m && got_x) { 562 } else if (!got_m && got_x) {
566 info->fCapHeight = x_bbox.yMax - x_bbox.yMin; 563 info->fCapHeight = x_bbox.yMax - x_bbox.yMin;
567 } else { 564 } else {
568 // Last resort, use the ascent. 565 // Last resort, use the ascent.
569 info->fCapHeight = info->fAscent; 566 info->fCapHeight = info->fAscent;
570 } 567 }
571 } 568 }
572 569
573 info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax, 570 info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax,
574 face->bbox.xMax, face->bbox.yMin); 571 face->bbox.xMax, face->bbox.yMin);
575 572
576 if (!FT_IS_SCALABLE(face)) { 573 if (!FT_IS_SCALABLE(face)) {
577 perGlyphInfo = kNo_PerGlyphInfo; 574 perGlyphInfo = kNo_PerGlyphInfo;
578 } 575 }
579 576
580 if (perGlyphInfo & kHAdvance_PerGlyphInfo) { 577 if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
581 if (FT_IS_FIXED_WIDTH(face)) { 578 info->setGlyphWidths(
582 SkAdvancedTypefaceMetrics::WidthRange range(0); 579 face->num_glyphs,
583 int16_t advance = face->max_advance_width; 580 glyphIDs,
584 range.fAdvance.append(1, &advance); 581 glyphIDsCount,
585 SkAdvancedTypefaceMetrics::FinishRange( 582 SkAdvancedTypefaceMetrics::GetAdvance([face](int gId, int16_t* data) {
586 &range, 0, SkAdvancedTypefaceMetrics::WidthRange::kDefault); 583 FT_Fixed advance = 0;
587 info->fGlyphWidths.emplace_back(std::move(range)); 584 if (FT_Get_Advances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
588 } else if (!cid) { 585 return false;
589 SkAdvancedTypefaceMetrics::WidthRange range(0);
590 // So as to not blow out the stack, get advances in batches.
591 for (int gID = 0; gID < face->num_glyphs; gID += 128) {
592 FT_Fixed advances[128];
593 int advanceCount = 128;
594 if (gID + advanceCount > face->num_glyphs) {
595 advanceCount = face->num_glyphs - gID;
596 } 586 }
597 FT_Get_Advances(face, gID, advanceCount, FT_LOAD_NO_SCALE, advan ces); 587 SkASSERT(data);
598 for (int i = 0; i < advanceCount; i++) { 588 *data = advance;
599 int16_t advance = advances[i]; 589 return true;
600 range.fAdvance.append(1, &advance); 590 })
601 } 591 );
602 }
603 SkAdvancedTypefaceMetrics::FinishRange(
604 &range, face->num_glyphs - 1,
605 SkAdvancedTypefaceMetrics::WidthRange::kRange);
606 info->fGlyphWidths.emplace_back(std::move(range));
607 } else {
608 info->setGlyphWidths(
609 face->num_glyphs,
610 glyphIDs,
611 glyphIDsCount,
612 SkAdvancedTypefaceMetrics::GetAdvance([face](int gId, int16_t* d ata) {
613 FT_Fixed advance = 0;
614 if (FT_Get_Advances(face, gId, 1, FT_LOAD_NO_SCALE, &advance )) {
615 return false;
616 }
617 SkASSERT(data);
618 *data = advance;
619 return true;
620 })
621 );
622 }
623 } 592 }
624 593
625 if (perGlyphInfo & kVAdvance_PerGlyphInfo && 594 if (perGlyphInfo & kVAdvance_PerGlyphInfo && FT_HAS_VERTICAL(face)) {
626 FT_HAS_VERTICAL(face)) {
627 SkASSERT(false); // Not implemented yet. 595 SkASSERT(false); // Not implemented yet.
628 } 596 }
629 597
630 if (perGlyphInfo & kGlyphNames_PerGlyphInfo && 598 if (perGlyphInfo & kGlyphNames_PerGlyphInfo &&
631 info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { 599 info->fType == SkAdvancedTypefaceMetrics::kType1_Font)
hal.canary 2016/07/22 16:20:36 style nit: `{` on previous line
600 {
632 // Postscript fonts may contain more than 255 glyphs, so we end up 601 // Postscript fonts may contain more than 255 glyphs, so we end up
633 // using multiple font descriptions with a glyph ordering. Record 602 // using multiple font descriptions with a glyph ordering. Record
634 // the name of each glyph. 603 // the name of each glyph.
635 info->fGlyphNames.reset( 604 info->fGlyphNames.reset(new SkAutoTArray<SkString>(face->num_glyphs));
636 new SkAutoTArray<SkString>(face->num_glyphs));
637 for (int gID = 0; gID < face->num_glyphs; gID++) { 605 for (int gID = 0; gID < face->num_glyphs; gID++) {
638 char glyphName[128]; // PS limit for names is 127 bytes. 606 char glyphName[128]; // PS limit for names is 127 bytes.
639 FT_Get_Glyph_Name(face, gID, glyphName, 128); 607 FT_Get_Glyph_Name(face, gID, glyphName, 128);
640 info->fGlyphNames->get()[gID].set(glyphName); 608 info->fGlyphNames->get()[gID].set(glyphName);
641 } 609 }
642 } 610 }
643 611
644 if (perGlyphInfo & kToUnicode_PerGlyphInfo && 612 if (perGlyphInfo & kToUnicode_PerGlyphInfo &&
645 info->fType != SkAdvancedTypefaceMetrics::kType1_Font && 613 info->fType != SkAdvancedTypefaceMetrics::kType1_Font &&
646 face->num_charmaps) { 614 face->num_charmaps)
hal.canary 2016/07/22 16:20:35 same
615 {
647 populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); 616 populate_glyph_to_unicode(face, &(info->fGlyphToUnicode));
648 } 617 }
649 618
650 return info; 619 return info;
651 #endif 620 #endif
652 } 621 }
653 622
654 /////////////////////////////////////////////////////////////////////////// 623 ///////////////////////////////////////////////////////////////////////////
655 624
656 static bool bothZero(SkScalar a, SkScalar b) { 625 static bool bothZero(SkScalar a, SkScalar b) {
(...skipping 1161 matching lines...) Expand 10 before | Expand all | Expand 10 after
1818 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n", 1787 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n",
1819 name.c_str(), 1788 name.c_str(),
1820 (skTag >> 24) & 0xFF, 1789 (skTag >> 24) & 0xFF,
1821 (skTag >> 16) & 0xFF, 1790 (skTag >> 16) & 0xFF,
1822 (skTag >> 8) & 0xFF, 1791 (skTag >> 8) & 0xFF,
1823 (skTag) & 0xFF)); 1792 (skTag) & 0xFF));
1824 } 1793 }
1825 } 1794 }
1826 ) 1795 )
1827 } 1796 }
OLDNEW
« no previous file with comments | « no previous file | src/ports/SkFontHost_mac.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698