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

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: Remove TypesettingFeatures check Created 5 years, 6 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
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/unicode/CharacterNames.h" 50 #include "wtf/unicode/CharacterNames.h"
50 #include "wtf/unicode/Unicode.h" 51 #include "wtf/unicode/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 return !platformData.hasSpaceInLigaturesOrKerning();
370 };
371
340 void Font::willUseFontData(UChar32 character) const 372 void Font::willUseFontData(UChar32 character) const
341 { 373 {
342 const FontFamily& family = fontDescription().family(); 374 const FontFamily& family = fontDescription().family();
343 if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.fami lyIsEmpty()) 375 if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.fami lyIsEmpty())
344 m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), f amily.family(), character); 376 m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), f amily.family(), character);
345 } 377 }
346 378
347 static inline GlyphData glyphDataForNonCJKCharacterWithGlyphOrientation(UChar32 character, FontOrientation orientation, GlyphData& data, unsigned pageNumber) 379 static inline GlyphData glyphDataForNonCJKCharacterWithGlyphOrientation(UChar32 character, FontOrientation orientation, GlyphData& data, unsigned pageNumber)
348 { 380 {
349 if (isVerticalNonCJKUpright(orientation) || Character::shouldIgnoreRotation( character)) { 381 if (isVerticalNonCJKUpright(orientation) || Character::shouldIgnoreRotation( character)) {
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 canvas->restoreToCount(canvasStackLevel); 698 canvas->restoreToCount(canvasStackLevel);
667 } 699 }
668 700
669 void Font::drawTextBlob(SkCanvas* canvas, const SkPaint& paint, const SkTextBlob * blob, const SkPoint& origin) const 701 void Font::drawTextBlob(SkCanvas* canvas, const SkPaint& paint, const SkTextBlob * blob, const SkPoint& origin) const
670 { 702 {
671 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); 703 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
672 704
673 canvas->drawTextBlob(blob, origin.x(), origin.y(), paint); 705 canvas->drawTextBlob(blob, origin.x(), origin.y(), paint);
674 } 706 }
675 707
676 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon tData*>* fallbackFonts, FloatRect* outGlyphBounds) const 708 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon tData*>* fallbackFonts, FloatRect* glyphBounds) const
677 { 709 {
678 bool hasWordSpacingOrLetterSpacing = fontDescription().wordSpacing() 710 CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper();
679 || fontDescription().letterSpacing(); 711 float width = shaper.width(this, run, fallbackFonts, glyphBounds);
680 // Word spacing and letter spacing can change the width of a word. 712 return width;
681 // If a tab occurs inside a word, the width of the word varies based on its
682 // position on the line.
683 bool isCacheable = !hasWordSpacingOrLetterSpacing && !run.allowTabs();
684
685 WidthCacheEntry* cacheEntry = isCacheable
686 ? m_fontFallbackList->widthCache().add(run, WidthCacheEntry())
687 : 0;
688 if (cacheEntry && cacheEntry->isValid()) {
689 if (outGlyphBounds)
690 *outGlyphBounds = cacheEntry->glyphBounds;
691 return cacheEntry->width;
692 }
693
694 FloatRect glyphBounds;
695 HarfBuzzShaper shaper(this, run, nullptr, fallbackFonts, &glyphBounds);
696 if (!shaper.shape())
697 return 0;
698
699 float result = shaper.totalWidth();
700
701 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) {
702 cacheEntry->glyphBounds = glyphBounds;
703 cacheEntry->width = result;
704 }
705
706 if (outGlyphBounds)
707 *outGlyphBounds = glyphBounds;
708 return result;
709 } 713 }
710 714
711 // Return the code point index for the given |x| offset into the text run. 715 // Return the code point index for the given |x| offset into the text run.
712 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, 716 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
713 bool includePartialGlyphs) const 717 bool includePartialGlyphs) const
714 { 718 {
715 HarfBuzzShaper shaper(this, run); 719 HarfBuzzShaper shaper(this, run);
716 if (!shaper.shape()) 720 RefPtr<ShapeResult> shapeResult = shaper.shapeResult();
721 if (!shapeResult)
717 return 0; 722 return 0;
718 return shaper.offsetForPosition(xFloat); 723 return shapeResult->offsetForPosition(xFloat);
719 } 724 }
720 725
721 // Return the rectangle for selecting the given range of code-points in the Text Run. 726 // Return the rectangle for selecting the given range of code-points in the Text Run.
722 FloatRect Font::selectionRectForComplexText(const TextRun& run, 727 FloatRect Font::selectionRectForComplexText(const TextRun& run,
723 const FloatPoint& point, int height, int from, int to) const 728 const FloatPoint& point, int height, int from, int to) const
724 { 729 {
725 HarfBuzzShaper shaper(this, run); 730 CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper();
726 if (!shaper.shape()) 731 return shaper.selectionRect(this, run, point, height, from, to);
727 return FloatRect();
728 return shaper.selectionRect(point, height, from, to);
729 } 732 }
730 733
731 void Font::drawGlyphBuffer(SkCanvas* canvas, const SkPaint& paint, const TextRun PaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point, flo at deviceScaleFactor) const 734 void Font::drawGlyphBuffer(SkCanvas* canvas, const SkPaint& paint, const TextRun PaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point, flo at deviceScaleFactor) const
732 { 735 {
733 if (glyphBuffer.isEmpty()) 736 if (glyphBuffer.isEmpty())
734 return; 737 return;
735 738
736 if (RuntimeEnabledFeatures::textBlobEnabled()) { 739 if (RuntimeEnabledFeatures::textBlobEnabled()) {
737 // Enabling text-blobs forces the blob rendering path even for uncacheab le blobs. 740 // Enabling text-blobs forces the blob rendering path even for uncacheab le blobs.
738 TextBlobPtr uncacheableTextBlob; 741 TextBlobPtr uncacheableTextBlob;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 { 843 {
841 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); 844 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts();
842 } 845 }
843 846
844 bool Font::isFallbackValid() const 847 bool Font::isFallbackValid() const
845 { 848 {
846 return !m_fontFallbackList || m_fontFallbackList->isValid(); 849 return !m_fontFallbackList || m_fontFallbackList->isValid();
847 } 850 }
848 851
849 } // namespace blink 852 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698