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

Side by Side Diff: third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.cpp

Issue 1479003002: Remove Simple Text Path (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 1 month 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
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2003, 2006, 2008, 2009, 2010, 2011 Apple Inc. All rights
3 * reserved.
4 * Copyright (C) 2008 Holger Hans Peter Freyther
5 * Copyright (C) 2014 Google Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24 #include "platform/fonts/shaping/SimpleShaper.h"
25
26 #include "platform/fonts/Font.h"
27 #include "platform/fonts/GlyphBuffer.h"
28 #include "platform/fonts/Latin1TextIterator.h"
29 #include "platform/fonts/SimpleFontData.h"
30 #include "platform/fonts/UTF16TextIterator.h"
31 #include "platform/text/Character.h"
32 #include "wtf/MathExtras.h"
33 #include "wtf/text/CharacterNames.h"
34
35 using namespace WTF;
36 using namespace Unicode;
37
38 namespace blink {
39
40 SimpleShaper::SimpleShaper(const Font* font,
41 const TextRun& run,
42 const GlyphData* emphasisData,
43 HashSet<const SimpleFontData*>* fallbackFonts,
44 FloatRect* bounds)
45 : Shaper(font, run, emphasisData, fallbackFonts, bounds),
46 m_currentCharacter(0),
47 m_runWidthSoFar(0) {
48 // If the padding is non-zero, count the number of spaces in the run
49 // and divide that by the padding for per space addition.
50 m_expansion = m_textRun.expansion();
51 if (!m_expansion) {
52 m_expansionPerOpportunity = 0;
53 } else {
54 bool isAfterExpansion = m_isAfterExpansion;
55 unsigned expansionOpportunityCount =
56 m_textRun.is8Bit() ? Character::expansionOpportunityCount(
57 m_textRun.characters8(), m_textRun.length(),
58 m_textRun.direction(), isAfterExpansion,
59 m_textRun.getTextJustify())
60 : Character::expansionOpportunityCount(
61 m_textRun.characters16(), m_textRun.length(),
62 m_textRun.direction(), isAfterExpansion,
63 m_textRun.getTextJustify());
64 if (isAfterExpansion && !m_textRun.allowsTrailingExpansion())
65 expansionOpportunityCount--;
66
67 if (!expansionOpportunityCount)
68 m_expansionPerOpportunity = 0;
69 else
70 m_expansionPerOpportunity = m_expansion / expansionOpportunityCount;
71 }
72 }
73
74 GlyphData SimpleShaper::glyphDataForCharacter(CharacterData& charData,
75 bool normalizeSpace) {
76 ASSERT(m_font);
77 return m_font->glyphDataForCharacter(charData.character, m_textRun.rtl(),
78 normalizeSpace);
79 }
80
81 float SimpleShaper::characterWidth(UChar32 character,
82 const GlyphData& glyphData) const {
83 const SimpleFontData* fontData = glyphData.fontData;
84 ASSERT(fontData);
85
86 if (UNLIKELY(character == tabulationCharacter && m_textRun.allowTabs()))
87 return m_font->tabWidth(fontData, m_textRun.getTabSize(),
88 m_textRun.xPos() + m_runWidthSoFar);
89
90 float width = fontData->widthForGlyph(glyphData.glyph);
91
92 // SVG uses horizontalGlyphStretch(), when textLength is used to
93 // stretch/squeeze text.
94 if (UNLIKELY(m_textRun.horizontalGlyphStretch() != 1))
95 width *= m_textRun.horizontalGlyphStretch();
96
97 return width;
98 }
99
100 float SimpleShaper::adjustSpacing(float width, const CharacterData& charData) {
101 // Account for letter-spacing.
102 if (width)
103 width += m_font->getFontDescription().letterSpacing();
104
105 bool isExpansionOpportunity =
106 Character::treatAsSpace(charData.character) ||
107 (m_textRun.getTextJustify() == TextJustifyDistribute);
108 if (isExpansionOpportunity ||
109 (m_textRun.getTextJustify() == TextJustifyAuto &&
110 Character::isCJKIdeographOrSymbol(charData.character))) {
111 // Distribute the run's total expansion evenly over all expansion
112 // opportunities in the run.
113 if (m_expansion) {
114 if (!isExpansionOpportunity && !m_isAfterExpansion) {
115 // Take the expansion opportunity before this ideograph.
116 m_expansion -= m_expansionPerOpportunity;
117 m_runWidthSoFar += m_expansionPerOpportunity;
118 }
119 if (m_textRun.allowsTrailingExpansion() ||
120 (m_textRun.ltr() &&
121 charData.characterOffset + charData.clusterLength <
122 m_textRun.length()) ||
123 (m_textRun.rtl() && charData.characterOffset)) {
124 m_expansion -= m_expansionPerOpportunity;
125 width += m_expansionPerOpportunity;
126 m_isAfterExpansion = true;
127 }
128 } else {
129 m_isAfterExpansion = false;
130 }
131
132 // Account for word spacing.
133 // We apply additional space between "words" by adding width to the space
134 // character.
135 if (isExpansionOpportunity &&
136 (charData.character != tabulationCharacter || !m_textRun.allowTabs()) &&
137 (charData.characterOffset ||
138 charData.character == noBreakSpaceCharacter) &&
139 m_font->getFontDescription().wordSpacing()) {
140 width += m_font->getFontDescription().wordSpacing();
141 }
142 } else {
143 m_isAfterExpansion = false;
144 }
145
146 return width;
147 }
148
149 template <typename TextIterator>
150 unsigned SimpleShaper::advanceInternal(TextIterator& textIterator,
151 GlyphBuffer* glyphBuffer) {
152 bool hasExtraSpacing =
153 (m_font->getFontDescription().letterSpacing() ||
154 m_font->getFontDescription().wordSpacing() || m_expansion) &&
155 !m_textRun.spacingDisabled();
156
157 const SimpleFontData* lastFontData = m_font->primaryFont();
158 bool normalizeSpace = m_textRun.normalizeSpace();
159 const float initialRunWidth = m_runWidthSoFar;
160
161 CharacterData charData;
162 while (textIterator.consume(charData.character)) {
163 charData.characterOffset = textIterator.offset();
164 charData.clusterLength = textIterator.glyphLength();
165 GlyphData glyphData = glyphDataForCharacter(charData, normalizeSpace);
166
167 // Some fonts do not have a glyph for zero-width-space,
168 // in that case use the space character and override the width.
169 float width;
170 bool spaceUsedAsZeroWidthSpace = false;
171 if (!glyphData.glyph &&
172 Character::treatAsZeroWidthSpace(charData.character)) {
173 charData.character = spaceCharacter;
174 glyphData = glyphDataForCharacter(charData);
175 width = 0;
176 spaceUsedAsZeroWidthSpace = true;
177 } else {
178 width = characterWidth(charData.character, glyphData);
179 }
180
181 Glyph glyph = glyphData.glyph;
182 const SimpleFontData* fontData = glyphData.fontData;
183 ASSERT(fontData);
184
185 if (m_fallbackFonts && lastFontData != fontData && width) {
186 lastFontData = fontData;
187 trackNonPrimaryFallbackFont(fontData);
188 }
189
190 if (hasExtraSpacing && !spaceUsedAsZeroWidthSpace)
191 width = adjustSpacing(width, charData);
192
193 if (m_glyphBoundingBox) {
194 ASSERT(glyphData.fontData);
195 FloatRect glyphBounds =
196 glyphData.fontData->boundsForGlyph(glyphData.glyph);
197 // We are handling simple text run here, so Y-Offset will be zero.
198 // FIXME: Computing bounds relative to the initial advance seems odd. Are
199 // we adjusting these someplace else? If not, we'll end up with different
200 // bounds depending on how we segment our advance() calls.
201 glyphBounds.move(m_runWidthSoFar - initialRunWidth, 0);
202 m_glyphBoundingBox->unite(glyphBounds);
203 }
204
205 if (glyphBuffer) {
206 if (!forTextEmphasis()) {
207 glyphBuffer->add(glyph, fontData, m_runWidthSoFar);
208 } else if (Character::canReceiveTextEmphasis(charData.character)) {
209 addEmphasisMark(glyphBuffer, m_runWidthSoFar + width / 2);
210 }
211 }
212
213 // Advance past the character we just dealt with.
214 textIterator.advance();
215 m_runWidthSoFar += width;
216 }
217
218 unsigned consumedCharacters = textIterator.offset() - m_currentCharacter;
219 m_currentCharacter = textIterator.offset();
220
221 return consumedCharacters;
222 }
223
224 unsigned SimpleShaper::advance(int offset, GlyphBuffer* glyphBuffer) {
225 int length = m_textRun.length();
226
227 if (offset > length)
228 offset = length;
229
230 if (m_currentCharacter >= static_cast<unsigned>(offset))
231 return 0;
232
233 if (m_textRun.is8Bit()) {
234 Latin1TextIterator textIterator(m_textRun.data8(m_currentCharacter),
235 m_currentCharacter, offset);
236 return advanceInternal(textIterator, glyphBuffer);
237 }
238
239 UTF16TextIterator textIterator(m_textRun.data16(m_currentCharacter),
240 m_currentCharacter, offset, length);
241 return advanceInternal(textIterator, glyphBuffer);
242 }
243
244 bool SimpleShaper::advanceOneCharacter(float& width) {
245 float initialWidth = m_runWidthSoFar;
246
247 if (!advance(m_currentCharacter + 1))
248 return false;
249
250 width = m_runWidthSoFar - initialWidth;
251 return true;
252 }
253
254 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.h ('k') | third_party/WebKit/Source/platform/text/Character.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698