OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2000 Dirk Mueller (mueller@kde.org) | 4 * (C) 2000 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. | 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. |
6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. | 6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include "SkPaint.h" | 28 #include "SkPaint.h" |
29 #include "SkTemplates.h" | 29 #include "SkTemplates.h" |
30 #include "platform/LayoutUnit.h" | 30 #include "platform/LayoutUnit.h" |
31 #include "platform/RuntimeEnabledFeatures.h" | 31 #include "platform/RuntimeEnabledFeatures.h" |
32 #include "platform/fonts/Character.h" | 32 #include "platform/fonts/Character.h" |
33 #include "platform/fonts/FontCache.h" | 33 #include "platform/fonts/FontCache.h" |
34 #include "platform/fonts/FontFallbackList.h" | 34 #include "platform/fonts/FontFallbackList.h" |
35 #include "platform/fonts/GlyphBuffer.h" | 35 #include "platform/fonts/GlyphBuffer.h" |
36 #include "platform/fonts/GlyphPageTreeNode.h" | 36 #include "platform/fonts/GlyphPageTreeNode.h" |
37 #include "platform/fonts/SimpleFontData.h" | 37 #include "platform/fonts/SimpleFontData.h" |
| 38 #include "platform/fonts/shaping/HarfBuzzFace.h" |
38 #include "platform/fonts/shaping/HarfBuzzShaper.h" | 39 #include "platform/fonts/shaping/HarfBuzzShaper.h" |
39 #include "platform/fonts/shaping/SimpleShaper.h" | 40 #include "platform/fonts/shaping/SimpleShaper.h" |
40 #include "platform/geometry/FloatRect.h" | 41 #include "platform/geometry/FloatRect.h" |
41 #include "platform/graphics/skia/SkiaUtils.h" | 42 #include "platform/graphics/skia/SkiaUtils.h" |
42 #include "platform/text/BidiResolver.h" | 43 #include "platform/text/BidiResolver.h" |
43 #include "platform/text/TextRun.h" | 44 #include "platform/text/TextRun.h" |
44 #include "platform/text/TextRunIterator.h" | 45 #include "platform/text/TextRunIterator.h" |
45 #include "platform/transforms/AffineTransform.h" | 46 #include "platform/transforms/AffineTransform.h" |
46 #include "third_party/skia/include/core/SkCanvas.h" | 47 #include "third_party/skia/include/core/SkCanvas.h" |
47 #include "wtf/MainThread.h" | 48 #include "wtf/MainThread.h" |
48 #include "wtf/StdLibExtras.h" | 49 #include "wtf/StdLibExtras.h" |
49 #include "wtf/text/CharacterNames.h" | 50 #include "wtf/text/CharacterNames.h" |
50 #include "wtf/text/Unicode.h" | 51 #include "wtf/text/Unicode.h" |
51 | 52 |
52 using namespace WTF; | 53 using namespace WTF; |
53 using namespace Unicode; | 54 using namespace Unicode; |
54 | 55 |
55 namespace blink { | 56 namespace blink { |
56 | 57 |
57 Font::Font() | 58 Font::Font() |
58 { | 59 { |
59 } | 60 } |
60 | 61 |
61 Font::Font(const FontDescription& fd) | 62 Font::Font(const FontDescription& fd) |
62 : m_fontDescription(fd) | 63 : m_fontDescription(fd) |
| 64 , m_canShapeWordByWord(0) |
| 65 , m_shapeWordByWordComputed(0) |
63 { | 66 { |
64 } | 67 } |
65 | 68 |
66 Font::Font(const Font& other) | 69 Font::Font(const Font& other) |
67 : m_fontDescription(other.m_fontDescription) | 70 : m_fontDescription(other.m_fontDescription) |
68 , m_fontFallbackList(other.m_fontFallbackList) | 71 , m_fontFallbackList(other.m_fontFallbackList) |
| 72 , m_canShapeWordByWord(0) |
| 73 , m_shapeWordByWordComputed(0) |
69 { | 74 { |
70 } | 75 } |
71 | 76 |
72 Font& Font::operator=(const Font& other) | 77 Font& Font::operator=(const Font& other) |
73 { | 78 { |
74 m_fontDescription = other.m_fontDescription; | 79 m_fontDescription = other.m_fontDescription; |
75 m_fontFallbackList = other.m_fontFallbackList; | 80 m_fontFallbackList = other.m_fontFallbackList; |
| 81 m_canShapeWordByWord = other.m_canShapeWordByWord; |
| 82 m_shapeWordByWordComputed = other.m_shapeWordByWordComputed; |
76 return *this; | 83 return *this; |
77 } | 84 } |
78 | 85 |
79 bool Font::operator==(const Font& other) const | 86 bool Font::operator==(const Font& other) const |
80 { | 87 { |
81 FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector(
) : 0; | 88 FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector(
) : 0; |
82 FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList->
fontSelector() : 0; | 89 FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList->
fontSelector() : 0; |
83 | 90 |
84 return first == second | 91 return first == second |
85 && m_fontDescription == other.m_fontDescription | 92 && m_fontDescription == other.m_fontDescription |
(...skipping 10 matching lines...) Expand all Loading... |
96 // and could eventually be rectified by using RefPtrs for Fonts themselves. | 103 // and could eventually be rectified by using RefPtrs for Fonts themselves. |
97 if (!m_fontFallbackList) | 104 if (!m_fontFallbackList) |
98 m_fontFallbackList = FontFallbackList::create(); | 105 m_fontFallbackList = FontFallbackList::create(); |
99 m_fontFallbackList->invalidate(fontSelector); | 106 m_fontFallbackList->invalidate(fontSelector); |
100 } | 107 } |
101 | 108 |
102 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph
Buffer, | 109 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph
Buffer, |
103 const GlyphData* emphasisData) const | 110 const GlyphData* emphasisData) const |
104 { | 111 { |
105 if (codePath(runInfo) == ComplexPath) { | 112 if (codePath(runInfo) == ComplexPath) { |
106 HarfBuzzShaper shaper(this, runInfo.run, emphasisData); | 113 float width; |
107 shaper.setDrawRange(runInfo.from, runInfo.to); | 114 CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper(); |
108 shaper.shape(&glyphBuffer); | 115 if (emphasisData) { |
109 return shaper.totalWidth(); | 116 width = shaper.fillGlyphBufferForTextEmphasis(this, runInfo.run, |
| 117 emphasisData, &glyphBuffer, runInfo.from, runInfo.to); |
| 118 } else { |
| 119 width = shaper.fillGlyphBuffer(this, runInfo.run, nullptr, |
| 120 &glyphBuffer, runInfo.from, runInfo.to); |
| 121 } |
| 122 |
| 123 return width; |
110 } | 124 } |
111 | 125 |
112 SimpleShaper shaper(this, runInfo.run, emphasisData, nullptr /* fallbackFont
s */, nullptr); | 126 SimpleShaper shaper(this, runInfo.run, emphasisData, nullptr /* fallbackFont
s */, nullptr); |
113 shaper.advance(runInfo.from); | 127 shaper.advance(runInfo.from); |
114 shaper.advance(runInfo.to, &glyphBuffer); | 128 shaper.advance(runInfo.to, &glyphBuffer); |
115 float width = shaper.runWidthSoFar(); | 129 float width = shaper.runWidthSoFar(); |
116 | 130 |
117 if (runInfo.run.rtl()) { | 131 if (runInfo.run.rtl()) { |
118 // Glyphs are shaped & stored in RTL advance order - reverse them for LT
R drawing. | 132 // Glyphs are shaped & stored in RTL advance order - reverse them for LT
R drawing. |
119 shaper.advance(runInfo.run.length()); | 133 shaper.advance(runInfo.run.length()); |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 if (run.codePath() == TextRun::ForceSimple) | 344 if (run.codePath() == TextRun::ForceSimple) |
331 return SimplePath; | 345 return SimplePath; |
332 | 346 |
333 if (run.is8Bit()) | 347 if (run.is8Bit()) |
334 return SimplePath; | 348 return SimplePath; |
335 | 349 |
336 // Start from 0 since drawing and highlighting also measure the characters b
efore run->from. | 350 // Start from 0 since drawing and highlighting also measure the characters b
efore run->from. |
337 return Character::characterRangeCodePath(run.characters16(), run.length()); | 351 return Character::characterRangeCodePath(run.characters16(), run.length()); |
338 } | 352 } |
339 | 353 |
| 354 bool Font::canShapeWordByWord() const |
| 355 { |
| 356 if (!m_shapeWordByWordComputed) { |
| 357 m_canShapeWordByWord = computeCanShapeWordByWord(); |
| 358 m_shapeWordByWordComputed = true; |
| 359 } |
| 360 return m_canShapeWordByWord; |
| 361 }; |
| 362 |
| 363 bool Font::computeCanShapeWordByWord() const |
| 364 { |
| 365 if (!fontDescription().typesettingFeatures()) |
| 366 return true; |
| 367 |
| 368 const FontPlatformData& platformData = primaryFont()->platformData(); |
| 369 TypesettingFeatures features = fontDescription().typesettingFeatures(); |
| 370 return !platformData.hasSpaceInLigaturesOrKerning(features); |
| 371 }; |
| 372 |
340 void Font::willUseFontData(UChar32 character) const | 373 void Font::willUseFontData(UChar32 character) const |
341 { | 374 { |
342 const FontFamily& family = fontDescription().family(); | 375 const FontFamily& family = fontDescription().family(); |
343 if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.fami
lyIsEmpty()) | 376 if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.fami
lyIsEmpty()) |
344 m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), f
amily.family(), character); | 377 m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), f
amily.family(), character); |
345 } | 378 } |
346 | 379 |
347 static inline GlyphData glyphDataForNonCJKCharacterWithGlyphOrientation(UChar32
character, bool isUpright, GlyphData& data, unsigned pageNumber) | 380 static inline GlyphData glyphDataForNonCJKCharacterWithGlyphOrientation(UChar32
character, bool isUpright, GlyphData& data, unsigned pageNumber) |
348 { | 381 { |
349 if (isUpright) { | 382 if (isUpright) { |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 canvas->restoreToCount(canvasStackLevel); | 689 canvas->restoreToCount(canvasStackLevel); |
657 } | 690 } |
658 | 691 |
659 void Font::drawTextBlob(SkCanvas* canvas, const SkPaint& paint, const SkTextBlob
* blob, const SkPoint& origin) const | 692 void Font::drawTextBlob(SkCanvas* canvas, const SkPaint& paint, const SkTextBlob
* blob, const SkPoint& origin) const |
660 { | 693 { |
661 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | 694 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
662 | 695 |
663 canvas->drawTextBlob(blob, origin.x(), origin.y(), paint); | 696 canvas->drawTextBlob(blob, origin.x(), origin.y(), paint); |
664 } | 697 } |
665 | 698 |
666 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
tData*>* fallbackFonts, FloatRect* outGlyphBounds) const | 699 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
tData*>* fallbackFonts, FloatRect* glyphBounds) const |
667 { | 700 { |
668 bool hasWordSpacingOrLetterSpacing = fontDescription().wordSpacing() | 701 CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper(); |
669 || fontDescription().letterSpacing(); | 702 float width = shaper.width(this, run, fallbackFonts, glyphBounds); |
670 // Word spacing and letter spacing can change the width of a word. | 703 return width; |
671 // If a tab occurs inside a word, the width of the word varies based on its | |
672 // position on the line. | |
673 bool isCacheable = !hasWordSpacingOrLetterSpacing && !run.allowTabs(); | |
674 | |
675 WidthCacheEntry* cacheEntry = isCacheable | |
676 ? m_fontFallbackList->widthCache().add(run, WidthCacheEntry()) | |
677 : 0; | |
678 if (cacheEntry && cacheEntry->isValid()) { | |
679 if (outGlyphBounds) | |
680 *outGlyphBounds = cacheEntry->glyphBounds; | |
681 return cacheEntry->width; | |
682 } | |
683 | |
684 FloatRect glyphBounds; | |
685 HarfBuzzShaper shaper(this, run, nullptr, fallbackFonts, &glyphBounds); | |
686 if (!shaper.shape()) | |
687 return 0; | |
688 | |
689 float result = shaper.totalWidth(); | |
690 | |
691 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) { | |
692 cacheEntry->glyphBounds = glyphBounds; | |
693 cacheEntry->width = result; | |
694 } | |
695 | |
696 if (outGlyphBounds) | |
697 *outGlyphBounds = glyphBounds; | |
698 return result; | |
699 } | 704 } |
700 | 705 |
701 // Return the code point index for the given |x| offset into the text run. | 706 // Return the code point index for the given |x| offset into the text run. |
702 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, | 707 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, |
703 bool includePartialGlyphs) const | 708 bool includePartialGlyphs) const |
704 { | 709 { |
705 HarfBuzzShaper shaper(this, run); | 710 HarfBuzzShaper shaper(this, run); |
706 if (!shaper.shape()) | 711 RefPtr<ShapeResult> shapeResult = shaper.shapeResult(); |
| 712 if (!shapeResult) |
707 return 0; | 713 return 0; |
708 return shaper.offsetForPosition(xFloat); | 714 return shapeResult->offsetForPosition(xFloat); |
709 } | 715 } |
710 | 716 |
711 // Return the rectangle for selecting the given range of code-points in the Text
Run. | 717 // Return the rectangle for selecting the given range of code-points in the Text
Run. |
712 FloatRect Font::selectionRectForComplexText(const TextRun& run, | 718 FloatRect Font::selectionRectForComplexText(const TextRun& run, |
713 const FloatPoint& point, int height, int from, int to) const | 719 const FloatPoint& point, int height, int from, int to) const |
714 { | 720 { |
715 HarfBuzzShaper shaper(this, run); | 721 CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper(); |
716 if (!shaper.shape()) | 722 return shaper.selectionRect(this, run, point, height, from, to); |
717 return FloatRect(); | |
718 return shaper.selectionRect(point, height, from, to); | |
719 } | 723 } |
720 | 724 |
721 void Font::drawGlyphBuffer(SkCanvas* canvas, const SkPaint& paint, const TextRun
PaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point, flo
at deviceScaleFactor) const | 725 void Font::drawGlyphBuffer(SkCanvas* canvas, const SkPaint& paint, const TextRun
PaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point, flo
at deviceScaleFactor) const |
722 { | 726 { |
723 if (glyphBuffer.isEmpty()) | 727 if (glyphBuffer.isEmpty()) |
724 return; | 728 return; |
725 | 729 |
726 if (RuntimeEnabledFeatures::textBlobEnabled()) { | 730 if (RuntimeEnabledFeatures::textBlobEnabled()) { |
727 // Enabling text-blobs forces the blob rendering path even for uncacheab
le blobs. | 731 // Enabling text-blobs forces the blob rendering path even for uncacheab
le blobs. |
728 TextBlobPtr uncacheableTextBlob; | 732 TextBlobPtr uncacheableTextBlob; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
830 { | 834 { |
831 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); | 835 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); |
832 } | 836 } |
833 | 837 |
834 bool Font::isFallbackValid() const | 838 bool Font::isFallbackValid() const |
835 { | 839 { |
836 return !m_fontFallbackList || m_fontFallbackList->isValid(); | 840 return !m_fontFallbackList || m_fontFallbackList->isValid(); |
837 } | 841 } |
838 | 842 |
839 } // namespace blink | 843 } // namespace blink |
OLD | NEW |