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 |
11 * version 2 of the License, or (at your option) any later version. | 11 * version 2 of the License, or (at your option) any later version. |
12 * | 12 * |
13 * This library is distributed in the hope that it will be useful, | 13 * This library is distributed in the hope that it will be useful, |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 * Library General Public License for more details. | 16 * Library General Public License for more details. |
17 * | 17 * |
18 * You should have received a copy of the GNU Library General Public License | 18 * You should have received a copy of the GNU Library General Public License |
19 * along with this library; see the file COPYING.LIB. If not, write to | 19 * along with this library; see the file COPYING.LIB. If not, write to |
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
21 * Boston, MA 02110-1301, USA. | 21 * Boston, MA 02110-1301, USA. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 #include "config.h" | 25 #include "config.h" |
26 #include "platform/fonts/Font.h" | 26 #include "platform/fonts/Font.h" |
27 | 27 |
28 #include "SkPaint.h" | 28 #include "SkPaint.h" |
29 #include "SkTemplates.h" | 29 #include "SkTemplates.h" |
30 #include "hb-ot.h" | |
31 #include "hb.h" | |
30 #include "platform/LayoutUnit.h" | 32 #include "platform/LayoutUnit.h" |
31 #include "platform/RuntimeEnabledFeatures.h" | 33 #include "platform/RuntimeEnabledFeatures.h" |
32 #include "platform/fonts/Character.h" | 34 #include "platform/fonts/Character.h" |
33 #include "platform/fonts/FontCache.h" | 35 #include "platform/fonts/FontCache.h" |
34 #include "platform/fonts/FontFallbackList.h" | 36 #include "platform/fonts/FontFallbackList.h" |
35 #include "platform/fonts/GlyphBuffer.h" | 37 #include "platform/fonts/GlyphBuffer.h" |
36 #include "platform/fonts/GlyphPageTreeNode.h" | 38 #include "platform/fonts/GlyphPageTreeNode.h" |
37 #include "platform/fonts/SimpleFontData.h" | 39 #include "platform/fonts/SimpleFontData.h" |
40 #include "platform/fonts/shaping/HarfBuzzFace.h" | |
38 #include "platform/fonts/shaping/HarfBuzzShaper.h" | 41 #include "platform/fonts/shaping/HarfBuzzShaper.h" |
39 #include "platform/fonts/shaping/SimpleShaper.h" | 42 #include "platform/fonts/shaping/SimpleShaper.h" |
40 #include "platform/geometry/FloatRect.h" | 43 #include "platform/geometry/FloatRect.h" |
41 #include "platform/graphics/skia/SkiaUtils.h" | 44 #include "platform/graphics/skia/SkiaUtils.h" |
42 #include "platform/text/BidiResolver.h" | 45 #include "platform/text/BidiResolver.h" |
43 #include "platform/text/TextRun.h" | 46 #include "platform/text/TextRun.h" |
44 #include "platform/text/TextRunIterator.h" | 47 #include "platform/text/TextRunIterator.h" |
45 #include "platform/transforms/AffineTransform.h" | 48 #include "platform/transforms/AffineTransform.h" |
46 #include "third_party/skia/include/core/SkCanvas.h" | 49 #include "third_party/skia/include/core/SkCanvas.h" |
47 #include "wtf/MainThread.h" | 50 #include "wtf/MainThread.h" |
48 #include "wtf/StdLibExtras.h" | 51 #include "wtf/StdLibExtras.h" |
49 #include "wtf/unicode/CharacterNames.h" | 52 #include "wtf/unicode/CharacterNames.h" |
50 #include "wtf/unicode/Unicode.h" | 53 #include "wtf/unicode/Unicode.h" |
51 | 54 |
52 using namespace WTF; | 55 using namespace WTF; |
53 using namespace Unicode; | 56 using namespace Unicode; |
54 | 57 |
55 namespace blink { | 58 namespace blink { |
56 | 59 |
57 Font::Font() | 60 Font::Font() |
58 { | 61 { |
59 } | 62 } |
60 | 63 |
61 Font::Font(const FontDescription& fd) | 64 Font::Font(const FontDescription& fd) |
62 : m_fontDescription(fd) | 65 : m_fontDescription(fd) |
66 , m_canShapeWordByWord(0) | |
67 , m_shapeWordByWordComputed(0) | |
63 { | 68 { |
64 } | 69 } |
65 | 70 |
66 Font::Font(const Font& other) | 71 Font::Font(const Font& other) |
67 : m_fontDescription(other.m_fontDescription) | 72 : m_fontDescription(other.m_fontDescription) |
68 , m_fontFallbackList(other.m_fontFallbackList) | 73 , m_fontFallbackList(other.m_fontFallbackList) |
74 , m_canShapeWordByWord(0) | |
75 , m_shapeWordByWordComputed(0) | |
69 { | 76 { |
70 } | 77 } |
71 | 78 |
72 Font& Font::operator=(const Font& other) | 79 Font& Font::operator=(const Font& other) |
73 { | 80 { |
74 m_fontDescription = other.m_fontDescription; | 81 m_fontDescription = other.m_fontDescription; |
75 m_fontFallbackList = other.m_fontFallbackList; | 82 m_fontFallbackList = other.m_fontFallbackList; |
83 m_canShapeWordByWord = other.m_canShapeWordByWord; | |
84 m_shapeWordByWordComputed = other.m_shapeWordByWordComputed; | |
76 return *this; | 85 return *this; |
77 } | 86 } |
78 | 87 |
79 bool Font::operator==(const Font& other) const | 88 bool Font::operator==(const Font& other) const |
80 { | 89 { |
81 FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector( ) : 0; | 90 FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector( ) : 0; |
82 FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList-> fontSelector() : 0; | 91 FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList-> fontSelector() : 0; |
83 | 92 |
84 return first == second | 93 return first == second |
85 && m_fontDescription == other.m_fontDescription | 94 && m_fontDescription == other.m_fontDescription |
(...skipping 10 matching lines...) Expand all Loading... | |
96 // and could eventually be rectified by using RefPtrs for Fonts themselves. | 105 // and could eventually be rectified by using RefPtrs for Fonts themselves. |
97 if (!m_fontFallbackList) | 106 if (!m_fontFallbackList) |
98 m_fontFallbackList = FontFallbackList::create(); | 107 m_fontFallbackList = FontFallbackList::create(); |
99 m_fontFallbackList->invalidate(fontSelector); | 108 m_fontFallbackList->invalidate(fontSelector); |
100 } | 109 } |
101 | 110 |
102 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph Buffer, | 111 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph Buffer, |
103 const GlyphData* emphasisData) const | 112 const GlyphData* emphasisData) const |
104 { | 113 { |
105 if (codePath(runInfo) == ComplexPath) { | 114 if (codePath(runInfo) == ComplexPath) { |
106 HarfBuzzShaper shaper(this, runInfo.run, emphasisData); | 115 float width; |
107 shaper.setDrawRange(runInfo.from, runInfo.to); | 116 if (emphasisData) { |
108 shaper.shape(&glyphBuffer); | 117 // FIXME: Populate using CachingWordShaper. |
drott
2015/06/23 12:45:51
IIRC, in a couple of reviews dpranke asked me to n
| |
109 return shaper.totalWidth(); | 118 HarfBuzzShaper shaper(this, runInfo.run); |
119 RefPtr<ShapeResult> shapeResult = shaper.shapeResult(); | |
120 shapeResult->fillGlyphBufferForTextEmphasis(&glyphBuffer, 0, | |
121 runInfo.run, emphasisData, runInfo.from, runInfo.to, 0); | |
122 width = shapeResult->width(); | |
123 } else { | |
124 CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper(); | |
125 width = shaper.fillGlyphBuffer(this, runInfo.run, nullptr, | |
126 &glyphBuffer, runInfo.from, runInfo.to); | |
127 } | |
128 | |
129 return width; | |
110 } | 130 } |
111 | 131 |
112 SimpleShaper shaper(this, runInfo.run, emphasisData, nullptr /* fallbackFont s */, nullptr); | 132 SimpleShaper shaper(this, runInfo.run, emphasisData, nullptr /* fallbackFont s */, nullptr); |
113 shaper.advance(runInfo.from); | 133 shaper.advance(runInfo.from); |
114 shaper.advance(runInfo.to, &glyphBuffer); | 134 shaper.advance(runInfo.to, &glyphBuffer); |
115 float width = shaper.runWidthSoFar(); | 135 float width = shaper.runWidthSoFar(); |
116 | 136 |
117 if (runInfo.run.rtl()) { | 137 if (runInfo.run.rtl()) { |
118 // Glyphs are shaped & stored in RTL advance order - reverse them for LT R drawing. | 138 // Glyphs are shaped & stored in RTL advance order - reverse them for LT R drawing. |
119 shaper.advance(runInfo.run.length()); | 139 shaper.advance(runInfo.run.length()); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
327 if (run.codePath() == TextRun::ForceSimple) | 347 if (run.codePath() == TextRun::ForceSimple) |
328 return SimplePath; | 348 return SimplePath; |
329 | 349 |
330 if (run.is8Bit()) | 350 if (run.is8Bit()) |
331 return SimplePath; | 351 return SimplePath; |
332 | 352 |
333 // Start from 0 since drawing and highlighting also measure the characters b efore run->from. | 353 // Start from 0 since drawing and highlighting also measure the characters b efore run->from. |
334 return Character::characterRangeCodePath(run.characters16(), run.length()); | 354 return Character::characterRangeCodePath(run.characters16(), run.length()); |
335 } | 355 } |
336 | 356 |
357 static inline bool tableHasSpace(hb_face_t* face, hb_set_t* glyphs, | |
358 hb_tag_t tag, hb_codepoint_t space) | |
359 { | |
360 unsigned count = hb_ot_layout_table_get_lookup_count(face, tag); | |
361 for (unsigned i = 0; i < count; i++) { | |
362 hb_ot_layout_lookup_collect_glyphs(face, tag, i, glyphs, glyphs, glyphs, | |
363 0); | |
364 if (hb_set_has(glyphs, space)) | |
365 return true; | |
366 } | |
367 return false; | |
368 } | |
369 | |
370 bool Font::canShapeWordByWord() const | |
371 { | |
372 if (!m_shapeWordByWordComputed) { | |
373 m_canShapeWordByWord = computeCanShapeWordByWord(); | |
374 m_shapeWordByWordComputed = true; | |
375 } | |
376 return m_canShapeWordByWord; | |
377 }; | |
378 | |
379 bool Font::computeCanShapeWordByWord() const | |
380 { | |
381 if (!fontDescription().typesettingFeatures()) | |
382 return true; | |
383 | |
384 const FontPlatformData& platformData = primaryFont()->platformData(); | |
drott
2015/06/23 12:45:51
I'd suggest to move the code from below this line
| |
385 const HarfBuzzFace* hbFace = platformData.harfBuzzFace(); | |
386 if (!hbFace) | |
387 return true; | |
388 | |
389 hb_face_t* face = hbFace->face(); | |
390 ASSERT(face); | |
391 hb_font_t* font = hbFace->createFont(); | |
392 ASSERT(font); | |
393 | |
394 hb_codepoint_t space; | |
395 // If the space glyph isn't present in the font then each space character | |
396 // will be rendering using a fallback font, which grantees that it cannot | |
397 // affect the shape of the preceding word. | |
398 if (!hb_font_get_glyph(font, spaceCharacter, 0, &space)) | |
399 return true; | |
400 | |
401 if (!hb_ot_layout_has_substitution(face) | |
402 && !hb_ot_layout_has_positioning(face)) { | |
403 return true; | |
404 } | |
405 | |
406 hb_set_t* glyphs = hb_set_create(); | |
407 TypesettingFeatures features = fontDescription().typesettingFeatures(); | |
408 | |
409 bool foundSpaceInTable = false; | |
410 if (features & Kerning) | |
411 foundSpaceInTable = tableHasSpace(face, glyphs, HB_OT_TAG_GPOS, space); | |
412 if (!foundSpaceInTable && (features & Ligatures)) | |
413 foundSpaceInTable = tableHasSpace(face, glyphs, HB_OT_TAG_GSUB, space); | |
414 | |
415 hb_set_destroy(glyphs); | |
416 hb_font_destroy(font); | |
417 | |
418 return !foundSpaceInTable; | |
419 }; | |
420 | |
337 void Font::willUseFontData(UChar32 character) const | 421 void Font::willUseFontData(UChar32 character) const |
338 { | 422 { |
339 const FontFamily& family = fontDescription().family(); | 423 const FontFamily& family = fontDescription().family(); |
340 if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.fami lyIsEmpty()) | 424 if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.fami lyIsEmpty()) |
341 m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), f amily.family(), character); | 425 m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), f amily.family(), character); |
342 } | 426 } |
343 | 427 |
344 static inline GlyphData glyphDataForNonCJKCharacterWithGlyphOrientation(UChar32 character, FontOrientation orientation, GlyphData& data, unsigned pageNumber) | 428 static inline GlyphData glyphDataForNonCJKCharacterWithGlyphOrientation(UChar32 character, FontOrientation orientation, GlyphData& data, unsigned pageNumber) |
345 { | 429 { |
346 if (isVerticalNonCJKUpright(orientation) || Character::shouldIgnoreRotation( character)) { | 430 if (isVerticalNonCJKUpright(orientation) || Character::shouldIgnoreRotation( character)) { |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
663 canvas->restoreToCount(canvasStackLevel); | 747 canvas->restoreToCount(canvasStackLevel); |
664 } | 748 } |
665 | 749 |
666 void Font::drawTextBlob(SkCanvas* canvas, const SkPaint& paint, const SkTextBlob * blob, const SkPoint& origin) const | 750 void Font::drawTextBlob(SkCanvas* canvas, const SkPaint& paint, const SkTextBlob * blob, const SkPoint& origin) const |
667 { | 751 { |
668 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | 752 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
669 | 753 |
670 canvas->drawTextBlob(blob, origin.x(), origin.y(), paint); | 754 canvas->drawTextBlob(blob, origin.x(), origin.y(), paint); |
671 } | 755 } |
672 | 756 |
673 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon tData*>* fallbackFonts, FloatRect* outGlyphBounds) const | 757 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon tData*>* fallbackFonts, FloatRect* glyphBounds) const |
674 { | 758 { |
675 bool hasWordSpacingOrLetterSpacing = fontDescription().wordSpacing() | 759 CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper(); |
676 || fontDescription().letterSpacing(); | 760 float width = shaper.width(this, run, fallbackFonts, glyphBounds); |
677 // Word spacing and letter spacing can change the width of a word. | 761 return width; |
678 // If a tab occurs inside a word, the width of the word varies based on its | |
679 // position on the line. | |
680 bool isCacheable = !hasWordSpacingOrLetterSpacing && !run.allowTabs(); | |
681 | |
682 WidthCacheEntry* cacheEntry = isCacheable | |
683 ? m_fontFallbackList->widthCache().add(run, WidthCacheEntry()) | |
684 : 0; | |
685 if (cacheEntry && cacheEntry->isValid()) { | |
686 if (outGlyphBounds) | |
687 *outGlyphBounds = cacheEntry->glyphBounds; | |
688 return cacheEntry->width; | |
689 } | |
690 | |
691 FloatRect glyphBounds; | |
692 HarfBuzzShaper shaper(this, run, nullptr, fallbackFonts, &glyphBounds); | |
693 if (!shaper.shape()) | |
694 return 0; | |
695 | |
696 float result = shaper.totalWidth(); | |
697 | |
698 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) { | |
699 cacheEntry->glyphBounds = glyphBounds; | |
700 cacheEntry->width = result; | |
701 } | |
702 | |
703 if (outGlyphBounds) | |
704 *outGlyphBounds = glyphBounds; | |
705 return result; | |
706 } | 762 } |
707 | 763 |
708 // Return the code point index for the given |x| offset into the text run. | 764 // Return the code point index for the given |x| offset into the text run. |
709 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, | 765 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, |
710 bool includePartialGlyphs) const | 766 bool includePartialGlyphs) const |
711 { | 767 { |
712 HarfBuzzShaper shaper(this, run); | 768 HarfBuzzShaper shaper(this, run); |
713 if (!shaper.shape()) | 769 RefPtr<ShapeResult> shapeResult = shaper.shapeResult(); |
770 if (!shapeResult) | |
714 return 0; | 771 return 0; |
715 return shaper.offsetForPosition(xFloat); | 772 return shapeResult->offsetForPosition(xFloat); |
716 } | 773 } |
717 | 774 |
718 // Return the rectangle for selecting the given range of code-points in the Text Run. | 775 // Return the rectangle for selecting the given range of code-points in the Text Run. |
719 FloatRect Font::selectionRectForComplexText(const TextRun& run, | 776 FloatRect Font::selectionRectForComplexText(const TextRun& run, |
720 const FloatPoint& point, int height, int from, int to) const | 777 const FloatPoint& point, int height, int from, int to) const |
721 { | 778 { |
722 HarfBuzzShaper shaper(this, run); | 779 HarfBuzzShaper shaper(this, run); |
723 if (!shaper.shape()) | 780 RefPtr<ShapeResult> shapeResult = shaper.shapeResult(); |
781 if (!shapeResult) | |
724 return FloatRect(); | 782 return FloatRect(); |
725 return shaper.selectionRect(point, height, from, to); | 783 return shapeResult->selectionRect(point, height, from, to); |
726 } | 784 } |
727 | 785 |
728 void Font::drawGlyphBuffer(SkCanvas* canvas, const SkPaint& paint, const TextRun PaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point, flo at deviceScaleFactor) const | 786 void Font::drawGlyphBuffer(SkCanvas* canvas, const SkPaint& paint, const TextRun PaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point, flo at deviceScaleFactor) const |
729 { | 787 { |
730 if (glyphBuffer.isEmpty()) | 788 if (glyphBuffer.isEmpty()) |
731 return; | 789 return; |
732 | 790 |
733 if (RuntimeEnabledFeatures::textBlobEnabled()) { | 791 if (RuntimeEnabledFeatures::textBlobEnabled()) { |
734 // Enabling text-blobs forces the blob rendering path even for uncacheab le blobs. | 792 // Enabling text-blobs forces the blob rendering path even for uncacheab le blobs. |
735 TextBlobPtr uncacheableTextBlob; | 793 TextBlobPtr uncacheableTextBlob; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
837 { | 895 { |
838 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); | 896 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); |
839 } | 897 } |
840 | 898 |
841 bool Font::isFallbackValid() const | 899 bool Font::isFallbackValid() const |
842 { | 900 { |
843 return !m_fontFallbackList || m_fontFallbackList->isValid(); | 901 return !m_fontFallbackList || m_fontFallbackList->isValid(); |
844 } | 902 } |
845 | 903 |
846 } // namespace blink | 904 } // namespace blink |
OLD | NEW |