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

Side by Side Diff: Source/platform/fonts/Font.cpp

Issue 1192223002: Optimize Complex Text Shaping and Caching (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Change CachingWordShaperTest as suggested Created 5 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 | Annotate | Revision Log
« no previous file with comments | « Source/platform/fonts/Font.h ('k') | Source/platform/fonts/FontCache.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 (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
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/platform/fonts/Font.h ('k') | Source/platform/fonts/FontCache.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698