| Index: Source/core/platform/graphics/opentype/OpenTypeVerticalData.cpp
|
| diff --git a/Source/core/platform/graphics/opentype/OpenTypeVerticalData.cpp b/Source/core/platform/graphics/opentype/OpenTypeVerticalData.cpp
|
| deleted file mode 100644
|
| index ef54999dcfa6e5e29cef3f007be2d07f815c01f8..0000000000000000000000000000000000000000
|
| --- a/Source/core/platform/graphics/opentype/OpenTypeVerticalData.cpp
|
| +++ /dev/null
|
| @@ -1,574 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com>
|
| - *
|
| - * Redistribution and use in source and binary forms, with or without
|
| - * modification, are permitted provided that the following conditions
|
| - * are met:
|
| - * 1. Redistributions of source code must retain the above copyright
|
| - * notice, this list of conditions and the following disclaimer.
|
| - * 2. Redistributions in binary form must reproduce the above copyright
|
| - * notice, this list of conditions and the following disclaimer in the
|
| - * documentation and/or other materials provided with the distribution.
|
| - *
|
| - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
|
| - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
| - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
| - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
| - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
| - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| - */
|
| -
|
| -#include "config.h"
|
| -#if ENABLE(OPENTYPE_VERTICAL)
|
| -#include "core/platform/graphics/opentype/OpenTypeVerticalData.h"
|
| -
|
| -#include "platform/SharedBuffer.h"
|
| -#include "core/platform/graphics/SimpleFontData.h"
|
| -#include "platform/fonts/GlyphPage.h"
|
| -#include "platform/fonts/opentype/OpenTypeTypes.h"
|
| -#include "platform/geometry/FloatRect.h"
|
| -#include "wtf/RefPtr.h"
|
| -
|
| -using namespace std;
|
| -
|
| -namespace WebCore {
|
| -namespace OpenType {
|
| -
|
| -const uint32_t GSUBTag = OT_MAKE_TAG('G', 'S', 'U', 'B');
|
| -const uint32_t HheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a');
|
| -const uint32_t HmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x');
|
| -const uint32_t VheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a');
|
| -const uint32_t VmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x');
|
| -const uint32_t VORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G');
|
| -
|
| -const uint32_t DefaultScriptTag = OT_MAKE_TAG('D', 'F', 'L', 'T');
|
| -
|
| -const uint32_t VertFeatureTag = OT_MAKE_TAG('v', 'e', 'r', 't');
|
| -
|
| -#pragma pack(1)
|
| -
|
| -struct HheaTable {
|
| - OpenType::Fixed version;
|
| - OpenType::Int16 ascender;
|
| - OpenType::Int16 descender;
|
| - OpenType::Int16 lineGap;
|
| - OpenType::Int16 advanceWidthMax;
|
| - OpenType::Int16 minLeftSideBearing;
|
| - OpenType::Int16 minRightSideBearing;
|
| - OpenType::Int16 xMaxExtent;
|
| - OpenType::Int16 caretSlopeRise;
|
| - OpenType::Int16 caretSlopeRun;
|
| - OpenType::Int16 caretOffset;
|
| - OpenType::Int16 reserved[4];
|
| - OpenType::Int16 metricDataFormat;
|
| - OpenType::UInt16 numberOfHMetrics;
|
| -};
|
| -
|
| -struct VheaTable {
|
| - OpenType::Fixed version;
|
| - OpenType::Int16 ascent;
|
| - OpenType::Int16 descent;
|
| - OpenType::Int16 lineGap;
|
| - OpenType::Int16 advanceHeightMax;
|
| - OpenType::Int16 minTopSideBearing;
|
| - OpenType::Int16 minBottomSideBearing;
|
| - OpenType::Int16 yMaxExtent;
|
| - OpenType::Int16 caretSlopeRise;
|
| - OpenType::Int16 caretSlopeRun;
|
| - OpenType::Int16 caretOffset;
|
| - OpenType::Int16 reserved[4];
|
| - OpenType::Int16 metricDataFormat;
|
| - OpenType::UInt16 numOfLongVerMetrics;
|
| -};
|
| -
|
| -struct HmtxTable {
|
| - struct Entry {
|
| - OpenType::UInt16 advanceWidth;
|
| - OpenType::Int16 lsb;
|
| - } entries[1];
|
| -};
|
| -
|
| -struct VmtxTable {
|
| - struct Entry {
|
| - OpenType::UInt16 advanceHeight;
|
| - OpenType::Int16 topSideBearing;
|
| - } entries[1];
|
| -};
|
| -
|
| -struct VORGTable {
|
| - OpenType::UInt16 majorVersion;
|
| - OpenType::UInt16 minorVersion;
|
| - OpenType::Int16 defaultVertOriginY;
|
| - OpenType::UInt16 numVertOriginYMetrics;
|
| - struct VertOriginYMetrics {
|
| - OpenType::UInt16 glyphIndex;
|
| - OpenType::Int16 vertOriginY;
|
| - } vertOriginYMetrics[1];
|
| -
|
| - size_t requiredSize() const { return sizeof(*this) + sizeof(VertOriginYMetrics) * (numVertOriginYMetrics - 1); }
|
| -};
|
| -
|
| -struct CoverageTable : TableBase {
|
| - OpenType::UInt16 coverageFormat;
|
| -};
|
| -
|
| -struct Coverage1Table : CoverageTable {
|
| - OpenType::UInt16 glyphCount;
|
| - OpenType::GlyphID glyphArray[1];
|
| -};
|
| -
|
| -struct Coverage2Table : CoverageTable {
|
| - OpenType::UInt16 rangeCount;
|
| - struct RangeRecord {
|
| - OpenType::GlyphID start;
|
| - OpenType::GlyphID end;
|
| - OpenType::UInt16 startCoverageIndex;
|
| - } ranges[1];
|
| -};
|
| -
|
| -struct SubstitutionSubTable : TableBase {
|
| - OpenType::UInt16 substFormat;
|
| - OpenType::Offset coverageOffset;
|
| -
|
| - const CoverageTable* coverage(const SharedBuffer& buffer) const { return validateOffset<CoverageTable>(buffer, coverageOffset); }
|
| -};
|
| -
|
| -struct SingleSubstitution2SubTable : SubstitutionSubTable {
|
| - OpenType::UInt16 glyphCount;
|
| - OpenType::GlyphID substitute[1];
|
| -};
|
| -
|
| -struct LookupTable : TableBase {
|
| - OpenType::UInt16 lookupType;
|
| - OpenType::UInt16 lookupFlag;
|
| - OpenType::UInt16 subTableCount;
|
| - OpenType::Offset subTableOffsets[1];
|
| - // OpenType::UInt16 markFilteringSet; this field comes after variable length, so offset is determined dynamically.
|
| -
|
| - bool getSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
|
| - {
|
| - uint16_t countSubTable = subTableCount;
|
| - if (!isValidEnd(buffer, &subTableOffsets[countSubTable]))
|
| - return false;
|
| - if (lookupType != 1) // "Single Substitution Subtable" is all what we support
|
| - return false;
|
| - for (uint16_t i = 0; i < countSubTable; ++i) {
|
| - const SubstitutionSubTable* substitution = validateOffset<SubstitutionSubTable>(buffer, subTableOffsets[i]);
|
| - if (!substitution)
|
| - return false;
|
| - const CoverageTable* coverage = substitution->coverage(buffer);
|
| - if (!coverage)
|
| - return false;
|
| - if (substitution->substFormat != 2) // "Single Substitution Format 2" is all what we support
|
| - return false;
|
| - const SingleSubstitution2SubTable* singleSubstitution2 = validatePtr<SingleSubstitution2SubTable>(buffer, substitution);
|
| - if (!singleSubstitution2)
|
| - return false;
|
| - uint16_t countTo = singleSubstitution2->glyphCount;
|
| - if (!isValidEnd(buffer, &singleSubstitution2->substitute[countTo]))
|
| - return false;
|
| - switch (coverage->coverageFormat) {
|
| - case 1: { // Coverage Format 1 (e.g., MS Gothic)
|
| - const Coverage1Table* coverage1 = validatePtr<Coverage1Table>(buffer, coverage);
|
| - if (!coverage1)
|
| - return false;
|
| - uint16_t countFrom = coverage1->glyphCount;
|
| - if (!isValidEnd(buffer, &coverage1->glyphArray[countFrom]) || countTo != countFrom)
|
| - return false;
|
| - for (uint16_t i = 0; i < countTo; ++i)
|
| - map->set(coverage1->glyphArray[i], singleSubstitution2->substitute[i]);
|
| - break;
|
| - }
|
| - case 2: { // Coverage Format 2 (e.g., Adobe Kozuka Gothic)
|
| - const Coverage2Table* coverage2 = validatePtr<Coverage2Table>(buffer, coverage);
|
| - if (!coverage2)
|
| - return false;
|
| - uint16_t countRange = coverage2->rangeCount;
|
| - if (!isValidEnd(buffer, &coverage2->ranges[countRange]))
|
| - return false;
|
| - for (uint16_t i = 0, indexTo = 0; i < countRange; ++i) {
|
| - uint16_t from = coverage2->ranges[i].start;
|
| - uint16_t fromEnd = coverage2->ranges[i].end + 1; // OpenType "end" is inclusive
|
| - if (indexTo + (fromEnd - from) > countTo)
|
| - return false;
|
| - for (; from != fromEnd; ++from, ++indexTo)
|
| - map->set(from, singleSubstitution2->substitute[indexTo]);
|
| - }
|
| - break;
|
| - }
|
| - default:
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| - }
|
| -};
|
| -
|
| -struct LookupList : TableBase {
|
| - OpenType::UInt16 lookupCount;
|
| - OpenType::Offset lookupOffsets[1];
|
| -
|
| - const LookupTable* lookup(uint16_t index, const SharedBuffer& buffer) const
|
| - {
|
| - uint16_t count = lookupCount;
|
| - if (index >= count || !isValidEnd(buffer, &lookupOffsets[count]))
|
| - return 0;
|
| - return validateOffset<LookupTable>(buffer, lookupOffsets[index]);
|
| - }
|
| -};
|
| -
|
| -struct FeatureTable : TableBase {
|
| - OpenType::Offset featureParams;
|
| - OpenType::UInt16 lookupCount;
|
| - OpenType::UInt16 lookupListIndex[1];
|
| -
|
| - bool getGlyphSubstitutions(const LookupList* lookups, HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
|
| - {
|
| - uint16_t count = lookupCount;
|
| - if (!isValidEnd(buffer, &lookupListIndex[count]))
|
| - return false;
|
| - for (uint16_t i = 0; i < count; ++i) {
|
| - const LookupTable* lookup = lookups->lookup(lookupListIndex[i], buffer);
|
| - if (!lookup || !lookup->getSubstitutions(map, buffer))
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -};
|
| -
|
| -struct FeatureList : TableBase {
|
| - OpenType::UInt16 featureCount;
|
| - struct FeatureRecord {
|
| - OpenType::Tag featureTag;
|
| - OpenType::Offset featureOffset;
|
| - } features[1];
|
| -
|
| - const FeatureTable* feature(uint16_t index, OpenType::Tag tag, const SharedBuffer& buffer) const
|
| - {
|
| - uint16_t count = featureCount;
|
| - if (index >= count || !isValidEnd(buffer, &features[count]))
|
| - return 0;
|
| - if (features[index].featureTag == tag)
|
| - return validateOffset<FeatureTable>(buffer, features[index].featureOffset);
|
| - return 0;
|
| - }
|
| -
|
| - const FeatureTable* findFeature(OpenType::Tag tag, const SharedBuffer& buffer) const
|
| - {
|
| - for (uint16_t i = 0; i < featureCount; ++i) {
|
| - if (isValidEnd(buffer, &features[i]) && features[i].featureTag == tag)
|
| - return validateOffset<FeatureTable>(buffer, features[i].featureOffset);
|
| - }
|
| - return 0;
|
| - }
|
| -};
|
| -
|
| -struct LangSysTable : TableBase {
|
| - OpenType::Offset lookupOrder;
|
| - OpenType::UInt16 reqFeatureIndex;
|
| - OpenType::UInt16 featureCount;
|
| - OpenType::UInt16 featureIndex[1];
|
| -
|
| - const FeatureTable* feature(OpenType::Tag featureTag, const FeatureList* features, const SharedBuffer& buffer) const
|
| - {
|
| - uint16_t count = featureCount;
|
| - if (!isValidEnd(buffer, &featureIndex[count]))
|
| - return 0;
|
| - for (uint16_t i = 0; i < count; ++i) {
|
| - const FeatureTable* featureTable = features->feature(featureIndex[i], featureTag, buffer);
|
| - if (featureTable)
|
| - return featureTable;
|
| - }
|
| - return 0;
|
| - }
|
| -};
|
| -
|
| -struct ScriptTable : TableBase {
|
| - OpenType::Offset defaultLangSysOffset;
|
| - OpenType::UInt16 langSysCount;
|
| - struct LangSysRecord {
|
| - OpenType::Tag langSysTag;
|
| - OpenType::Offset langSysOffset;
|
| - } langSysRecords[1];
|
| -
|
| - const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
|
| - {
|
| - uint16_t count = langSysCount;
|
| - if (!isValidEnd(buffer, &langSysRecords[count]))
|
| - return 0;
|
| - uint16_t offset = defaultLangSysOffset;
|
| - if (offset)
|
| - return validateOffset<LangSysTable>(buffer, offset);
|
| - if (count)
|
| - return validateOffset<LangSysTable>(buffer, langSysRecords[0].langSysOffset);
|
| - return 0;
|
| - }
|
| -};
|
| -
|
| -struct ScriptList : TableBase {
|
| - OpenType::UInt16 scriptCount;
|
| - struct ScriptRecord {
|
| - OpenType::Tag scriptTag;
|
| - OpenType::Offset scriptOffset;
|
| - } scripts[1];
|
| -
|
| - const ScriptTable* script(OpenType::Tag tag, const SharedBuffer& buffer) const
|
| - {
|
| - uint16_t count = scriptCount;
|
| - if (!isValidEnd(buffer, &scripts[count]))
|
| - return 0;
|
| - for (uint16_t i = 0; i < count; ++i) {
|
| - if (scripts[i].scriptTag == tag)
|
| - return validateOffset<ScriptTable>(buffer, scripts[i].scriptOffset);
|
| - }
|
| - return 0;
|
| - }
|
| -
|
| - const ScriptTable* defaultScript(const SharedBuffer& buffer) const
|
| - {
|
| - uint16_t count = scriptCount;
|
| - if (!count || !isValidEnd(buffer, &scripts[count]))
|
| - return 0;
|
| - const ScriptTable* scriptOfDefaultTag = script(OpenType::DefaultScriptTag, buffer);
|
| - if (scriptOfDefaultTag)
|
| - return scriptOfDefaultTag;
|
| - return validateOffset<ScriptTable>(buffer, scripts[0].scriptOffset);
|
| - }
|
| -
|
| - const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
|
| - {
|
| - const ScriptTable* scriptTable = defaultScript(buffer);
|
| - if (!scriptTable)
|
| - return 0;
|
| - return scriptTable->defaultLangSys(buffer);
|
| - }
|
| -};
|
| -
|
| -struct GSUBTable : TableBase {
|
| - OpenType::Fixed version;
|
| - OpenType::Offset scriptListOffset;
|
| - OpenType::Offset featureListOffset;
|
| - OpenType::Offset lookupListOffset;
|
| -
|
| - const ScriptList* scriptList(const SharedBuffer& buffer) const { return validateOffset<ScriptList>(buffer, scriptListOffset); }
|
| - const FeatureList* featureList(const SharedBuffer& buffer) const { return validateOffset<FeatureList>(buffer, featureListOffset); }
|
| - const LookupList* lookupList(const SharedBuffer& buffer) const { return validateOffset<LookupList>(buffer, lookupListOffset); }
|
| -
|
| - const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
|
| - {
|
| - const ScriptList* scripts = scriptList(buffer);
|
| - if (!scripts)
|
| - return 0;
|
| - return scripts->defaultLangSys(buffer);
|
| - }
|
| -
|
| - const FeatureTable* feature(OpenType::Tag featureTag, const SharedBuffer& buffer) const
|
| - {
|
| - const LangSysTable* langSys = defaultLangSys(buffer);
|
| - const FeatureList* features = featureList(buffer);
|
| - if (!features)
|
| - return 0;
|
| - const FeatureTable* feature = 0;
|
| - if (langSys)
|
| - feature = langSys->feature(featureTag, features, buffer);
|
| - if (!feature) {
|
| - // If the font has no langSys table, or has no default script and the first script doesn't
|
| - // have the requested feature, then use the first matching feature directly.
|
| - feature = features->findFeature(featureTag, buffer);
|
| - }
|
| - return feature;
|
| - }
|
| -
|
| - bool getVerticalGlyphSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
|
| - {
|
| - const FeatureTable* verticalFeatureTable = feature(OpenType::VertFeatureTag, buffer);
|
| - if (!verticalFeatureTable)
|
| - return false;
|
| - const LookupList* lookups = lookupList(buffer);
|
| - return lookups && verticalFeatureTable->getGlyphSubstitutions(lookups, map, buffer);
|
| - }
|
| -};
|
| -
|
| -#pragma pack()
|
| -
|
| -} // namespace OpenType
|
| -
|
| -OpenTypeVerticalData::OpenTypeVerticalData(const FontPlatformData& platformData)
|
| - : m_defaultVertOriginY(0)
|
| -{
|
| - loadMetrics(platformData);
|
| - loadVerticalGlyphSubstitutions(platformData);
|
| -}
|
| -
|
| -void OpenTypeVerticalData::loadMetrics(const FontPlatformData& platformData)
|
| -{
|
| - // Load hhea and hmtx to get x-component of vertical origins.
|
| - // If these tables are missing, it's not an OpenType font.
|
| - RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::HheaTag);
|
| - const OpenType::HheaTable* hhea = OpenType::validateTable<OpenType::HheaTable>(buffer);
|
| - if (!hhea)
|
| - return;
|
| - uint16_t countHmtxEntries = hhea->numberOfHMetrics;
|
| - if (!countHmtxEntries) {
|
| - WTF_LOG_ERROR("Invalid numberOfHMetrics");
|
| - return;
|
| - }
|
| -
|
| - buffer = platformData.openTypeTable(OpenType::HmtxTag);
|
| - const OpenType::HmtxTable* hmtx = OpenType::validateTable<OpenType::HmtxTable>(buffer, countHmtxEntries);
|
| - if (!hmtx) {
|
| - WTF_LOG_ERROR("hhea exists but hmtx does not (or broken)");
|
| - return;
|
| - }
|
| - m_advanceWidths.resize(countHmtxEntries);
|
| - for (uint16_t i = 0; i < countHmtxEntries; ++i)
|
| - m_advanceWidths[i] = hmtx->entries[i].advanceWidth;
|
| -
|
| - // Load vhea first. This table is required for fonts that support vertical flow.
|
| - buffer = platformData.openTypeTable(OpenType::VheaTag);
|
| - const OpenType::VheaTable* vhea = OpenType::validateTable<OpenType::VheaTable>(buffer);
|
| - if (!vhea)
|
| - return;
|
| - uint16_t countVmtxEntries = vhea->numOfLongVerMetrics;
|
| - if (!countVmtxEntries) {
|
| - WTF_LOG_ERROR("Invalid numOfLongVerMetrics");
|
| - return;
|
| - }
|
| -
|
| - // Load VORG. This table is optional.
|
| - buffer = platformData.openTypeTable(OpenType::VORGTag);
|
| - const OpenType::VORGTable* vorg = OpenType::validateTable<OpenType::VORGTable>(buffer);
|
| - if (vorg && buffer->size() >= vorg->requiredSize()) {
|
| - m_defaultVertOriginY = vorg->defaultVertOriginY;
|
| - uint16_t countVertOriginYMetrics = vorg->numVertOriginYMetrics;
|
| - if (!countVertOriginYMetrics) {
|
| - // Add one entry so that hasVORG() becomes true
|
| - m_vertOriginY.set(0, m_defaultVertOriginY);
|
| - } else {
|
| - for (uint16_t i = 0; i < countVertOriginYMetrics; ++i) {
|
| - const OpenType::VORGTable::VertOriginYMetrics& metrics = vorg->vertOriginYMetrics[i];
|
| - m_vertOriginY.set(metrics.glyphIndex, metrics.vertOriginY);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Load vmtx then. This table is required for fonts that support vertical flow.
|
| - buffer = platformData.openTypeTable(OpenType::VmtxTag);
|
| - const OpenType::VmtxTable* vmtx = OpenType::validateTable<OpenType::VmtxTable>(buffer, countVmtxEntries);
|
| - if (!vmtx) {
|
| - WTF_LOG_ERROR("vhea exists but vmtx does not (or broken)");
|
| - return;
|
| - }
|
| - m_advanceHeights.resize(countVmtxEntries);
|
| - for (uint16_t i = 0; i < countVmtxEntries; ++i)
|
| - m_advanceHeights[i] = vmtx->entries[i].advanceHeight;
|
| -
|
| - // VORG is preferred way to calculate vertical origin than vmtx,
|
| - // so load topSideBearing from vmtx only if VORG is missing.
|
| - if (hasVORG())
|
| - return;
|
| -
|
| - size_t sizeExtra = buffer->size() - sizeof(OpenType::VmtxTable::Entry) * countVmtxEntries;
|
| - if (sizeExtra % sizeof(OpenType::Int16)) {
|
| - WTF_LOG_ERROR("vmtx has incorrect tsb count");
|
| - return;
|
| - }
|
| - size_t countTopSideBearings = countVmtxEntries + sizeExtra / sizeof(OpenType::Int16);
|
| - m_topSideBearings.resize(countTopSideBearings);
|
| - size_t i;
|
| - for (i = 0; i < countVmtxEntries; ++i)
|
| - m_topSideBearings[i] = vmtx->entries[i].topSideBearing;
|
| - if (i < countTopSideBearings) {
|
| - const OpenType::Int16* pTopSideBearingsExtra = reinterpret_cast<const OpenType::Int16*>(&vmtx->entries[countVmtxEntries]);
|
| - for (; i < countTopSideBearings; ++i, ++pTopSideBearingsExtra)
|
| - m_topSideBearings[i] = *pTopSideBearingsExtra;
|
| - }
|
| -}
|
| -
|
| -void OpenTypeVerticalData::loadVerticalGlyphSubstitutions(const FontPlatformData& platformData)
|
| -{
|
| - RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::GSUBTag);
|
| - const OpenType::GSUBTable* gsub = OpenType::validateTable<OpenType::GSUBTable>(buffer);
|
| - if (gsub)
|
| - gsub->getVerticalGlyphSubstitutions(&m_verticalGlyphMap, *buffer.get());
|
| -}
|
| -
|
| -float OpenTypeVerticalData::advanceHeight(const SimpleFontData* font, Glyph glyph) const
|
| -{
|
| - size_t countHeights = m_advanceHeights.size();
|
| - if (countHeights) {
|
| - uint16_t advanceFUnit = m_advanceHeights[glyph < countHeights ? glyph : countHeights - 1];
|
| - float advance = advanceFUnit * font->sizePerUnit();
|
| - return advance;
|
| - }
|
| -
|
| - // No vertical info in the font file; use height as advance.
|
| - return font->fontMetrics().height();
|
| -}
|
| -
|
| -void OpenTypeVerticalData::getVerticalTranslationsForGlyphs(const SimpleFontData* font, const Glyph* glyphs, size_t count, float* outXYArray) const
|
| -{
|
| - size_t countWidths = m_advanceWidths.size();
|
| - ASSERT(countWidths > 0);
|
| - const FontMetrics& metrics = font->fontMetrics();
|
| - float sizePerUnit = font->sizePerUnit();
|
| - float ascent = metrics.ascent();
|
| - bool useVORG = hasVORG();
|
| - size_t countTopSideBearings = m_topSideBearings.size();
|
| - float defaultVertOriginY = std::numeric_limits<float>::quiet_NaN();
|
| - for (float* end = &(outXYArray[count * 2]); outXYArray != end; ++glyphs, outXYArray += 2) {
|
| - Glyph glyph = *glyphs;
|
| - uint16_t widthFUnit = m_advanceWidths[glyph < countWidths ? glyph : countWidths - 1];
|
| - float width = widthFUnit * sizePerUnit;
|
| - outXYArray[0] = -width / 2;
|
| -
|
| - // For Y, try VORG first.
|
| - if (useVORG) {
|
| - int16_t vertOriginYFUnit = m_vertOriginY.get(glyph);
|
| - if (vertOriginYFUnit) {
|
| - outXYArray[1] = -vertOriginYFUnit * sizePerUnit;
|
| - continue;
|
| - }
|
| - if (std::isnan(defaultVertOriginY))
|
| - defaultVertOriginY = -m_defaultVertOriginY * sizePerUnit;
|
| - outXYArray[1] = defaultVertOriginY;
|
| - continue;
|
| - }
|
| -
|
| - // If no VORG, try vmtx next.
|
| - if (countTopSideBearings) {
|
| - int16_t topSideBearingFUnit = m_topSideBearings[glyph < countTopSideBearings ? glyph : countTopSideBearings - 1];
|
| - float topSideBearing = topSideBearingFUnit * sizePerUnit;
|
| - FloatRect bounds = font->boundsForGlyph(glyph);
|
| - outXYArray[1] = bounds.y() - topSideBearing;
|
| - continue;
|
| - }
|
| -
|
| - // No vertical info in the font file; use ascent as vertical origin.
|
| - outXYArray[1] = -ascent;
|
| - }
|
| -}
|
| -
|
| -void OpenTypeVerticalData::substituteWithVerticalGlyphs(const SimpleFontData* font, GlyphPage* glyphPage, unsigned offset, unsigned length) const
|
| -{
|
| - const HashMap<Glyph, Glyph>& map = m_verticalGlyphMap;
|
| - if (map.isEmpty())
|
| - return;
|
| -
|
| - for (unsigned index = offset, end = offset + length; index < end; ++index) {
|
| - Glyph glyph = glyphPage->glyphAt(index);
|
| - if (glyph) {
|
| - ASSERT(glyphPage->glyphDataForIndex(index).fontData == font);
|
| - Glyph to = map.get(glyph);
|
| - if (to)
|
| - glyphPage->setGlyphDataForIndex(index, to, font);
|
| - }
|
| - }
|
| -}
|
| -
|
| -} // namespace WebCore
|
| -#endif // ENABLE(OPENTYPE_VERTICAL)
|
|
|