michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkOTTable_glyf_DEFINED michael@0: #define SkOTTable_glyf_DEFINED michael@0: michael@0: #include "SkEndian.h" michael@0: #include "SkOTTableTypes.h" michael@0: #include "SkOTTable_head.h" michael@0: #include "SkOTTable_loca.h" michael@0: #include "SkTypedEnum.h" michael@0: michael@0: #pragma pack(push, 1) michael@0: michael@0: struct SkOTTableGlyphData; michael@0: michael@0: extern uint8_t const * const SK_OT_GlyphData_NoOutline; michael@0: michael@0: struct SkOTTableGlyph { michael@0: static const SK_OT_CHAR TAG0 = 'g'; michael@0: static const SK_OT_CHAR TAG1 = 'l'; michael@0: static const SK_OT_CHAR TAG2 = 'y'; michael@0: static const SK_OT_CHAR TAG3 = 'f'; michael@0: static const SK_OT_ULONG TAG = SkOTTableTAG::value; michael@0: michael@0: class Iterator { michael@0: public: michael@0: Iterator(const SkOTTableGlyph& glyf, michael@0: const SkOTTableIndexToLocation& loca, michael@0: SkOTTableHead::IndexToLocFormat locaFormat) michael@0: : fGlyf(glyf) michael@0: , fLocaFormat(SkOTTableHead::IndexToLocFormat::ShortOffsets == locaFormat.value ? 0 : 1) michael@0: , fCurrentGlyphOffset(0) michael@0: { fLocaPtr.shortOffset = reinterpret_cast(&loca); } michael@0: michael@0: void advance(uint16_t num) { michael@0: fLocaPtr.shortOffset += num << fLocaFormat; michael@0: fCurrentGlyphOffset = fLocaFormat ? SkEndian_SwapBE32(*fLocaPtr.longOffset) michael@0: : uint32_t(SkEndian_SwapBE16(*fLocaPtr.shortOffset) << 1); michael@0: } michael@0: const SkOTTableGlyphData* next() { michael@0: uint32_t previousGlyphOffset = fCurrentGlyphOffset; michael@0: advance(1); michael@0: if (previousGlyphOffset == fCurrentGlyphOffset) { michael@0: return reinterpret_cast(&SK_OT_GlyphData_NoOutline); michael@0: } else { michael@0: return reinterpret_cast( michael@0: reinterpret_cast(&fGlyf) + previousGlyphOffset michael@0: ); michael@0: } michael@0: } michael@0: private: michael@0: const SkOTTableGlyph& fGlyf; michael@0: uint16_t fLocaFormat; //0 or 1 michael@0: uint32_t fCurrentGlyphOffset; michael@0: union LocaPtr { michael@0: const SK_OT_USHORT* shortOffset; michael@0: const SK_OT_ULONG* longOffset; michael@0: } fLocaPtr; michael@0: }; michael@0: }; michael@0: michael@0: struct SkOTTableGlyphData { michael@0: SK_OT_SHORT numberOfContours; //== -1 Composite, > 0 Simple michael@0: SK_OT_FWORD xMin; michael@0: SK_OT_FWORD yMin; michael@0: SK_OT_FWORD xMax; michael@0: SK_OT_FWORD yMax; michael@0: michael@0: struct Simple { michael@0: SK_OT_USHORT endPtsOfContours[1/*numberOfContours*/]; michael@0: michael@0: struct Instructions { michael@0: SK_OT_USHORT length; michael@0: SK_OT_BYTE data[1/*length*/]; michael@0: }; michael@0: michael@0: union Flags { michael@0: struct Field { michael@0: SK_OT_BYTE_BITFIELD( michael@0: OnCurve, michael@0: xShortVector, michael@0: yShortVector, michael@0: Repeat, michael@0: xIsSame_xShortVectorPositive, michael@0: yIsSame_yShortVectorPositive, michael@0: Reserved6, michael@0: Reserved7) michael@0: } field; michael@0: struct Raw { michael@0: static const SK_OT_USHORT OnCurveMask = SkTEndian_SwapBE16(1 << 0); michael@0: static const SK_OT_USHORT xShortVectorMask = SkTEndian_SwapBE16(1 << 1); michael@0: static const SK_OT_USHORT yShortVectorMask = SkTEndian_SwapBE16(1 << 2); michael@0: static const SK_OT_USHORT RepeatMask = SkTEndian_SwapBE16(1 << 3); michael@0: static const SK_OT_USHORT xIsSame_xShortVectorPositiveMask = SkTEndian_SwapBE16(1 << 4); michael@0: static const SK_OT_USHORT yIsSame_yShortVectorPositiveMask = SkTEndian_SwapBE16(1 << 5); michael@0: SK_OT_BYTE value; michael@0: } raw; michael@0: }; michael@0: michael@0: //xCoordinates michael@0: //yCoordinates michael@0: }; michael@0: michael@0: struct Composite { michael@0: struct Component { michael@0: union Flags { michael@0: struct Field { michael@0: //8-15 michael@0: SK_OT_BYTE_BITFIELD( michael@0: WE_HAVE_INSTRUCTIONS, michael@0: USE_MY_METRICS, michael@0: OVERLAP_COMPOUND, michael@0: SCALED_COMPONENT_OFFSET, michael@0: UNSCALED_COMPONENT_OFFSET, michael@0: Reserved13, michael@0: Reserved14, michael@0: Reserved15) michael@0: //0-7 michael@0: SK_OT_BYTE_BITFIELD( michael@0: ARG_1_AND_2_ARE_WORDS, michael@0: ARGS_ARE_XY_VALUES, michael@0: ROUND_XY_TO_GRID, michael@0: WE_HAVE_A_SCALE, michael@0: RESERVED, michael@0: MORE_COMPONENTS, michael@0: WE_HAVE_AN_X_AND_Y_SCALE, michael@0: WE_HAVE_A_TWO_BY_TWO) michael@0: } field; michael@0: struct Raw { michael@0: static const SK_OT_USHORT ARG_1_AND_2_ARE_WORDS_Mask = SkTEndian_SwapBE16(1 << 0); michael@0: static const SK_OT_USHORT ARGS_ARE_XY_VALUES_Mask = SkTEndian_SwapBE16(1 << 1); michael@0: static const SK_OT_USHORT ROUND_XY_TO_GRID_Mask = SkTEndian_SwapBE16(1 << 2); michael@0: static const SK_OT_USHORT WE_HAVE_A_SCALE_Mask = SkTEndian_SwapBE16(1 << 3); michael@0: static const SK_OT_USHORT RESERVED_Mask = SkTEndian_SwapBE16(1 << 4); michael@0: static const SK_OT_USHORT MORE_COMPONENTS_Mask = SkTEndian_SwapBE16(1 << 5); michael@0: static const SK_OT_USHORT WE_HAVE_AN_X_AND_Y_SCALE_Mask = SkTEndian_SwapBE16(1 << 6); michael@0: static const SK_OT_USHORT WE_HAVE_A_TWO_BY_TWO_Mask = SkTEndian_SwapBE16(1 << 7); michael@0: michael@0: static const SK_OT_USHORT WE_HAVE_INSTRUCTIONS_Mask = SkTEndian_SwapBE16(1 << 8); michael@0: static const SK_OT_USHORT USE_MY_METRICS_Mask = SkTEndian_SwapBE16(1 << 9); michael@0: static const SK_OT_USHORT OVERLAP_COMPOUND_Mask = SkTEndian_SwapBE16(1 << 10); michael@0: static const SK_OT_USHORT SCALED_COMPONENT_OFFSET_Mask = SkTEndian_SwapBE16(1 << 11); michael@0: static const SK_OT_USHORT UNSCALED_COMPONENT_OFFSET_mask = SkTEndian_SwapBE16(1 << 12); michael@0: //Reserved michael@0: //Reserved michael@0: //Reserved michael@0: SK_OT_USHORT value; michael@0: } raw; michael@0: } flags; michael@0: SK_OT_USHORT glyphIndex; michael@0: union Transform { michael@0: union Matrix { michael@0: /** !WE_HAVE_A_SCALE & !WE_HAVE_AN_X_AND_Y_SCALE & !WE_HAVE_A_TWO_BY_TWO */ michael@0: struct None { } none; michael@0: /** WE_HAVE_A_SCALE */ michael@0: struct Scale { michael@0: SK_OT_F2DOT14 a_d; michael@0: } scale; michael@0: /** WE_HAVE_AN_X_AND_Y_SCALE */ michael@0: struct ScaleXY { michael@0: SK_OT_F2DOT14 a; michael@0: SK_OT_F2DOT14 d; michael@0: } scaleXY; michael@0: /** WE_HAVE_A_TWO_BY_TWO */ michael@0: struct TwoByTwo { michael@0: SK_OT_F2DOT14 a; michael@0: SK_OT_F2DOT14 b; michael@0: SK_OT_F2DOT14 c; michael@0: SK_OT_F2DOT14 d; michael@0: } twoByTwo; michael@0: }; michael@0: /** ARG_1_AND_2_ARE_WORDS & ARGS_ARE_XY_VALUES */ michael@0: struct WordValue { michael@0: SK_OT_FWORD e; michael@0: SK_OT_FWORD f; michael@0: SkOTTableGlyphData::Composite::Component::Transform::Matrix matrix; michael@0: } wordValue; michael@0: /** !ARG_1_AND_2_ARE_WORDS & ARGS_ARE_XY_VALUES */ michael@0: struct ByteValue { michael@0: SK_OT_CHAR e; michael@0: SK_OT_CHAR f; michael@0: SkOTTableGlyphData::Composite::Component::Transform::Matrix matrix; michael@0: } byteValue; michael@0: /** ARG_1_AND_2_ARE_WORDS & !ARGS_ARE_XY_VALUES */ michael@0: struct WordIndex { michael@0: SK_OT_USHORT compoundPointIndex; michael@0: SK_OT_USHORT componentPointIndex; michael@0: SkOTTableGlyphData::Composite::Component::Transform::Matrix matrix; michael@0: } wordIndex; michael@0: /** !ARG_1_AND_2_ARE_WORDS & !ARGS_ARE_XY_VALUES */ michael@0: struct ByteIndex { michael@0: SK_OT_BYTE compoundPointIndex; michael@0: SK_OT_BYTE componentPointIndex; michael@0: SkOTTableGlyphData::Composite::Component::Transform::Matrix matrix; michael@0: } byteIndex; michael@0: } transform; michael@0: } component;//[] last element does not set MORE_COMPONENTS michael@0: michael@0: /** Comes after the last Component if the last component has WE_HAVE_INSTR. */ michael@0: struct Instructions { michael@0: SK_OT_USHORT length; michael@0: SK_OT_BYTE data[1/*length*/]; michael@0: }; michael@0: }; michael@0: }; michael@0: michael@0: #pragma pack(pop) michael@0: michael@0: #endif