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

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

Issue 212863008: Merge SimpleFontData.cpp and SimpleFontDataSkia.cpp (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 2 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) 2005, 2008, 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2005, 2008, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Alexey Proskuryakov 3 * Copyright (C) 2006 Alexey Proskuryakov
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 12 matching lines...) Expand all
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30 #include "config.h" 30 #include "config.h"
31 #include "platform/fonts/SimpleFontData.h" 31 #include "platform/fonts/SimpleFontData.h"
32 32
33 #include "SkPaint.h"
34 #include "SkPath.h"
35 #include "SkTypeface.h"
36 #include "SkTypes.h"
37 #include "SkUtils.h"
38 #include "platform/fonts/FontDescription.h"
39 #include "platform/fonts/GlyphPage.h"
40 #include "platform/fonts/VDMXParser.h"
41 #include "platform/geometry/FloatRect.h"
33 #include "wtf/MathExtras.h" 42 #include "wtf/MathExtras.h"
43 #include "wtf/unicode/Unicode.h"
44 #include <unicode/normlzr.h>
34 45
35 namespace blink { 46 namespace blink {
36 47
37 const float smallCapsFontSizeMultiplier = 0.7f; 48 const float smallCapsFontSizeMultiplier = 0.7f;
38 const float emphasisMarkFontSizeMultiplier = 0.5f; 49 const float emphasisMarkFontSizeMultiplier = 0.5f;
39 50
51 #if OS(LINUX) || OS(ANDROID)
52 // This is the largest VDMX table which we'll try to load and parse.
53 static const size_t maxVDMXTableSize = 1024 * 1024; // 1 MB
54 #endif
55
40 SimpleFontData::SimpleFontData(const FontPlatformData& platformData, PassRefPtr< CustomFontData> customData, bool isTextOrientationFallback) 56 SimpleFontData::SimpleFontData(const FontPlatformData& platformData, PassRefPtr< CustomFontData> customData, bool isTextOrientationFallback)
41 : m_maxCharWidth(-1) 57 : m_maxCharWidth(-1)
42 , m_avgCharWidth(-1) 58 , m_avgCharWidth(-1)
43 , m_platformData(platformData) 59 , m_platformData(platformData)
44 , m_treatAsFixedPitch(false) 60 , m_treatAsFixedPitch(false)
45 , m_isTextOrientationFallback(isTextOrientationFallback) 61 , m_isTextOrientationFallback(isTextOrientationFallback)
46 , m_isBrokenIdeographFallback(false) 62 , m_isBrokenIdeographFallback(false)
47 #if ENABLE(OPENTYPE_VERTICAL) 63 #if ENABLE(OPENTYPE_VERTICAL)
48 , m_verticalData(nullptr) 64 , m_verticalData(nullptr)
49 #endif 65 #endif
50 , m_hasVerticalGlyphs(false) 66 , m_hasVerticalGlyphs(false)
51 , m_customFontData(customData) 67 , m_customFontData(customData)
52 { 68 {
53 platformInit(); 69 platformInit();
54 platformGlyphInit(); 70 platformGlyphInit();
55 platformCharWidthInit();
56 #if ENABLE(OPENTYPE_VERTICAL) 71 #if ENABLE(OPENTYPE_VERTICAL)
57 if (platformData.orientation() == Vertical && !isTextOrientationFallback) { 72 if (platformData.orientation() == Vertical && !isTextOrientationFallback) {
58 m_verticalData = platformData.verticalData(); 73 m_verticalData = platformData.verticalData();
59 m_hasVerticalGlyphs = m_verticalData.get() && m_verticalData->hasVertica lMetrics(); 74 m_hasVerticalGlyphs = m_verticalData.get() && m_verticalData->hasVertica lMetrics();
60 } 75 }
61 #endif 76 #endif
62 } 77 }
63 78
64 SimpleFontData::SimpleFontData(PassRefPtr<CustomFontData> customData, float font Size, bool syntheticBold, bool syntheticItalic) 79 SimpleFontData::SimpleFontData(PassRefPtr<CustomFontData> customData, float font Size, bool syntheticBold, bool syntheticItalic)
65 : m_platformData(FontPlatformData(fontSize, syntheticBold, syntheticItalic)) 80 : m_platformData(FontPlatformData(fontSize, syntheticBold, syntheticItalic))
66 , m_treatAsFixedPitch(false) 81 , m_treatAsFixedPitch(false)
67 , m_isTextOrientationFallback(false) 82 , m_isTextOrientationFallback(false)
68 , m_isBrokenIdeographFallback(false) 83 , m_isBrokenIdeographFallback(false)
69 #if ENABLE(OPENTYPE_VERTICAL) 84 #if ENABLE(OPENTYPE_VERTICAL)
70 , m_verticalData(nullptr) 85 , m_verticalData(nullptr)
71 #endif 86 #endif
72 , m_hasVerticalGlyphs(false) 87 , m_hasVerticalGlyphs(false)
73 , m_customFontData(customData) 88 , m_customFontData(customData)
74 { 89 {
75 if (m_customFontData) 90 if (m_customFontData)
76 m_customFontData->initializeFontData(this, fontSize); 91 m_customFontData->initializeFontData(this, fontSize);
77 } 92 }
78 93
94 void SimpleFontData::platformInit()
95 {
96 if (!m_platformData.size()) {
97 m_fontMetrics.reset();
98 m_avgCharWidth = 0;
99 m_maxCharWidth = 0;
100 return;
101 }
102
103 SkPaint paint;
104 SkPaint::FontMetrics metrics;
105
106 m_platformData.setupPaint(&paint);
107 paint.getFontMetrics(&metrics);
108 SkTypeface* face = paint.getTypeface();
109 ASSERT(face);
110
111 int vdmxAscent = 0, vdmxDescent = 0;
112 bool isVDMXValid = false;
113
114 #if OS(LINUX) || OS(ANDROID)
115 // Manually digging up VDMX metrics is only applicable when bytecode hinting using FreeType.
116 // With GDI, the metrics will already have taken this into account (as neede d).
117 // With DirectWrite or CoreText, no bytecode hinting is ever done.
118 // This code should be pushed into FreeType (hinted font metrics).
119 static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
120 int pixelSize = m_platformData.size() + 0.5;
121 if (!paint.isAutohinted()
122 && (paint.getHinting() == SkPaint::kFull_Hinting
123 || paint.getHinting() == SkPaint::kNormal_Hinting))
124 {
125 size_t vdmxSize = face->getTableSize(vdmxTag);
126 if (vdmxSize && vdmxSize < maxVDMXTableSize) {
127 uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
128 if (vdmxTable
129 && face->getTableData(vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSi ze
130 && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pix elSize))
131 isVDMXValid = true;
132 fastFree(vdmxTable);
133 }
134 }
135 #endif
136
137 float ascent;
138 float descent;
139
140 // Beware those who step here: This code is designed to match Win32 font
141 // metrics *exactly* (except the adjustment of ascent/descent on Linux/Andro id).
142 if (isVDMXValid) {
143 ascent = vdmxAscent;
144 descent = -vdmxDescent;
145 } else {
146 ascent = SkScalarRoundToInt(-metrics.fAscent);
147 descent = SkScalarRoundToInt(metrics.fDescent);
148 #if OS(LINUX) || OS(ANDROID)
149 // When subpixel positioning is enabled, if the descent is rounded down, the descent part
150 // of the glyph may be truncated when displayed in a 'overflow: hidden' container.
151 // To avoid that, borrow 1 unit from the ascent when possible.
152 // FIXME: This can be removed if sub-pixel ascent/descent is supported.
153 if (platformData().fontRenderStyle().useSubpixelPositioning && descent < SkScalarToFloat(metrics.fDescent) && ascent >= 1) {
154 ++descent;
155 --ascent;
156 }
157 #endif
158 }
159
160 m_fontMetrics.setAscent(ascent);
161 m_fontMetrics.setDescent(descent);
162
163 float xHeight;
164 if (metrics.fXHeight) {
165 xHeight = metrics.fXHeight;
166 m_fontMetrics.setXHeight(xHeight);
167 } else {
168 xHeight = ascent * 0.56; // Best guess from Windows font metrics.
169 m_fontMetrics.setXHeight(xHeight);
170 m_fontMetrics.setHasXHeight(false);
171 }
172
173 float lineGap = SkScalarToFloat(metrics.fLeading);
174 m_fontMetrics.setLineGap(lineGap);
175 m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(li neGap));
176
177 if (platformData().orientation() == Vertical && !isTextOrientationFallback() ) {
178 static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
179 static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
180 size_t vheaSize = face->getTableSize(vheaTag);
181 size_t vorgSize = face->getTableSize(vorgTag);
182 if ((vheaSize > 0) || (vorgSize > 0))
183 m_hasVerticalGlyphs = true;
184 }
185
186 // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
187 // calculated for us, but we need to calculate m_maxCharWidth and
188 // m_avgCharWidth in order for text entry widgets to be sized correctly.
189 #if OS(WIN)
190 m_maxCharWidth = SkScalarRoundToInt(metrics.fMaxCharWidth);
191
192 // Older version of the DirectWrite API doesn't implement support for max
193 // char width. Fall back on a multiple of the ascent. This is entirely
194 // arbitrary but comes pretty close to the expected value in most cases.
195 if (m_maxCharWidth < 1)
196 m_maxCharWidth = ascent * 2;
197 #else
198 // FIXME: This seems incorrect and should probably use fMaxCharWidth as
199 // the code path above.
200 SkScalar xRange = metrics.fXMax - metrics.fXMin;
201 m_maxCharWidth = SkScalarRoundToInt(xRange * SkScalarRoundToInt(m_platformDa ta.size()));
202 #endif
203
204 if (metrics.fAvgCharWidth) {
205 m_avgCharWidth = SkScalarRoundToInt(metrics.fAvgCharWidth);
206 } else {
207 m_avgCharWidth = xHeight;
208
209 GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->pag e();
210
211 if (glyphPageZero) {
212 static const UChar32 xChar = 'x';
213 const Glyph xGlyph = glyphPageZero->glyphForCharacter(xChar);
214
215 if (xGlyph) {
216 // In widthForGlyph(), xGlyph will be compared with
217 // m_zeroWidthSpaceGlyph, which isn't initialized yet here.
218 // Initialize it with zero to make sure widthForGlyph() returns
219 // the right width.
220 m_zeroWidthSpaceGlyph = 0;
221 m_avgCharWidth = widthForGlyph(xGlyph);
222 }
223 }
224 }
225
226 if (int unitsPerEm = face->getUnitsPerEm())
227 m_fontMetrics.setUnitsPerEm(unitsPerEm);
228 }
229
79 void SimpleFontData::platformGlyphInit() 230 void SimpleFontData::platformGlyphInit()
80 { 231 {
81 GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page(); 232 GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
82 if (!glyphPageZero) { 233 if (!glyphPageZero) {
83 m_spaceGlyph = 0; 234 m_spaceGlyph = 0;
84 m_spaceWidth = 0; 235 m_spaceWidth = 0;
85 m_zeroGlyph = 0; 236 m_zeroGlyph = 0;
86 determinePitch(); 237 determinePitch();
87 m_zeroWidthSpaceGlyph = 0; 238 m_zeroWidthSpaceGlyph = 0;
88 m_missingGlyphData.fontData = this; 239 m_missingGlyphData.fontData = this;
(...skipping 22 matching lines...) Expand all
111 m_zeroWidthSpaceGlyph = 0; 262 m_zeroWidthSpaceGlyph = 0;
112 WTF_LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. G lyph width will not be overridden."); 263 WTF_LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. G lyph width will not be overridden.");
113 } 264 }
114 265
115 m_missingGlyphData.fontData = this; 266 m_missingGlyphData.fontData = this;
116 m_missingGlyphData.glyph = 0; 267 m_missingGlyphData.glyph = 0;
117 } 268 }
118 269
119 SimpleFontData::~SimpleFontData() 270 SimpleFontData::~SimpleFontData()
120 { 271 {
121 if (!isSVGFont())
122 platformDestroy();
123
124 if (isCustomFont()) 272 if (isCustomFont())
125 GlyphPageTreeNode::pruneTreeCustomFontData(this); 273 GlyphPageTreeNode::pruneTreeCustomFontData(this);
126 else 274 else
127 GlyphPageTreeNode::pruneTreeFontData(this); 275 GlyphPageTreeNode::pruneTreeFontData(this);
128 } 276 }
129 277
130 const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const 278 const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
131 { 279 {
132 return this; 280 return this;
133 } 281 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 368
221 PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri ption& fontDescription, float scaleFactor) const 369 PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri ption& fontDescription, float scaleFactor) const
222 { 370 {
223 // FIXME: Support scaled SVG fonts. Given that SVG is scalable in general th is should be achievable. 371 // FIXME: Support scaled SVG fonts. Given that SVG is scalable in general th is should be achievable.
224 if (isSVGFont()) 372 if (isSVGFont())
225 return nullptr; 373 return nullptr;
226 374
227 return platformCreateScaledFontData(fontDescription, scaleFactor); 375 return platformCreateScaledFontData(fontDescription, scaleFactor);
228 } 376 }
229 377
378
379
380 PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const Fo ntDescription& fontDescription, float scaleFactor) const
381 {
382 const float scaledSize = lroundf(fontDescription.computedSize() * scaleFacto r);
383 return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont() ? CustomFontData::create() : nullptr);
384 }
385
386 void SimpleFontData::determinePitch()
387 {
388 m_treatAsFixedPitch = platformData().isFixedPitch();
389 }
390
391 static inline void getSkiaBoundsForGlyph(SkPaint& paint, Glyph glyph, SkRect& bo unds)
392 {
393 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
394
395 SkPath path;
396 paint.getTextPath(&glyph, sizeof(glyph), 0, 0, &path);
397 bounds = path.getBounds();
398
399 if (!paint.isSubpixelText()) {
400 SkIRect ir;
401 bounds.round(&ir);
402 bounds.set(ir);
403 }
404 }
405
406 FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
407 {
408 if (!m_platformData.size())
409 return FloatRect();
410
411 SkASSERT(sizeof(glyph) == 2); // compile-time assert
412
413 SkPaint paint;
414 m_platformData.setupPaint(&paint);
415
416 SkRect bounds;
417 getSkiaBoundsForGlyph(paint, glyph, bounds);
418 return FloatRect(bounds);
419 }
420
421 float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
422 {
423 if (!m_platformData.size())
424 return 0;
425
426 SkASSERT(sizeof(glyph) == 2); // compile-time assert
427
428 SkPaint paint;
429
430 m_platformData.setupPaint(&paint);
431
432 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
433 SkScalar width = paint.measureText(&glyph, 2);
434 if (!paint.isSubpixelText())
435 width = SkScalarRoundToInt(width);
436 return SkScalarToFloat(width);
437 }
438
439 bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters , size_t length) const
440 {
441 if (!m_combiningCharacterSequenceSupport)
442 m_combiningCharacterSequenceSupport = adoptPtr(new HashMap<String, bool> );
443
444 WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequen ceSupport->add(String(characters, length), false);
445 if (!addResult.isNewEntry)
446 return addResult.storedValue->value;
447
448 UErrorCode error = U_ZERO_ERROR;
449 Vector<UChar, 4> normalizedCharacters(length);
450 int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UN ORM_UNICODE_3_2, &normalizedCharacters[0], length, &error);
451 // Can't render if we have an error or no composition occurred.
452 if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length))
453 return false;
454
455 SkPaint paint;
456 m_platformData.setupPaint(&paint);
457 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
458 if (paint.textToGlyphs(&normalizedCharacters[0], normalizedLength * 2, 0)) {
459 addResult.storedValue->value = true;
460 return true;
461 }
462 return false;
463 }
464
465 bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsig ned length, UChar* buffer, unsigned bufferLength) const
466 {
467 if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
468 SkDebugf("%s last char is high-surrogate", __FUNCTION__);
469 return false;
470 }
471
472 SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length);
473
474 uint16_t* glyphs = glyphStorage.get();
475 SkTypeface* typeface = platformData().typeface();
476 typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length) ;
477
478 bool haveGlyphs = false;
479 for (unsigned i = 0; i < length; i++) {
480 if (glyphs[i]) {
481 pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
482 haveGlyphs = true;
483 }
484 }
485
486 return haveGlyphs;
487 }
488
230 } // namespace blink 489 } // namespace blink
OLDNEW
« no previous file with comments | « Source/platform/fonts/SimpleFontData.h ('k') | Source/platform/fonts/skia/SimpleFontDataSkia.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698