| /* |
| * Copyright © 2018 Ebrahim Byagowi |
| * |
| * This is part of HarfBuzz, a text shaping library. |
| * |
| * Permission is hereby granted, without written agreement and without |
| * license or royalty fees, to use, copy, modify, and distribute this |
| * software and its documentation for any purpose, provided that the |
| * above copyright notice and the following two paragraphs appear in |
| * all copies of this software. |
| * |
| * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
| * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| * |
| * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
| * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| */ |
| |
| #ifndef HB_AAT_LAYOUT_JUST_TABLE_HH |
| #define HB_AAT_LAYOUT_JUST_TABLE_HH |
| |
| #include "hb-aat-layout-common.hh" |
| #include "hb-ot-layout.hh" |
| #include "hb-open-type.hh" |
| |
| #include "hb-aat-layout-morx-table.hh" |
| |
| /* |
| * just -- Justification |
| * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6just.html |
| */ |
| #define HB_AAT_TAG_just HB_TAG('j','u','s','t') |
| |
| |
| namespace AAT { |
| |
| using namespace OT; |
| |
| |
| struct ActionSubrecordHeader |
| { |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (c->check_struct (this)); |
| } |
| |
| HBUINT16 actionClass; /* The JustClass value associated with this |
| * ActionSubrecord. */ |
| HBUINT16 actionType; /* The type of postcompensation action. */ |
| HBUINT16 actionLength; /* Length of this ActionSubrecord record, which |
| * must be a multiple of 4. */ |
| public: |
| DEFINE_SIZE_STATIC (6); |
| }; |
| |
| struct DecompositionAction |
| { |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (c->check_struct (this)); |
| } |
| |
| ActionSubrecordHeader |
| header; |
| HBFixed lowerLimit; /* If the distance factor is less than this value, |
| * then the ligature is decomposed. */ |
| HBFixed upperLimit; /* If the distance factor is greater than this value, |
| * then the ligature is decomposed. */ |
| HBUINT16 order; /* Numerical order in which this ligature will |
| * be decomposed; you may want infrequent ligatures |
| * to decompose before more frequent ones. The ligatures |
| * on the line of text will decompose in increasing |
| * value of this field. */ |
| Array16Of<HBUINT16> |
| decomposedglyphs; |
| /* Number of 16-bit glyph indexes that follow; |
| * the ligature will be decomposed into these glyphs. |
| * |
| * Array of decomposed glyphs. */ |
| public: |
| DEFINE_SIZE_ARRAY (18, decomposedglyphs); |
| }; |
| |
| struct UnconditionalAddGlyphAction |
| { |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (c->check_struct (this)); |
| } |
| |
| protected: |
| ActionSubrecordHeader |
| header; |
| HBGlyphID16 addGlyph; /* Glyph that should be added if the distance factor |
| * is growing. */ |
| |
| public: |
| DEFINE_SIZE_STATIC (8); |
| }; |
| |
| struct ConditionalAddGlyphAction |
| { |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (c->check_struct (this)); |
| } |
| |
| protected: |
| ActionSubrecordHeader |
| header; |
| HBFixed substThreshold; /* Distance growth factor (in ems) at which |
| * this glyph is replaced and the growth factor |
| * recalculated. */ |
| HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is |
| * 0xFFFF, no extra glyph will be added. Note that |
| * generally when a glyph is added, justification |
| * will need to be redone. */ |
| HBGlyphID16 substGlyph; /* Glyph to be substituted for this glyph if the |
| * growth factor equals or exceeds the value of |
| * substThreshold. */ |
| public: |
| DEFINE_SIZE_STATIC (14); |
| }; |
| |
| struct DuctileGlyphAction |
| { |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (c->check_struct (this)); |
| } |
| |
| protected: |
| ActionSubrecordHeader |
| header; |
| HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis. |
| * This would normally be 0x64756374 ('duct'), |
| * but you may use any axis the font contains. */ |
| HBFixed minimumLimit; /* The lowest value for the ductility axis that |
| * still yields an acceptable appearance. Normally |
| * this will be 1.0. */ |
| HBFixed noStretchValue; /* This is the default value that corresponds to |
| * no change in appearance. Normally, this will |
| * be 1.0. */ |
| HBFixed maximumLimit; /* The highest value for the ductility axis that |
| * still yields an acceptable appearance. */ |
| public: |
| DEFINE_SIZE_STATIC (22); |
| }; |
| |
| struct RepeatedAddGlyphAction |
| { |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (c->check_struct (this)); |
| } |
| |
| protected: |
| ActionSubrecordHeader |
| header; |
| HBUINT16 flags; /* Currently unused; set to 0. */ |
| HBGlyphID16 glyph; /* Glyph that should be added if the distance factor |
| * is growing. */ |
| public: |
| DEFINE_SIZE_STATIC (10); |
| }; |
| |
| struct ActionSubrecord |
| { |
| unsigned int get_length () const { return u.header.actionLength; } |
| |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| if (unlikely (!c->check_struct (this))) |
| return_trace (false); |
| |
| switch (u.header.actionType) |
| { |
| case 0: return_trace (u.decompositionAction.sanitize (c)); |
| case 1: return_trace (u.unconditionalAddGlyphAction.sanitize (c)); |
| case 2: return_trace (u.conditionalAddGlyphAction.sanitize (c)); |
| // case 3: return_trace (u.stretchGlyphAction.sanitize (c)); |
| case 4: return_trace (u.decompositionAction.sanitize (c)); |
| case 5: return_trace (u.decompositionAction.sanitize (c)); |
| default: return_trace (true); |
| } |
| } |
| |
| protected: |
| union { |
| ActionSubrecordHeader header; |
| DecompositionAction decompositionAction; |
| UnconditionalAddGlyphAction unconditionalAddGlyphAction; |
| ConditionalAddGlyphAction conditionalAddGlyphAction; |
| /* StretchGlyphAction stretchGlyphAction; -- Not supported by CoreText */ |
| DuctileGlyphAction ductileGlyphAction; |
| RepeatedAddGlyphAction repeatedAddGlyphAction; |
| } u; /* Data. The format of this data depends on |
| * the value of the actionType field. */ |
| public: |
| DEFINE_SIZE_UNION (6, header); |
| }; |
| |
| struct PostcompensationActionChain |
| { |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| if (unlikely (!c->check_struct (this))) |
| return_trace (false); |
| |
| unsigned int offset = min_size; |
| for (unsigned int i = 0; i < count; i++) |
| { |
| const ActionSubrecord& subrecord = StructAtOffset<ActionSubrecord> (this, offset); |
| if (unlikely (!subrecord.sanitize (c))) return_trace (false); |
| offset += subrecord.get_length (); |
| } |
| |
| return_trace (true); |
| } |
| |
| protected: |
| HBUINT32 count; |
| |
| public: |
| DEFINE_SIZE_STATIC (4); |
| }; |
| |
| struct JustWidthDeltaEntry |
| { |
| enum Flags |
| { |
| Reserved1 =0xE000,/* Reserved. You should set these bits to zero. */ |
| UnlimiteGap =0x1000,/* The glyph can take unlimited gap. When this |
| * glyph participates in the justification process, |
| * it and any other glyphs on the line having this |
| * bit set absorb all the remaining gap. */ |
| Reserved2 =0x0FF0,/* Reserved. You should set these bits to zero. */ |
| Priority =0x000F /* The justification priority of the glyph. */ |
| }; |
| |
| enum Priority |
| { |
| Kashida = 0, /* Kashida priority. This is the highest priority |
| * during justification. */ |
| Whitespace = 1, /* Whitespace priority. Any whitespace glyphs (as |
| * identified in the glyph properties table) will |
| * get this priority. */ |
| InterCharacter = 2, /* Inter-character priority. Give this to any |
| * remaining glyphs. */ |
| NullPriority = 3 /* Null priority. You should set this priority for |
| * glyphs that only participate in justification |
| * after the above priorities. Normally all glyphs |
| * have one of the previous three values. If you |
| * don't want a glyph to participate in justification, |
| * and you don't want to set its factors to zero, |
| * you may instead assign it to the null priority. */ |
| }; |
| |
| protected: |
| HBFixed beforeGrowLimit;/* The ratio by which the advance width of the |
| * glyph is permitted to grow on the left or top side. */ |
| HBFixed beforeShrinkLimit; |
| /* The ratio by which the advance width of the |
| * glyph is permitted to shrink on the left or top side. */ |
| HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph |
| * is permitted to shrink on the left or top side. */ |
| HBFixed afterShrinkLimit; |
| /* The ratio by which the advance width of the glyph |
| * is at most permitted to shrink on the right or |
| * bottom side. */ |
| HBUINT16 growFlags; /* Flags controlling the grow case. */ |
| HBUINT16 shrinkFlags; /* Flags controlling the shrink case. */ |
| |
| public: |
| DEFINE_SIZE_STATIC (20); |
| }; |
| |
| struct WidthDeltaPair |
| { |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (c->check_struct (this)); |
| } |
| |
| protected: |
| HBUINT32 justClass; /* The justification category associated |
| * with the wdRecord field. Only 7 bits of |
| * this field are used. (The other bits are |
| * used as padding to guarantee longword |
| * alignment of the following record). */ |
| JustWidthDeltaEntry |
| wdRecord; /* The actual width delta record. */ |
| |
| public: |
| DEFINE_SIZE_STATIC (24); |
| }; |
| |
| typedef OT::Array32Of<WidthDeltaPair> WidthDeltaCluster; |
| |
| struct JustificationCategory |
| { |
| typedef void EntryData; |
| |
| enum Flags |
| { |
| SetMark =0x8000,/* If set, make the current glyph the marked |
| * glyph. */ |
| DontAdvance =0x4000,/* If set, don't advance to the next glyph before |
| * going to the new state. */ |
| MarkCategory =0x3F80,/* The justification category for the marked |
| * glyph if nonzero. */ |
| CurrentCategory =0x007F /* The justification category for the current |
| * glyph if nonzero. */ |
| }; |
| |
| bool sanitize (hb_sanitize_context_t *c, const void *base) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (likely (c->check_struct (this) && |
| morphHeader.sanitize (c) && |
| stHeader.sanitize (c))); |
| } |
| |
| protected: |
| ChainSubtable<ObsoleteTypes> |
| morphHeader; /* Metamorphosis-style subtable header. */ |
| StateTable<ObsoleteTypes, EntryData> |
| stHeader; /* The justification insertion state table header */ |
| public: |
| DEFINE_SIZE_STATIC (30); |
| }; |
| |
| struct JustificationHeader |
| { |
| bool sanitize (hb_sanitize_context_t *c, const void *base) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (likely (c->check_struct (this) && |
| justClassTable.sanitize (c, base, base) && |
| wdcTable.sanitize (c, base) && |
| pcTable.sanitize (c, base) && |
| lookupTable.sanitize (c, base))); |
| } |
| |
| protected: |
| Offset16To<JustificationCategory> |
| justClassTable; /* Offset to the justification category state table. */ |
| Offset16To<WidthDeltaCluster> |
| wdcTable; /* Offset from start of justification table to start |
| * of the subtable containing the width delta factors |
| * for the glyphs in your font. |
| * |
| * The width delta clusters table. */ |
| Offset16To<PostcompensationActionChain> |
| pcTable; /* Offset from start of justification table to start |
| * of postcompensation subtable (set to zero if none). |
| * |
| * The postcompensation subtable, if present in the font. */ |
| Lookup<Offset16To<WidthDeltaCluster>> |
| lookupTable; /* Lookup table associating glyphs with width delta |
| * clusters. See the description of Width Delta Clusters |
| * table for details on how to interpret the lookup values. */ |
| |
| public: |
| DEFINE_SIZE_MIN (8); |
| }; |
| |
| struct just |
| { |
| static constexpr hb_tag_t tableTag = HB_AAT_TAG_just; |
| |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| |
| return_trace (likely (c->check_struct (this) && |
| version.major == 1 && |
| horizData.sanitize (c, this, this) && |
| vertData.sanitize (c, this, this))); |
| } |
| |
| protected: |
| FixedVersion<>version; /* Version of the justification table |
| * (0x00010000u for version 1.0). */ |
| HBUINT16 format; /* Format of the justification table (set to 0). */ |
| Offset16To<JustificationHeader> |
| horizData; /* Byte offset from the start of the justification table |
| * to the header for tables that contain justification |
| * information for horizontal text. |
| * If you are not including this information, |
| * store 0. */ |
| Offset16To<JustificationHeader> |
| vertData; /* ditto, vertical */ |
| |
| public: |
| DEFINE_SIZE_STATIC (10); |
| }; |
| |
| } /* namespace AAT */ |
| |
| |
| #endif /* HB_AAT_LAYOUT_JUST_TABLE_HH */ |