Skip to content

Commit c705428

Browse files
committed
Merge SimpleFontData.cpp and SimpleFontDataSkia.cpp
SimpleFontData.cpp and SimpleFontDataSkia.cpp are now both built on all platforms thus the separation no longer makes sense. Merge the two into SimpleFontData.cpp BUG=356808 [email protected] Review URL: https://codereview.chromium.org/212863008 git-svn-id: svn://svn.chromium.org/blink/trunk@183163 bbb929c8-8fbe-4397-9dbb-9b2b20218538
1 parent 024bd87 commit c705428

File tree

5 files changed

+263
-318
lines changed

5 files changed

+263
-318
lines changed

Source/platform/blink_platform.gyp

-4
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,6 @@
253253
# Cherry-pick files excluded by the broader regular expressions above.
254254
['include', 'fonts/opentype/OpenTypeTypes\\.h$'],
255255
['include', 'fonts/opentype/OpenTypeVerticalData\\.(cpp|h)$'],
256-
['include', 'fonts/skia/SimpleFontDataSkia\\.cpp$'],
257256
],
258257
'dependencies': [
259258
'<(DEPTH)/third_party/harfbuzz-ng/harfbuzz.gyp:harfbuzz-ng',
@@ -327,8 +326,6 @@
327326

328327
['exclude', 'fonts/skia/FontCacheSkia\\.cpp$'],
329328

330-
['include', 'fonts/skia/SimpleFontDataSkia\\.cpp$'],
331-
332329
['include', 'geometry/mac/FloatPointMac\\.mm$'],
333330
['include', 'geometry/mac/FloatRectMac\\.mm$'],
334331
['include', 'geometry/mac/FloatSizeMac\\.mm$'],
@@ -369,7 +366,6 @@
369366
['include', 'fonts/opentype/'],
370367
['include', 'fonts/skia/FontCustomPlatformDataSkia\\.cpp$'],
371368
['include', 'fonts/skia/FontCustomPlatformDataSkia\\.cpp$'],
372-
['include', 'fonts/skia/SimpleFontDataSkia\\.cpp$'],
373369
['include', 'fonts/win/FontCacheSkiaWin\\.cpp$'],
374370
['include', 'fonts/win/FontFallbackWin\\.(cpp|h)$'],
375371
['include', 'fonts/win/FontPlatformDataWin\\.cpp$'],

Source/platform/blink_platform.gypi

-1
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,6 @@
408408
'fonts/skia/FontCacheSkia.cpp',
409409
'fonts/skia/FontCustomPlatformDataSkia.cpp',
410410
'fonts/skia/FontPlatformDataSkia.cpp',
411-
'fonts/skia/SimpleFontDataSkia.cpp',
412411
'fonts/win/FontCacheSkiaWin.cpp',
413412
'fonts/win/FontFallbackWin.cpp',
414413
'fonts/win/FontFallbackWin.h',

Source/platform/fonts/SimpleFontData.cpp

+263-4
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,29 @@
3030
#include "config.h"
3131
#include "platform/fonts/SimpleFontData.h"
3232

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"
3342
#include "wtf/MathExtras.h"
43+
#include "wtf/unicode/Unicode.h"
44+
#include <unicode/normlzr.h>
3445

3546
namespace blink {
3647

3748
const float smallCapsFontSizeMultiplier = 0.7f;
3849
const float emphasisMarkFontSizeMultiplier = 0.5f;
3950

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+
4056
SimpleFontData::SimpleFontData(const FontPlatformData& platformData, PassRefPtr<CustomFontData> customData, bool isTextOrientationFallback)
4157
: m_maxCharWidth(-1)
4258
, m_avgCharWidth(-1)
@@ -52,7 +68,6 @@ SimpleFontData::SimpleFontData(const FontPlatformData& platformData, PassRefPtr<
5268
{
5369
platformInit();
5470
platformGlyphInit();
55-
platformCharWidthInit();
5671
#if ENABLE(OPENTYPE_VERTICAL)
5772
if (platformData.orientation() == Vertical && !isTextOrientationFallback) {
5873
m_verticalData = platformData.verticalData();
@@ -76,6 +91,142 @@ SimpleFontData::SimpleFontData(PassRefPtr<CustomFontData> customData, float font
7691
m_customFontData->initializeFontData(this, fontSize);
7792
}
7893

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 needed).
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) == vdmxSize
130+
&& parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
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/Android).
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(lineGap));
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_platformData.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)->page();
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+
79230
void SimpleFontData::platformGlyphInit()
80231
{
81232
GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
@@ -118,9 +269,6 @@ void SimpleFontData::platformGlyphInit()
118269

119270
SimpleFontData::~SimpleFontData()
120271
{
121-
if (!isSVGFont())
122-
platformDestroy();
123-
124272
if (isCustomFont())
125273
GlyphPageTreeNode::pruneTreeCustomFontData(this);
126274
else
@@ -227,4 +375,115 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri
227375
return platformCreateScaledFontData(fontDescription, scaleFactor);
228376
}
229377

378+
379+
380+
PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
381+
{
382+
const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor);
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& bounds)
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_combiningCharacterSequenceSupport->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, UNORM_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, unsigned 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+
230489
} // namespace blink

Source/platform/fonts/SimpleFontData.h

-2
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,6 @@ class PLATFORM_EXPORT SimpleFontData : public FontData {
160160
private:
161161
void platformInit();
162162
void platformGlyphInit();
163-
void platformCharWidthInit();
164-
void platformDestroy();
165163

166164
PassRefPtr<SimpleFontData> createScaledFontData(const FontDescription&, float scaleFactor) const;
167165
PassRefPtr<SimpleFontData> platformCreateScaledFontData(const FontDescription&, float scaleFactor) const;

0 commit comments

Comments
 (0)