15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1.  Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2.  Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if ENABLE(OPENTYPE_VERTICAL)
27a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/fonts/opentype/OpenTypeVerticalData.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/SharedBuffer.h"
30a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/fonts/SimpleFontData.h"
3119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#include "platform/fonts/GlyphPage.h"
3251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/fonts/opentype/OpenTypeTypes.h"
331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatRect.h"
347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/RefPtr.h"
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace OpenType {
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const uint32_t GSUBTag = OT_MAKE_TAG('G', 'S', 'U', 'B');
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const uint32_t HheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a');
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const uint32_t HmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x');
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const uint32_t VheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a');
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const uint32_t VmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x');
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const uint32_t VORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G');
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const uint32_t DefaultScriptTag = OT_MAKE_TAG('D', 'F', 'L', 'T');
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const uint32_t VertFeatureTag = OT_MAKE_TAG('v', 'e', 'r', 't');
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#pragma pack(1)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct HheaTable {
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Fixed version;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 ascender;
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 descender;
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 lineGap;
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 advanceWidthMax;
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 minLeftSideBearing;
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 minRightSideBearing;
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 xMaxExtent;
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 caretSlopeRise;
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 caretSlopeRun;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 caretOffset;
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 reserved[4];
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 metricDataFormat;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 numberOfHMetrics;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct VheaTable {
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Fixed version;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 ascent;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 descent;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 lineGap;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 advanceHeightMax;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 minTopSideBearing;
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 minBottomSideBearing;
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 yMaxExtent;
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 caretSlopeRise;
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 caretSlopeRun;
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 caretOffset;
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 reserved[4];
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 metricDataFormat;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 numOfLongVerMetrics;
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct HmtxTable {
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    struct Entry {
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::UInt16 advanceWidth;
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::Int16 lsb;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } entries[1];
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct VmtxTable {
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    struct Entry {
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::UInt16 advanceHeight;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::Int16 topSideBearing;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } entries[1];
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct VORGTable {
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 majorVersion;
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 minorVersion;
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Int16 defaultVertOriginY;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 numVertOriginYMetrics;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    struct VertOriginYMetrics {
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::UInt16 glyphIndex;
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::Int16 vertOriginY;
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } vertOriginYMetrics[1];
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t requiredSize() const { return sizeof(*this) + sizeof(VertOriginYMetrics) * (numVertOriginYMetrics - 1); }
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct CoverageTable : TableBase {
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 coverageFormat;
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct Coverage1Table : CoverageTable {
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 glyphCount;
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::GlyphID glyphArray[1];
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct Coverage2Table : CoverageTable {
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 rangeCount;
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    struct RangeRecord {
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::GlyphID start;
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::GlyphID end;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::UInt16 startCoverageIndex;
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } ranges[1];
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct SubstitutionSubTable : TableBase {
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 substFormat;
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Offset coverageOffset;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CoverageTable* coverage(const SharedBuffer& buffer) const { return validateOffset<CoverageTable>(buffer, coverageOffset); }
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct SingleSubstitution2SubTable : SubstitutionSubTable {
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 glyphCount;
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::GlyphID substitute[1];
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct LookupTable : TableBase {
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 lookupType;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 lookupFlag;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 subTableCount;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Offset subTableOffsets[1];
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // OpenType::UInt16 markFilteringSet; this field comes after variable length, so offset is determined dynamically.
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool getSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t countSubTable = subTableCount;
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!isValidEnd(buffer, &subTableOffsets[countSubTable]))
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (lookupType != 1) // "Single Substitution Subtable" is all what we support
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (uint16_t i = 0; i < countSubTable; ++i) {
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const SubstitutionSubTable* substitution = validateOffset<SubstitutionSubTable>(buffer, subTableOffsets[i]);
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!substitution)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const CoverageTable* coverage = substitution->coverage(buffer);
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!coverage)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (substitution->substFormat != 2) // "Single Substitution Format 2" is all what we support
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const SingleSubstitution2SubTable* singleSubstitution2 = validatePtr<SingleSubstitution2SubTable>(buffer, substitution);
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!singleSubstitution2)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint16_t countTo = singleSubstitution2->glyphCount;
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!isValidEnd(buffer, &singleSubstitution2->substitute[countTo]))
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            switch (coverage->coverageFormat) {
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            case 1: { // Coverage Format 1 (e.g., MS Gothic)
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                const Coverage1Table* coverage1 = validatePtr<Coverage1Table>(buffer, coverage);
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!coverage1)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return false;
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                uint16_t countFrom = coverage1->glyphCount;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!isValidEnd(buffer, &coverage1->glyphArray[countFrom]) || countTo != countFrom)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return false;
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (uint16_t i = 0; i < countTo; ++i)
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    map->set(coverage1->glyphArray[i], singleSubstitution2->substitute[i]);
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            case 2: { // Coverage Format 2 (e.g., Adobe Kozuka Gothic)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                const Coverage2Table* coverage2 = validatePtr<Coverage2Table>(buffer, coverage);
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!coverage2)
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return false;
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                uint16_t countRange = coverage2->rangeCount;
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!isValidEnd(buffer, &coverage2->ranges[countRange]))
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return false;
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (uint16_t i = 0, indexTo = 0; i < countRange; ++i) {
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    uint16_t from = coverage2->ranges[i].start;
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    uint16_t fromEnd = coverage2->ranges[i].end + 1; // OpenType "end" is inclusive
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (indexTo + (fromEnd - from) > countTo)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return false;
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    for (; from != fromEnd; ++from, ++indexTo)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        map->set(from, singleSubstitution2->substitute[indexTo]);
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            default:
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct LookupList : TableBase {
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 lookupCount;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Offset lookupOffsets[1];
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const LookupTable* lookup(uint16_t index, const SharedBuffer& buffer) const
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t count = lookupCount;
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (index >= count || !isValidEnd(buffer, &lookupOffsets[count]))
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return validateOffset<LookupTable>(buffer, lookupOffsets[index]);
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct FeatureTable : TableBase {
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Offset featureParams;
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 lookupCount;
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 lookupListIndex[1];
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool getGlyphSubstitutions(const LookupList* lookups, HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t count = lookupCount;
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!isValidEnd(buffer, &lookupListIndex[count]))
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (uint16_t i = 0; i < count; ++i) {
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const LookupTable* lookup = lookups->lookup(lookupListIndex[i], buffer);
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!lookup || !lookup->getSubstitutions(map, buffer))
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct FeatureList : TableBase {
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 featureCount;
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    struct FeatureRecord {
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::Tag featureTag;
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::Offset featureOffset;
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } features[1];
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const FeatureTable* feature(uint16_t index, OpenType::Tag tag, const SharedBuffer& buffer) const
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t count = featureCount;
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (index >= count || !isValidEnd(buffer, &features[count]))
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (features[index].featureTag == tag)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return validateOffset<FeatureTable>(buffer, features[index].featureOffset);
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const FeatureTable* findFeature(OpenType::Tag tag, const SharedBuffer& buffer) const
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (uint16_t i = 0; i < featureCount; ++i) {
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (isValidEnd(buffer, &features[i]) && features[i].featureTag == tag)
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return validateOffset<FeatureTable>(buffer, features[i].featureOffset);
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct LangSysTable : TableBase {
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Offset lookupOrder;
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 reqFeatureIndex;
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 featureCount;
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 featureIndex[1];
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const FeatureTable* feature(OpenType::Tag featureTag, const FeatureList* features, const SharedBuffer& buffer) const
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t count = featureCount;
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!isValidEnd(buffer, &featureIndex[count]))
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (uint16_t i = 0; i < count; ++i) {
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const FeatureTable* featureTable = features->feature(featureIndex[i], featureTag, buffer);
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (featureTable)
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return featureTable;
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct ScriptTable : TableBase {
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Offset defaultLangSysOffset;
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 langSysCount;
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    struct LangSysRecord {
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::Tag langSysTag;
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::Offset langSysOffset;
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } langSysRecords[1];
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t count = langSysCount;
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!isValidEnd(buffer, &langSysRecords[count]))
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t offset = defaultLangSysOffset;
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (offset)
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return validateOffset<LangSysTable>(buffer, offset);
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (count)
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return validateOffset<LangSysTable>(buffer, langSysRecords[0].langSysOffset);
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct ScriptList : TableBase {
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::UInt16 scriptCount;
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    struct ScriptRecord {
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::Tag scriptTag;
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OpenType::Offset scriptOffset;
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } scripts[1];
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const ScriptTable* script(OpenType::Tag tag, const SharedBuffer& buffer) const
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t count = scriptCount;
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!isValidEnd(buffer, &scripts[count]))
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (uint16_t i = 0; i < count; ++i) {
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (scripts[i].scriptTag == tag)
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return validateOffset<ScriptTable>(buffer, scripts[i].scriptOffset);
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const ScriptTable* defaultScript(const SharedBuffer& buffer) const
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t count = scriptCount;
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!count || !isValidEnd(buffer, &scripts[count]))
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const ScriptTable* scriptOfDefaultTag = script(OpenType::DefaultScriptTag, buffer);
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (scriptOfDefaultTag)
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return scriptOfDefaultTag;
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return validateOffset<ScriptTable>(buffer, scripts[0].scriptOffset);
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const ScriptTable* scriptTable = defaultScript(buffer);
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!scriptTable)
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return scriptTable->defaultLangSys(buffer);
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct GSUBTable : TableBase {
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Fixed version;
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Offset scriptListOffset;
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Offset featureListOffset;
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OpenType::Offset lookupListOffset;
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const ScriptList* scriptList(const SharedBuffer& buffer) const { return validateOffset<ScriptList>(buffer, scriptListOffset); }
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const FeatureList* featureList(const SharedBuffer& buffer) const { return validateOffset<FeatureList>(buffer, featureListOffset); }
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const LookupList* lookupList(const SharedBuffer& buffer) const { return validateOffset<LookupList>(buffer, lookupListOffset); }
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const ScriptList* scripts = scriptList(buffer);
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!scripts)
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return scripts->defaultLangSys(buffer);
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const FeatureTable* feature(OpenType::Tag featureTag, const SharedBuffer& buffer) const
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const LangSysTable* langSys = defaultLangSys(buffer);
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const FeatureList* features = featureList(buffer);
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!features)
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const FeatureTable* feature = 0;
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (langSys)
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            feature = langSys->feature(featureTag, features, buffer);
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!feature) {
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // If the font has no langSys table, or has no default script and the first script doesn't
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // have the requested feature, then use the first matching feature directly.
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            feature = features->findFeature(featureTag, buffer);
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return feature;
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool getVerticalGlyphSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const FeatureTable* verticalFeatureTable = feature(OpenType::VertFeatureTag, buffer);
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!verticalFeatureTable)
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const LookupList* lookups = lookupList(buffer);
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return lookups && verticalFeatureTable->getGlyphSubstitutions(lookups, map, buffer);
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#pragma pack()
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace OpenType
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)OpenTypeVerticalData::OpenTypeVerticalData(const FontPlatformData& platformData)
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_defaultVertOriginY(0)
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadMetrics(platformData);
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadVerticalGlyphSubstitutions(platformData);
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void OpenTypeVerticalData::loadMetrics(const FontPlatformData& platformData)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Load hhea and hmtx to get x-component of vertical origins.
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If these tables are missing, it's not an OpenType font.
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::HheaTag);
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const OpenType::HheaTable* hhea = OpenType::validateTable<OpenType::HheaTable>(buffer);
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hhea)
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint16_t countHmtxEntries = hhea->numberOfHMetrics;
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!countHmtxEntries) {
415a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("Invalid numberOfHMetrics");
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    buffer = platformData.openTypeTable(OpenType::HmtxTag);
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const OpenType::HmtxTable* hmtx = OpenType::validateTable<OpenType::HmtxTable>(buffer, countHmtxEntries);
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hmtx) {
422a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("hhea exists but hmtx does not (or broken)");
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_advanceWidths.resize(countHmtxEntries);
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (uint16_t i = 0; i < countHmtxEntries; ++i)
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_advanceWidths[i] = hmtx->entries[i].advanceWidth;
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Load vhea first. This table is required for fonts that support vertical flow.
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    buffer = platformData.openTypeTable(OpenType::VheaTag);
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const OpenType::VheaTable* vhea = OpenType::validateTable<OpenType::VheaTable>(buffer);
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!vhea)
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint16_t countVmtxEntries = vhea->numOfLongVerMetrics;
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!countVmtxEntries) {
436a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("Invalid numOfLongVerMetrics");
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Load VORG. This table is optional.
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    buffer = platformData.openTypeTable(OpenType::VORGTag);
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const OpenType::VORGTable* vorg = OpenType::validateTable<OpenType::VORGTable>(buffer);
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (vorg && buffer->size() >= vorg->requiredSize()) {
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_defaultVertOriginY = vorg->defaultVertOriginY;
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t countVertOriginYMetrics = vorg->numVertOriginYMetrics;
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!countVertOriginYMetrics) {
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Add one entry so that hasVORG() becomes true
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_vertOriginY.set(0, m_defaultVertOriginY);
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (uint16_t i = 0; i < countVertOriginYMetrics; ++i) {
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                const OpenType::VORGTable::VertOriginYMetrics& metrics = vorg->vertOriginYMetrics[i];
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_vertOriginY.set(metrics.glyphIndex, metrics.vertOriginY);
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Load vmtx then. This table is required for fonts that support vertical flow.
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    buffer = platformData.openTypeTable(OpenType::VmtxTag);
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const OpenType::VmtxTable* vmtx = OpenType::validateTable<OpenType::VmtxTable>(buffer, countVmtxEntries);
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!vmtx) {
461a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("vhea exists but vmtx does not (or broken)");
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_advanceHeights.resize(countVmtxEntries);
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (uint16_t i = 0; i < countVmtxEntries; ++i)
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_advanceHeights[i] = vmtx->entries[i].advanceHeight;
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // VORG is preferred way to calculate vertical origin than vmtx,
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // so load topSideBearing from vmtx only if VORG is missing.
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasVORG())
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t sizeExtra = buffer->size() - sizeof(OpenType::VmtxTable::Entry) * countVmtxEntries;
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (sizeExtra % sizeof(OpenType::Int16)) {
475a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("vmtx has incorrect tsb count");
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t countTopSideBearings = countVmtxEntries + sizeExtra / sizeof(OpenType::Int16);
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_topSideBearings.resize(countTopSideBearings);
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t i;
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (i = 0; i < countVmtxEntries; ++i)
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_topSideBearings[i] = vmtx->entries[i].topSideBearing;
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (i < countTopSideBearings) {
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const OpenType::Int16* pTopSideBearingsExtra = reinterpret_cast<const OpenType::Int16*>(&vmtx->entries[countVmtxEntries]);
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (; i < countTopSideBearings; ++i, ++pTopSideBearingsExtra)
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_topSideBearings[i] = *pTopSideBearingsExtra;
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void OpenTypeVerticalData::loadVerticalGlyphSubstitutions(const FontPlatformData& platformData)
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::GSUBTag);
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const OpenType::GSUBTable* gsub = OpenType::validateTable<OpenType::GSUBTable>(buffer);
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (gsub)
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gsub->getVerticalGlyphSubstitutions(&m_verticalGlyphMap, *buffer.get());
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float OpenTypeVerticalData::advanceHeight(const SimpleFontData* font, Glyph glyph) const
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t countHeights = m_advanceHeights.size();
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (countHeights) {
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t advanceFUnit = m_advanceHeights[glyph < countHeights ? glyph : countHeights - 1];
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float advance = advanceFUnit * font->sizePerUnit();
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return advance;
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // No vertical info in the font file; use height as advance.
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return font->fontMetrics().height();
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void OpenTypeVerticalData::getVerticalTranslationsForGlyphs(const SimpleFontData* font, const Glyph* glyphs, size_t count, float* outXYArray) const
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t countWidths = m_advanceWidths.size();
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(countWidths > 0);
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const FontMetrics& metrics = font->fontMetrics();
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float sizePerUnit = font->sizePerUnit();
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float ascent = metrics.ascent();
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool useVORG = hasVORG();
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t countTopSideBearings = m_topSideBearings.size();
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float defaultVertOriginY = std::numeric_limits<float>::quiet_NaN();
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (float* end = &(outXYArray[count * 2]); outXYArray != end; ++glyphs, outXYArray += 2) {
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Glyph glyph = *glyphs;
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint16_t widthFUnit = m_advanceWidths[glyph < countWidths ? glyph : countWidths - 1];
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float width = widthFUnit * sizePerUnit;
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        outXYArray[0] = -width / 2;
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // For Y, try VORG first.
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (useVORG) {
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            int16_t vertOriginYFUnit = m_vertOriginY.get(glyph);
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (vertOriginYFUnit) {
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                outXYArray[1] = -vertOriginYFUnit * sizePerUnit;
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                continue;
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (std::isnan(defaultVertOriginY))
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                defaultVertOriginY = -m_defaultVertOriginY * sizePerUnit;
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            outXYArray[1] = defaultVertOriginY;
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If no VORG, try vmtx next.
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (countTopSideBearings) {
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            int16_t topSideBearingFUnit = m_topSideBearings[glyph < countTopSideBearings ? glyph : countTopSideBearings - 1];
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            float topSideBearing = topSideBearingFUnit * sizePerUnit;
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            FloatRect bounds = font->boundsForGlyph(glyph);
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            outXYArray[1] = bounds.y() - topSideBearing;
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // No vertical info in the font file; use ascent as vertical origin.
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        outXYArray[1] = -ascent;
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void OpenTypeVerticalData::substituteWithVerticalGlyphs(const SimpleFontData* font, GlyphPage* glyphPage, unsigned offset, unsigned length) const
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const HashMap<Glyph, Glyph>& map = m_verticalGlyphMap;
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (map.isEmpty())
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned index = offset, end = offset + length; index < end; ++index) {
56110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        GlyphData glyphData = glyphPage->glyphDataForIndex(index);
56210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        if (glyphData.glyph && glyphData.fontData == font) {
56310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            Glyph to = map.get(glyphData.glyph);
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (to)
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                glyphPage->setGlyphDataForIndex(index, to, font);
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
570c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // ENABLE(OPENTYPE_VERTICAL)
572