aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sfnt/SkOTTable_glyf.h
blob: 77bd982b0e3ab6fff04d470ff3d5fe1c1abb7ce9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkOTTable_glyf_DEFINED
#define SkOTTable_glyf_DEFINED

#include "SkEndian.h"
#include "SkOTTableTypes.h"
#include "SkOTTable_head.h"
#include "SkOTTable_loca.h"

#pragma pack(push, 1)

struct SkOTTableGlyphData;

extern uint8_t const * const SK_OT_GlyphData_NoOutline;

struct SkOTTableGlyph {
    static const SK_OT_CHAR TAG0 = 'g';
    static const SK_OT_CHAR TAG1 = 'l';
    static const SK_OT_CHAR TAG2 = 'y';
    static const SK_OT_CHAR TAG3 = 'f';
    static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableGlyph>::value;

    class Iterator {
    public:
        Iterator(const SkOTTableGlyph& glyf,
                 const SkOTTableIndexToLocation& loca,
                 SkOTTableHead::IndexToLocFormat locaFormat)
        : fGlyf(glyf)
        , fLocaFormat(SkOTTableHead::IndexToLocFormat::ShortOffsets == locaFormat.value ? 0 : 1)
        , fCurrentGlyphOffset(0)
        { fLocaPtr.shortOffset = reinterpret_cast<const SK_OT_USHORT*>(&loca); }

        void advance(uint16_t num) {
            fLocaPtr.shortOffset += num << fLocaFormat;
            fCurrentGlyphOffset = fLocaFormat ? SkEndian_SwapBE32(*fLocaPtr.longOffset)
                                              : uint32_t(SkEndian_SwapBE16(*fLocaPtr.shortOffset) << 1);
        }
        const SkOTTableGlyphData* next() {
            uint32_t previousGlyphOffset = fCurrentGlyphOffset;
            advance(1);
            if (previousGlyphOffset == fCurrentGlyphOffset) {
                return reinterpret_cast<const SkOTTableGlyphData*>(&SK_OT_GlyphData_NoOutline);
            } else {
                return reinterpret_cast<const SkOTTableGlyphData*>(
                    reinterpret_cast<const SK_OT_BYTE*>(&fGlyf) + previousGlyphOffset
                );
            }
        }
    private:
        const SkOTTableGlyph& fGlyf;
        uint16_t fLocaFormat; //0 or 1
        uint32_t fCurrentGlyphOffset;
        union LocaPtr {
            const SK_OT_USHORT* shortOffset;
            const SK_OT_ULONG* longOffset;
        } fLocaPtr;
    };
};

struct SkOTTableGlyphData {
    SK_OT_SHORT numberOfContours; //== -1 Composite, > 0 Simple
    SK_OT_FWORD xMin;
    SK_OT_FWORD yMin;
    SK_OT_FWORD xMax;
    SK_OT_FWORD yMax;

    struct Simple {
        SK_OT_USHORT endPtsOfContours[1/*numberOfContours*/];

        struct Instructions {
            SK_OT_USHORT length;
            SK_OT_BYTE data[1/*length*/];
        };

        union Flags {
            struct Field {
                SK_OT_BYTE_BITFIELD(
                    OnCurve,
                    xShortVector,
                    yShortVector,
                    Repeat,
                    xIsSame_xShortVectorPositive,
                    yIsSame_yShortVectorPositive,
                    Reserved6,
                    Reserved7)
            } field;
            struct Raw {
                static const SK_OT_USHORT OnCurveMask = SkTEndian_SwapBE16(1 << 0);
                static const SK_OT_USHORT xShortVectorMask = SkTEndian_SwapBE16(1 << 1);
                static const SK_OT_USHORT yShortVectorMask = SkTEndian_SwapBE16(1 << 2);
                static const SK_OT_USHORT RepeatMask = SkTEndian_SwapBE16(1 << 3);
                static const SK_OT_USHORT xIsSame_xShortVectorPositiveMask = SkTEndian_SwapBE16(1 << 4);
                static const SK_OT_USHORT yIsSame_yShortVectorPositiveMask = SkTEndian_SwapBE16(1 << 5);
                SK_OT_BYTE value;
            } raw;
        };

        //xCoordinates
        //yCoordinates
    };

