blob: df4b3f71371b173424a795cfb0ac18104e057c0a [file] [log] [blame]
/*
* 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 "src/core/SkEndian.h"
#include "src/sfnt/SkOTTableTypes.h"
#include "src/sfnt/SkOTTable_head.h"
#include "src/sfnt/SkOTTable_loca.h"
#pragma pack(push, 1)
struct SkOTTableGlyphData;
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(SkOTTableGlyph& glyf,
const SkOTTableIndexToLocation& loca,
SkOTTableHead::IndexToLocFormat locaFormat)
: fGlyf(glyf)
, fLoca(loca)
, fLocaFormat(locaFormat)
, fCurrentGlyph(0)
, fCurrentGlyphOffset(0)
{
SkASSERT(locaFormat.value == SkOTTableHead::IndexToLocFormat::ShortOffsets ||
locaFormat.value == SkOTTableHead::IndexToLocFormat::LongOffsets);
}
void advance(uint16_t num) {
fCurrentGlyph += num;
if (fLocaFormat.value == SkOTTableHead::IndexToLocFormat::ShortOffsets) {
fCurrentGlyphOffset =
SkEndian_SwapBE16(fLoca.offsets.shortOffset[fCurrentGlyph]) << 1;
} else if (fLocaFormat.value == SkOTTableHead::IndexToLocFormat::LongOffsets) {
fCurrentGlyphOffset = SkEndian_SwapBE32(fLoca.offsets.longOffset[fCurrentGlyph]);
}
}
SkOTTableGlyphData* next() {
uint32_t previousGlyphOffset = fCurrentGlyphOffset;
advance(1);
if (previousGlyphOffset == fCurrentGlyphOffset) {
return nullptr;
} else {
return reinterpret_cast<SkOTTableGlyphData*>(
reinterpret_cast<SK_OT_BYTE*>(&fGlyf) + previousGlyphOffset
);
}
}
private:
SkOTTableGlyph& fGlyf;
const SkOTTableIndexToLocation& fLoca;
SkOTTableHead::IndexToLocFormat fLocaFormat;
uint32_t fCurrentGlyph;
uint32_t fCurrentGlyphOffset;
};
};
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