    struct Composite {
        struct Component {
            union Flags {
                struct Field {
                    //8-15
                    SK_OT_BYTE_BITFIELD(
                        WE_HAVE_INSTRUCTIONS,
                        USE_MY_METRICS,
                        OVERLAP_COMPOUND,
                        SCALED_COMPONENT_OFFSET,
                        UNSCALED_COMPONENT_OFFSET,
                        Reserved13,
                        Reserved14,
                        Reserved15)
                    //0-7
                    SK_OT_BYTE_BITFIELD(
                        ARG_1_AND_2_ARE_WORDS,
                        ARGS_ARE_XY_VALUES,
                        ROUND_XY_TO_GRID,
                        WE_HAVE_A_SCALE,
                        RESERVED,
                        MORE_COMPONENTS,
                        WE_HAVE_AN_X_AND_Y_SCALE,
                        WE_HAVE_A_TWO_BY_TWO)
                } field;
                struct Raw {
                    static const SK_OT_USHORT ARG_1_AND_2_ARE_WORDS_Mask = SkTEndian_SwapBE16(1 << 0);
                    static const SK_OT_USHORT ARGS_ARE_XY_VALUES_Mask = SkTEndian_SwapBE16(1 << 1);
                    static const SK_OT_USHORT ROUND_XY_TO_GRID_Mask = SkTEndian_SwapBE16(1 << 2);
                    static const SK_OT_USHORT WE_HAVE_A_SCALE_Mask = SkTEndian_SwapBE16(1 << 3);
                    static const SK_OT_USHORT RESERVED_Mask = SkTEndian_SwapBE16(1 << 4);
                    static const SK_OT_USHORT MORE_COMPONENTS_Mask = SkTEndian_SwapBE16(1 << 5);
                    static const SK_OT_USHORT WE_HAVE_AN_X_AND_Y_SCALE_Mask = SkTEndian_SwapBE16(1 << 6);
                    static const SK_OT_USHORT WE_HAVE_A_TWO_BY_TWO_Mask = SkTEndian_SwapBE16(1 << 7);

                    static const SK_OT_USHORT WE_HAVE_INSTRUCTIONS_Mask = SkTEndian_SwapBE16(1 << 8);
                    static const SK_OT_USHORT USE_MY_METRICS_Mask = SkTEndian_SwapBE16(1 << 9);
                    static const SK_OT_USHORT OVERLAP_COMPOUND_Mask = SkTEndian_SwapBE16(1 << 10);
                    static const SK_OT_USHORT SCALED_COMPONENT_OFFSET_Mask = SkTEndian_SwapBE16(1 << 11);
                    static const SK_OT_USHORT UNSCALED_COMPONENT_OFFSET_mask = SkTEndian_SwapBE16(1 << 12);
                    //Reserved
                    //Reserved
                    //Reserved
                    SK_OT_USHORT value;
                } raw;
            } flags;
            SK_OT_USHORT glyphIndex;
            union Transform {
                union Matrix {
                    /** !WE_HAVE_A_SCALE & !WE_HAVE_AN_X_AND_Y_SCALE & !WE_HAVE_A_TWO_BY_TWO */
                    struct None { } none;
                    /** WE_HAVE_A_SCALE */
                    struct Scale {
                        SK_OT_F2DOT14 a_d;
                    } scale;
                    /** WE_HAVE_AN_X_AND_Y_SCALE */
                    struct ScaleXY {
                        SK_OT_F2DOT14 a;
                        SK_OT_F2DOT14 d;
                    } scaleXY;
                    /** WE_HAVE_A_TWO_BY_TWO */
                    struct TwoByTwo {
                        SK_OT_F2DOT14 a;
                        SK_OT_F2DOT14 b;
                        SK_OT_F2DOT14 c;
                        SK_OT_F2DOT14 d;
                    } twoByTwo;
                };
                /** ARG_1_AND_2_ARE_WORDS & ARGS_ARE_XY_VALUES */
                struct WordValue {
                    SK_OT_FWORD e;
                    SK_OT_FWORD f;
                    SkOTTableGlyphData::Composite::Component::Transform::Matrix matrix;
                } wordValue;
                /** !ARG_1_AND_2_ARE_WORDS & ARGS_ARE_XY_VALUES */
                struct ByteValue {
                    SK_OT_CHAR e;
                    SK_OT_CHAR f;
                    SkOTTableGlyphData::Composite::Component::Transform::Matrix matrix;
                } byteValue;
                /** ARG_1_AND_2_ARE_WORDS & !ARGS_ARE_XY_VALUES */
                struct WordIndex {
                    SK_OT_USHORT compoundPointIndex;
                    SK_OT_USHORT componentPointIndex;
                    SkOTTableGlyphData::Composite::Component::Transform::Matrix matrix;
                } wordIndex;
                /** !ARG_1_AND_2_ARE_WORDS & !ARGS_ARE_XY_VALUES */
                struct ByteIndex {
                    SK_OT_BYTE compoundPointIndex;
                    SK_OT_BYTE componentPointIndex;
                    SkOTTableGlyphData::Composite::Component::Transform::Matrix matrix;
                } byteIndex;
            } transform;
        } component;//[] last element does not set MORE_COMPONENTS

        /** Comes after the last Component if the last component has WE_HAVE_INSTR. */
        struct Instructions {
            SK_OT_USHORT length;
            SK_OT_BYTE data[1/*length*/];
        };
    };
};

#pragma pack(pop)

#endif