summaryrefslogtreecommitdiffstats
path: root/gfx/graphite2/src/inc
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/graphite2/src/inc')
-rw-r--r--gfx/graphite2/src/inc/CharInfo.h66
-rw-r--r--gfx/graphite2/src/inc/CmapCache.h82
-rw-r--r--gfx/graphite2/src/inc/Code.h171
-rw-r--r--gfx/graphite2/src/inc/Collider.h245
-rw-r--r--gfx/graphite2/src/inc/Compression.h104
-rw-r--r--gfx/graphite2/src/inc/Decompressor.h54
-rw-r--r--gfx/graphite2/src/inc/Endian.h111
-rw-r--r--gfx/graphite2/src/inc/Error.h134
-rw-r--r--gfx/graphite2/src/inc/Face.h225
-rw-r--r--gfx/graphite2/src/inc/FeatureMap.h198
-rw-r--r--gfx/graphite2/src/inc/FeatureVal.h68
-rw-r--r--gfx/graphite2/src/inc/FileFace.h80
-rw-r--r--gfx/graphite2/src/inc/Font.h90
-rw-r--r--gfx/graphite2/src/inc/GlyphCache.h223
-rw-r--r--gfx/graphite2/src/inc/GlyphFace.h83
-rw-r--r--gfx/graphite2/src/inc/Intervals.h234
-rw-r--r--gfx/graphite2/src/inc/List.h168
-rw-r--r--gfx/graphite2/src/inc/Machine.h207
-rw-r--r--gfx/graphite2/src/inc/Main.h199
-rw-r--r--gfx/graphite2/src/inc/NameTable.h65
-rw-r--r--gfx/graphite2/src/inc/Pass.h118
-rw-r--r--gfx/graphite2/src/inc/Position.h68
-rw-r--r--gfx/graphite2/src/inc/Rule.h305
-rw-r--r--gfx/graphite2/src/inc/Segment.h236
-rw-r--r--gfx/graphite2/src/inc/Silf.h128
-rw-r--r--gfx/graphite2/src/inc/Slot.h170
-rw-r--r--gfx/graphite2/src/inc/Sparse.h168
-rw-r--r--gfx/graphite2/src/inc/TtfTypes.h419
-rw-r--r--gfx/graphite2/src/inc/TtfUtil.h208
-rw-r--r--gfx/graphite2/src/inc/UtfCodec.h251
-rw-r--r--gfx/graphite2/src/inc/bits.h150
-rw-r--r--gfx/graphite2/src/inc/debug.h89
-rw-r--r--gfx/graphite2/src/inc/json.h178
-rw-r--r--gfx/graphite2/src/inc/locale2lcid.h450
-rw-r--r--gfx/graphite2/src/inc/opcode_table.h124
-rw-r--r--gfx/graphite2/src/inc/opcodes.h691
36 files changed, 6560 insertions, 0 deletions
diff --git a/gfx/graphite2/src/inc/CharInfo.h b/gfx/graphite2/src/inc/CharInfo.h
new file mode 100644
index 0000000000..01e7e31ac9
--- /dev/null
+++ b/gfx/graphite2/src/inc/CharInfo.h
@@ -0,0 +1,66 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+#include "inc/Main.h"
+
+
+namespace graphite2 {
+
+class CharInfo
+{
+
+public:
+ CharInfo() : m_char(0), m_before(-1), m_after(-1), m_base(0), m_featureid(0), m_break(0), m_flags(0) {}
+ void init(int cid) { m_char = cid; }
+ unsigned int unicodeChar() const { return m_char; }
+ void feats(int offset) { m_featureid = offset; }
+ int fid() const { return m_featureid; }
+ int breakWeight() const { return m_break; }
+ void breakWeight(int val) { m_break = val; }
+ int after() const { return m_after; }
+ void after(int val) { m_after = val; }
+ int before() const { return m_before; }
+ void before(int val) { m_before = val; }
+ size_t base() const { return m_base; }
+ void base(size_t offset) { m_base = offset; }
+ void addflags(uint8 val) { m_flags |= val; }
+ uint8 flags() const { return m_flags; }
+
+ CLASS_NEW_DELETE
+private:
+ int m_char; // Unicode character from character stream
+ int m_before; // slot index before us, comes before
+ int m_after; // slot index after us, comes after
+ size_t m_base; // offset into input string corresponding to this charinfo
+ uint8 m_featureid; // index into features list in the segment
+ int8 m_break; // breakweight coming from lb table
+ uint8 m_flags; // 0,1 segment split.
+};
+
+} // namespace graphite2
+
+struct gr_char_info : public graphite2::CharInfo {};
diff --git a/gfx/graphite2/src/inc/CmapCache.h b/gfx/graphite2/src/inc/CmapCache.h
new file mode 100644
index 0000000000..7820c958b0
--- /dev/null
+++ b/gfx/graphite2/src/inc/CmapCache.h
@@ -0,0 +1,82 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include "inc/Main.h"
+#include "inc/Face.h"
+
+namespace graphite2 {
+
+class Face;
+
+class Cmap
+{
+public:
+
+ virtual ~Cmap() throw() {}
+
+ virtual uint16 operator [] (const uint32) const throw() { return 0; }
+
+ virtual operator bool () const throw() { return false; }
+
+ CLASS_NEW_DELETE;
+};
+
+class DirectCmap : public Cmap
+{
+ DirectCmap(const DirectCmap &);
+ DirectCmap & operator = (const DirectCmap &);
+
+public:
+ DirectCmap(const Face &);
+ virtual uint16 operator [] (const uint32 usv) const throw();
+ virtual operator bool () const throw();
+
+ CLASS_NEW_DELETE;
+private:
+ const Face::Table _cmap;
+ const void * _smp,
+ * _bmp;
+};
+
+class CachedCmap : public Cmap
+{
+ CachedCmap(const CachedCmap &);
+ CachedCmap & operator = (const CachedCmap &);
+
+public:
+ CachedCmap(const Face &);
+ virtual ~CachedCmap() throw();
+ virtual uint16 operator [] (const uint32 usv) const throw();
+ virtual operator bool () const throw();
+ CLASS_NEW_DELETE;
+private:
+ bool m_isBmpOnly;
+ uint16 ** m_blocks;
+};
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Code.h b/gfx/graphite2/src/inc/Code.h
new file mode 100644
index 0000000000..3cee67c81d
--- /dev/null
+++ b/gfx/graphite2/src/inc/Code.h
@@ -0,0 +1,171 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+// This class represents loaded graphite stack machine code. It performs
+// basic sanity checks, on the incoming code to prevent more obvious problems
+// from crashing graphite.
+// Author: Tim Eves
+
+#pragma once
+
+#include <cassert>
+#include <graphite2/Types.h>
+#include "inc/Main.h"
+#include "inc/Machine.h"
+
+namespace graphite2 {
+
+class Silf;
+class Face;
+
+enum passtype {
+ PASS_TYPE_UNKNOWN = 0,
+ PASS_TYPE_LINEBREAK,
+ PASS_TYPE_SUBSTITUTE,
+ PASS_TYPE_POSITIONING,
+ PASS_TYPE_JUSTIFICATION
+};
+
+namespace vm {
+
+class Machine::Code
+{
+public:
+ enum status_t
+ {
+ loaded,
+ alloc_failed,
+ invalid_opcode,
+ unimplemented_opcode_used,
+ out_of_range_data,
+ jump_past_end,
+ arguments_exhausted,
+ missing_return,
+ nested_context_item,
+ underfull_stack
+ };
+
+private:
+ class decoder;
+
+ instr * _code;
+ byte * _data;
+ size_t _data_size,
+ _instr_count;
+ byte _max_ref;
+ mutable status_t _status;
+ bool _constraint,
+ _modify,
+ _delete;
+ mutable bool _own;
+
+ void release_buffers() throw ();
+ void failure(const status_t) throw();
+
+public:
+ static size_t estimateCodeDataOut(size_t num_bytecodes, int nRules, int nSlots);
+
+ Code() throw();
+ Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
+ uint8 pre_context, uint16 rule_length, const Silf &, const Face &,
+ enum passtype pt, byte * * const _out = 0);
+ Code(const Machine::Code &) throw();
+ ~Code() throw();
+
+ Code & operator=(const Code &rhs) throw();
+ operator bool () const throw() { return _code && status() == loaded; }
+ status_t status() const throw() { return _status; }
+ bool constraint() const throw() { return _constraint; }
+ size_t dataSize() const throw() { return _data_size; }
+ size_t instructionCount() const throw() { return _instr_count; }
+ bool immutable() const throw() { return !(_delete || _modify); }
+ bool deletes() const throw() { return _delete; }
+ size_t maxRef() const throw() { return _max_ref; }
+ void externalProgramMoved(ptrdiff_t) throw();
+
+ int32 run(Machine &m, slotref * & map) const;
+
+ CLASS_NEW_DELETE;
+};
+
+inline
+size_t Machine::Code::estimateCodeDataOut(size_t n_bc, int nRules, int nSlots)
+{
+ // max is: all codes are instructions + 1 for each rule + max tempcopies
+ // allocate space for separate maximal code and data then merge them later
+ return (n_bc + nRules + nSlots) * sizeof(instr) + n_bc * sizeof(byte);
+}
+
+
+inline Machine::Code::Code() throw()
+: _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0),
+ _status(loaded), _constraint(false), _modify(false), _delete(false),
+ _own(false)
+{
+}
+
+inline Machine::Code::Code(const Machine::Code &obj) throw ()
+ : _code(obj._code),
+ _data(obj._data),
+ _data_size(obj._data_size),
+ _instr_count(obj._instr_count),
+ _max_ref(obj._max_ref),
+ _status(obj._status),
+ _constraint(obj._constraint),
+ _modify(obj._modify),
+ _delete(obj._delete),
+ _own(obj._own)
+{
+ obj._own = false;
+}
+
+inline Machine::Code & Machine::Code::operator=(const Machine::Code &rhs) throw() {
+ if (_instr_count > 0)
+ release_buffers();
+ _code = rhs._code;
+ _data = rhs._data;
+ _data_size = rhs._data_size;
+ _instr_count = rhs._instr_count;
+ _status = rhs._status;
+ _constraint = rhs._constraint;
+ _modify = rhs._modify;
+ _delete = rhs._delete;
+ _own = rhs._own;
+ rhs._own = false;
+ return *this;
+}
+
+inline void Machine::Code::externalProgramMoved(ptrdiff_t dist) throw()
+{
+ if (_code && !_own)
+ {
+ _code += dist / signed(sizeof(instr));
+ _data += dist;
+ }
+}
+
+} // namespace vm
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Collider.h b/gfx/graphite2/src/inc/Collider.h
new file mode 100644
index 0000000000..71e8400501
--- /dev/null
+++ b/gfx/graphite2/src/inc/Collider.h
@@ -0,0 +1,245 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include "inc/List.h"
+#include "inc/Position.h"
+#include "inc/Intervals.h"
+#include "inc/debug.h"
+
+namespace graphite2 {
+
+class json;
+class Slot;
+class Segment;
+
+#define SLOTCOLSETUINTPROP(x, y) uint16 x() const { return _ ##x; } void y (uint16 v) { _ ##x = v; }
+#define SLOTCOLSETINTPROP(x, y) int16 x() const { return _ ##x; } void y (int16 v) { _ ##x = v; }
+#define SLOTCOLSETPOSITIONPROP(x, y) const Position &x() const { return _ ##x; } void y (const Position &v) { _ ##x = v; }
+
+// Slot attributes related to collision-fixing
+class SlotCollision
+{
+public:
+ enum {
+ // COLL_TESTONLY = 0, // default - test other glyphs for collision with this one, but don't move this one
+ COLL_FIX = 1, // fix collisions involving this glyph
+ COLL_IGNORE = 2, // ignore this glyph altogether
+ COLL_START = 4, // start of range of possible collisions
+ COLL_END = 8, // end of range of possible collisions
+ COLL_KERN = 16, // collisions with this glyph are fixed by adding kerning space after it
+ COLL_ISCOL = 32, // this glyph has a collision
+ COLL_KNOWN = 64, // we've figured out what's happening with this glyph
+ COLL_ISSPACE = 128, // treat this glyph as a space with regard to kerning
+ COLL_TEMPLOCK = 256, // Lock glyphs that have been given priority positioning
+ ////COLL_JUMPABLE = 128, // moving glyphs may jump this stationary glyph in any direction - DELETE
+ ////COLL_OVERLAP = 256, // use maxoverlap to restrict - DELETE
+ };
+
+ // Behavior for the collision.order attribute. To GDL this is an enum, to us it's a bitfield, with only 1 bit set
+ // Allows for easier inversion.
+ enum {
+ SEQ_ORDER_LEFTDOWN = 1,
+ SEQ_ORDER_RIGHTUP = 2,
+ SEQ_ORDER_NOABOVE = 4,
+ SEQ_ORDER_NOBELOW = 8,
+ SEQ_ORDER_NOLEFT = 16,
+ SEQ_ORDER_NORIGHT = 32
+ };
+
+ SlotCollision(Segment *seg, Slot *slot);
+ void initFromSlot(Segment *seg, Slot *slot);
+
+ const Rect &limit() const { return _limit; }
+ void setLimit(const Rect &r) { _limit = r; }
+ SLOTCOLSETPOSITIONPROP(shift, setShift)
+ SLOTCOLSETPOSITIONPROP(offset, setOffset)
+ SLOTCOLSETPOSITIONPROP(exclOffset, setExclOffset)
+ SLOTCOLSETUINTPROP(margin, setMargin)
+ SLOTCOLSETUINTPROP(marginWt, setMarginWt)
+ SLOTCOLSETUINTPROP(flags, setFlags)
+ SLOTCOLSETUINTPROP(exclGlyph, setExclGlyph)
+ SLOTCOLSETUINTPROP(seqClass, setSeqClass)
+ SLOTCOLSETUINTPROP(seqProxClass, setSeqProxClass)
+ SLOTCOLSETUINTPROP(seqOrder, setSeqOrder)
+ SLOTCOLSETINTPROP(seqAboveXoff, setSeqAboveXoff)
+ SLOTCOLSETUINTPROP(seqAboveWt, setSeqAboveWt)
+ SLOTCOLSETINTPROP(seqBelowXlim, setSeqBelowXlim)
+ SLOTCOLSETUINTPROP(seqBelowWt, setSeqBelowWt)
+ SLOTCOLSETUINTPROP(seqValignHt, setSeqValignHt)
+ SLOTCOLSETUINTPROP(seqValignWt, setSeqValignWt)
+
+ float getKern(int dir) const;
+ bool ignore() const;
+
+private:
+ Rect _limit;
+ Position _shift; // adjustment within the given pass
+ Position _offset; // total adjustment for collisions
+ Position _exclOffset;
+ uint16 _margin;
+ uint16 _marginWt;
+ uint16 _flags;
+ uint16 _exclGlyph;
+ uint16 _seqClass;
+ uint16 _seqProxClass;
+ uint16 _seqOrder;
+ int16 _seqAboveXoff;
+ uint16 _seqAboveWt;
+ int16 _seqBelowXlim;
+ uint16 _seqBelowWt;
+ uint16 _seqValignHt;
+ uint16 _seqValignWt;
+
+}; // end of class SlotColllision
+
+struct BBox;
+struct SlantBox;
+
+class ShiftCollider
+{
+public:
+ typedef std::pair<float, float> fpair;
+ typedef Vector<fpair> vfpairs;
+ typedef vfpairs::iterator ivfpairs;
+
+ ShiftCollider(json *dbgout);
+ ~ShiftCollider() throw() { };
+
+ bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint,
+ float margin, float marginMin, const Position &currShift,
+ const Position &currOffset, int dir, GR_MAYBE_UNUSED json * const dbgout);
+ bool mergeSlot(Segment *seg, Slot *slot, const SlotCollision *cinfo, const Position &currShift, bool isAfter,
+ bool sameCluster, bool &hasCol, bool isExclusion, GR_MAYBE_UNUSED json * const dbgout);
+ Position resolve(Segment *seg, bool &isCol, GR_MAYBE_UNUSED json * const dbgout);
+ void addBox_slope(bool isx, const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, float weight, float m, bool minright, int mode);
+ void removeBox(const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, int mode);
+ const Position &origin() const { return _origin; }
+
+#if !defined GRAPHITE2_NTRACING
+ void outputJsonDbg(json * const dbgout, Segment *seg, int axis);
+ void outputJsonDbgStartSlot(json * const dbgout, Segment *seg);
+ void outputJsonDbgEndSlot(json * const dbgout, Position resultPos, int bestAxis, bool isCol);
+ void outputJsonDbgOneVector(json * const dbgout, Segment *seg, int axis, float tleft, float bestCost, float bestVal);
+ void outputJsonDbgRawRanges(json * const dbgout, int axis);
+ void outputJsonDbgRemovals(json * const dbgout, int axis, Segment *seg);
+#endif
+
+ CLASS_NEW_DELETE;
+
+protected:
+ Zones _ranges[4]; // possible movements in 4 directions (horizontally, vertically, diagonally);
+ Slot * _target; // the glyph to fix
+ Rect _limit;
+ Position _currShift;
+ Position _currOffset;
+ Position _origin; // Base for all relative calculations
+ float _margin;
+ float _marginWt;
+ float _len[4];
+ uint16 _seqClass;
+ uint16 _seqProxClass;
+ uint16 _seqOrder;
+
+ //bool _scraping[4];
+
+}; // end of class ShiftCollider
+
+inline
+ShiftCollider::ShiftCollider(GR_MAYBE_UNUSED json *dbgout)
+: _target(0),
+ _margin(0.0),
+ _marginWt(0.0),
+ _seqClass(0),
+ _seqProxClass(0),
+ _seqOrder(0)
+{
+#if !defined GRAPHITE2_NTRACING
+ for (int i = 0; i < 4; ++i)
+ _ranges[i].setdebug(dbgout);
+#endif
+}
+
+class KernCollider
+{
+public:
+ KernCollider(json *dbg);
+ ~KernCollider() throw() { };
+ bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint, float margin,
+ const Position &currShift, const Position &offsetPrev, int dir,
+ float ymin, float ymax, json * const dbgout);
+ bool mergeSlot(Segment *seg, Slot *slot, const Position &currShift, float currSpace, int dir, json * const dbgout);
+ Position resolve(Segment *seg, Slot *slot, int dir, json * const dbgout);
+ void shift(const Position &mv, int dir);
+
+ CLASS_NEW_DELETE;
+
+private:
+ Slot * _target; // the glyph to fix
+ Rect _limit;
+ float _margin;
+ Position _offsetPrev; // kern from a previous pass
+ Position _currShift; // NOT USED??
+ float _miny; // y-coordinates offset by global slot position
+ float _maxy;
+ Vector<float> _edges; // edges of horizontal slices
+ float _sliceWidth; // width of each slice
+ float _mingap;
+ float _xbound; // max or min edge
+ bool _hit;
+
+#if !defined GRAPHITE2_NTRACING
+ // Debugging
+ Segment * _seg;
+ Vector<float> _nearEdges; // closest potential collision in each slice
+ Vector<Slot*> _slotNear;
+#endif
+}; // end of class KernCollider
+
+
+inline
+float sqr(float x) {
+ return x * x;
+}
+
+inline
+KernCollider::KernCollider(GR_MAYBE_UNUSED json *dbg)
+: _target(0),
+ _margin(0.0f),
+ _miny(-1e38f),
+ _maxy(1e38f),
+ _sliceWidth(0.0f),
+ _mingap(0.0f),
+ _xbound(0.0),
+ _hit(false)
+{
+#if !defined GRAPHITE2_NTRACING
+ _seg = 0;
+#endif
+};
+
+}; // end of namespace graphite2
diff --git a/gfx/graphite2/src/inc/Compression.h b/gfx/graphite2/src/inc/Compression.h
new file mode 100644
index 0000000000..9fe10e025d
--- /dev/null
+++ b/gfx/graphite2/src/inc/Compression.h
@@ -0,0 +1,104 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2015, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+
+#pragma once
+
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+
+namespace
+{
+
+#if defined(_MSC_VER)
+typedef unsigned __int8 u8;
+typedef unsigned __int16 u16;
+typedef unsigned __int32 u32;
+typedef unsigned __int64 u64;
+#else
+#include <stdint.h>
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+#endif
+
+ptrdiff_t const MINMATCH = 4,
+ LASTLITERALS = 5,
+ MINCODA = LASTLITERALS+1,
+ MINSRCSIZE = 13;
+
+template<int S>
+inline
+void unaligned_copy(void * d, void const * s) {
+ ::memcpy(d, s, S);
+}
+
+inline
+size_t align(size_t p) {
+ return (p + sizeof(unsigned long)-1) & ~(sizeof(unsigned long)-1);
+}
+
+inline
+u8 * safe_copy(u8 * d, u8 const * s, size_t n) {
+ while (n--) *d++ = *s++;
+ return d;
+}
+
+inline
+u8 * overrun_copy(u8 * d, u8 const * s, size_t n) {
+ size_t const WS = sizeof(unsigned long);
+ u8 const * e = s + n;
+ do
+ {
+ unaligned_copy<WS>(d, s);
+ d += WS;
+ s += WS;
+ }
+ while (s < e);
+ d-=(s-e);
+
+ return d;
+}
+
+
+inline
+u8 * fast_copy(u8 * d, u8 const * s, size_t n) {
+ size_t const WS = sizeof(unsigned long);
+ size_t wn = n/WS;
+ while (wn--)
+ {
+ unaligned_copy<WS>(d, s);
+ d += WS;
+ s += WS;
+ }
+ n &= WS-1;
+ return safe_copy(d, s, n);
+}
+
+
+} // end of anonymous namespace
diff --git a/gfx/graphite2/src/inc/Decompressor.h b/gfx/graphite2/src/inc/Decompressor.h
new file mode 100644
index 0000000000..10f21b7af1
--- /dev/null
+++ b/gfx/graphite2/src/inc/Decompressor.h
@@ -0,0 +1,54 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2015, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+
+#pragma once
+
+#include <cstddef>
+
+namespace lz4
+{
+
+// decompress an LZ4 block
+// Parameters:
+// @in - Input buffer containing an LZ4 block.
+// @in_size - Size of the input LZ4 block in bytes.
+// @out - Output buffer to hold decompressed results.
+// @out_size - The size of the buffer pointed to by @out.
+// Invariants:
+// @in - This buffer must be at least 1 machine word in length,
+// regardless of the actual LZ4 block size.
+// @in_size - This must be at least 4 and must also be <= to the
+// allocated buffer @in.
+// @out - This must be bigger than the input buffer and at least
+// 13 bytes.
+// @out_size - Must always be big enough to hold the expected size.
+// Return:
+// -1 - Decompression failed.
+// size - Actual number of bytes decompressed.
+int decompress(void const *in, size_t in_size, void *out, size_t out_size);
+
+} // end of namespace shrinker
diff --git a/gfx/graphite2/src/inc/Endian.h b/gfx/graphite2/src/inc/Endian.h
new file mode 100644
index 0000000000..56ecfd8667
--- /dev/null
+++ b/gfx/graphite2/src/inc/Endian.h
@@ -0,0 +1,111 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2011, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+
+/*
+Description:
+ A set of fast template based decoders for decoding values of any C integer
+ type up to long int size laid out with most significant byte first or least
+ significant byte first (aka big endian or little endian). These are CPU
+ byte order agnostic and will function the same regardless of the CPUs native
+ byte order.
+
+ Being template based means if the either le or be class is not used then
+ template code of unused functions will not be instantiated by the compiler
+ and thus shouldn't cause any overhead.
+*/
+
+#include <cstddef>
+
+#pragma once
+
+
+class be
+{
+ template<int S>
+ inline static unsigned long int _peek(const unsigned char * p) {
+ return _peek<S/2>(p) << (S/2)*8 | _peek<S/2>(p+S/2);
+ }
+public:
+ template<typename T>
+ inline static T peek(const void * p) {
+ return T(_peek<sizeof(T)>(static_cast<const unsigned char *>(p)));
+ }
+
+ template<typename T>
+ inline static T read(const unsigned char * &p) {
+ const T r = T(_peek<sizeof(T)>(p));
+ p += sizeof r;
+ return r;
+ }
+
+ template<typename T>
+ inline static T swap(const T x) {
+ return T(_peek<sizeof(T)>(reinterpret_cast<const unsigned char *>(&x)));
+ }
+
+ template<typename T>
+ inline static void skip(const unsigned char * &p, size_t n=1) {
+ p += sizeof(T)*n;
+ }
+};
+
+template<>
+inline unsigned long int be::_peek<1>(const unsigned char * p) { return *p; }
+
+
+class le
+{
+ template<int S>
+ inline static unsigned long int _peek(const unsigned char * p) {
+ return _peek<S/2>(p) | _peek<S/2>(p+S/2) << (S/2)*8;
+ }
+public:
+ template<typename T>
+ inline static T peek(const void * p) {
+ return T(_peek<sizeof(T)>(static_cast<const unsigned char *>(p)));
+ }
+
+ template<typename T>
+ inline static T read(const unsigned char * &p) {
+ const T r = T(_peek<sizeof(T)>(p));
+ p += sizeof r;
+ return r;
+ }
+
+ template<typename T>
+ inline static T swap(const T x) {
+ return T(_peek<sizeof(T)>(reinterpret_cast<const unsigned char *>(&x)));
+ }
+
+ template<typename T>
+ inline static void skip(const unsigned char * &p, size_t n=1) {
+ p += sizeof(T)*n;
+ }
+};
+
+template<>
+inline unsigned long int le::_peek<1>(const unsigned char * p) { return *p; }
diff --git a/gfx/graphite2/src/inc/Error.h b/gfx/graphite2/src/inc/Error.h
new file mode 100644
index 0000000000..2b7ab763a2
--- /dev/null
+++ b/gfx/graphite2/src/inc/Error.h
@@ -0,0 +1,134 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2013, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+// numbers are explicitly assigned for future proofing
+
+namespace graphite2
+{
+
+class Error
+{
+public:
+ Error() : _e(0) {};
+ operator bool() { return (_e != 0); }
+ int error() { return _e; }
+ void error(int e) { _e = e; }
+ bool test(bool pr, int err) { return (_e = int(pr) * err); }
+
+private:
+ int _e;
+};
+
+enum errcontext {
+ EC_READGLYPHS = 1, // while reading glyphs
+ EC_READSILF = 2, // in Silf table
+ EC_ASILF = 3, // in Silf %d
+ EC_APASS = 4, // in Silf %d, pass %d
+ EC_PASSCCODE = 5, // in pass constraint code for Silf %d, pass %d
+ EC_ARULE = 6, // in Silf %d, pass %d, rule %d
+ EC_ASTARTS = 7, // in Silf %d, pass %d, start state %d
+ EC_ATRANS = 8, // in Silf %d, pass %d, fsm state %d
+ EC_ARULEMAP = 9 // in Silf %d, pass %d, state %d
+};
+
+enum errors {
+ E_OUTOFMEM = 1, // Out of memory
+ E_NOGLYPHS = 2, // There are no glyphs in the font
+ E_BADUPEM = 3, // The units per em for the font is bad (0)
+ E_BADCMAP = 4, // The font does not contain any useful cmaps
+ E_NOSILF = 5, // Missing Silf table
+ E_TOOOLD = 6, // Silf table version is too old
+ E_BADSIZE = 7, // context object has the wrong structural size
+// Silf Subtable Errors take a Silf subtable number * 256 in the context
+ E_BADMAXGLYPH = 8, // Silf max glyph id is too high
+ E_BADNUMJUSTS = 9, // Number of Silf justification blocks is too high
+ E_BADENDJUSTS = 10, // Silf justification blocks take too much of the Silf table space
+ E_BADCRITFEATURES = 11, // Critical features section in a Silf table is too big
+ E_BADSCRIPTTAGS = 12, // Silf script tags area is too big
+ E_BADAPSEUDO = 13, // The pseudo glyph attribute number is too high
+ E_BADABREAK = 14, // The linebreak glyph attribute number is too high
+ E_BADABIDI = 15, // The bidi glyph attribute number is too high
+ E_BADAMIRROR = 16, // The mirrored glyph attribute number is too high
+ E_BADNUMPASSES = 17, // The number of passes is > 128
+ E_BADPASSESSTART = 18, // The Silf table is too small to hold any passes
+ E_BADPASSBOUND = 19, // The positioning pass number is too low or the substitution pass number is too high
+ E_BADPPASS = 20, // The positioning pass number is too high
+ E_BADSPASS = 21, // the substitution pass number is too high
+ E_BADJPASSBOUND = 22, // the justification pass must be higher than the positioning pass
+ E_BADJPASS = 23, // the justification pass is too high
+ E_BADALIG = 24, // the number of initial ligature component glyph attributes is too high
+ E_BADBPASS = 25, // the bidi pass number is specified and is either too high or too low
+ E_BADNUMPSEUDO = 26, // The number of pseudo glyphs is too high
+ E_BADCLASSSIZE = 27, // The size of the classes block is bad
+ E_TOOMANYLINEAR = 28, // The number of linear classes in the silf table is too high
+ E_CLASSESTOOBIG = 29, // There are too many classes for the space allocated in the Silf subtable
+ E_MISALIGNEDCLASSES = 30, // The class offsets in the class table don't line up with the number of classes
+ E_HIGHCLASSOFFSET = 31, // The class offsets point out of the class table
+ E_BADCLASSOFFSET = 32, // A class offset is less than one following it
+ E_BADCLASSLOOKUPINFO = 33, // The search header info for a non-linear class has wrong values in it
+// Pass subtable errors. Context has pass number * 65536
+ E_BADPASSSTART = 34, // The start offset for a particular pass is bad
+ E_BADPASSEND = 35, // The end offset for a particular pass is bad
+ E_BADPASSLENGTH = 36, // The length of the pass is too small
+ E_BADNUMTRANS = 37, // The number of transition states in the fsm is bad
+ E_BADNUMSUCCESS = 38, // The number of success states in the fsm is bad
+ E_BADNUMSTATES = 39, // The number of states in the fsm is bad
+ E_NORANGES = 40, // There are no columns in the fsm
+ E_BADRULEMAPLEN = 41, // The size of the success state to rule mapping is bad
+ E_BADCTXTLENBOUNDS = 42, // The precontext maximum is greater than its minimum
+ E_BADCTXTLENS = 43, // The lists of rule lengths or pre context lengths is bad
+ E_BADPASSCCODEPTR = 44, // The pass constraint code position does not align with where the forward reference says it should be
+ E_BADRULECCODEPTR = 45, // The rule constraint code position does not align with where the forward reference says it should be
+ E_BADCCODELEN = 46, // Bad rule/pass constraint code length
+ E_BADACTIONCODEPTR = 47, // The action code position does not align with where the forward reference says it should be
+ E_MUTABLECCODE = 48, // Constraint code edits slots. It shouldn't.
+ E_BADSTATE = 49, // Bad state transition referencing an illegal state
+ E_BADRULEMAPPING = 50, // The structure of the rule mapping is bad
+ E_BADRANGE = 51, // Bad column range structure including a glyph in more than one column
+ E_BADRULENUM = 52, // A reference to a rule is out of range (too high)
+ E_BADACOLLISION = 53, // Bad Silf table collision attribute number (too high)
+ E_BADEMPTYPASS = 54, // Can't have empty passes (no rules) except for collision passes
+ E_BADSILFVERSION = 55, // The Silf table has a bad version (probably too high)
+ E_BADCOLLISIONPASS = 56, // Collision flags set on a non positioning pass
+ E_BADNUMCOLUMNS = 57, // Arbitrarily limit number of columns in fsm
+// Code errors
+ E_CODEFAILURE = 60, // Base code error. The following subcodes must align with Machine::Code::status_t in Code.h
+ E_CODEALLOC = 61, // Out of memory
+ E_INVALIDOPCODE = 62, // Invalid op code
+ E_UNIMPOPCODE = 63, // Unimplemented op code encountered
+ E_OUTOFRANGECODE = 64, // Code argument out of range
+ E_BADJUMPCODE = 65, // Code jumps past end of op codes
+ E_CODEBADARGS = 66, // Code arguments exhausted
+ E_CODENORETURN = 67, // Missing return type op code at end of code
+ E_CODENESTEDCTXT = 68, // Nested context encountered in code
+// Compression errors
+ E_BADSCHEME = 69,
+ E_SHRINKERFAILED = 70,
+};
+
+}
diff --git a/gfx/graphite2/src/inc/Face.h b/gfx/graphite2/src/inc/Face.h
new file mode 100644
index 0000000000..355c5aa0d3
--- /dev/null
+++ b/gfx/graphite2/src/inc/Face.h
@@ -0,0 +1,225 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include <cstdio>
+
+#include "graphite2/Font.h"
+
+#include "inc/Main.h"
+#include "inc/FeatureMap.h"
+#include "inc/TtfUtil.h"
+#include "inc/Silf.h"
+#include "inc/Error.h"
+
+namespace graphite2 {
+
+class Cmap;
+class FileFace;
+class GlyphCache;
+class NameTable;
+class json;
+class Font;
+
+
+using TtfUtil::Tag;
+
+// These are the actual tags, as distinct from the consecutive IDs in TtfUtil.h
+
+class Face
+{
+ // Prevent any kind of copying
+ Face(const Face&);
+ Face& operator=(const Face&);
+
+public:
+ class Table;
+ static float default_glyph_advance(const void* face_ptr, gr_uint16 glyphid);
+
+ Face(const void* appFaceHandle/*non-NULL*/, const gr_face_ops & ops);
+ virtual ~Face();
+
+ virtual bool runGraphite(Segment *seg, const Silf *silf) const;
+
+public:
+ bool readGlyphs(uint32 faceOptions);
+ bool readGraphite(const Table & silf);
+ bool readFeatures();
+ void takeFileFace(FileFace* pFileFace/*takes ownership*/);
+
+ const SillMap & theSill() const;
+ const GlyphCache & glyphs() const;
+ Cmap & cmap() const;
+ NameTable * nameTable() const;
+ void setLogger(FILE *log_file);
+ json * logger() const throw();
+
+ const Silf * chooseSilf(uint32 script) const;
+ uint16 languageForLocale(const char * locale) const;
+
+ // Features
+ uint16 numFeatures() const;
+ const FeatureRef * featureById(uint32 id) const;
+ const FeatureRef * feature(uint16 index) const;
+
+ // Glyph related
+ int32 getGlyphMetric(uint16 gid, uint8 metric) const;
+ uint16 findPseudo(uint32 uid) const;
+
+ // Errors
+ unsigned int error() const { return m_error; }
+ bool error(Error e) { m_error = e.error(); return false; }
+ unsigned int error_context() const { return m_error; }
+ void error_context(unsigned int errcntxt) { m_errcntxt = errcntxt; }
+
+ CLASS_NEW_DELETE;
+private:
+ SillMap m_Sill;
+ gr_face_ops m_ops;
+ const void * m_appFaceHandle; // non-NULL
+ FileFace * m_pFileFace; //owned
+ mutable GlyphCache * m_pGlyphFaceCache; // owned - never NULL
+ mutable Cmap * m_cmap; // cmap cache if available
+ mutable NameTable * m_pNames;
+ mutable json * m_logger;
+ unsigned int m_error;
+ unsigned int m_errcntxt;
+protected:
+ Silf * m_silfs; // silf subtables.
+ uint16 m_numSilf; // num silf subtables in the silf table
+private:
+ uint16 m_ascent,
+ m_descent;
+#ifdef GRAPHITE2_TELEMETRY
+public:
+ mutable telemetry tele;
+#endif
+};
+
+
+
+inline
+const SillMap & Face::theSill() const
+{
+ return m_Sill;
+}
+
+inline
+uint16 Face::numFeatures() const
+{
+ return m_Sill.theFeatureMap().numFeats();
+}
+
+inline
+const FeatureRef * Face::featureById(uint32 id) const
+{
+ return m_Sill.theFeatureMap().findFeatureRef(id);
+}
+
+inline
+const FeatureRef *Face::feature(uint16 index) const
+{
+ return m_Sill.theFeatureMap().feature(index);
+}
+
+inline
+const GlyphCache & Face::glyphs() const
+{
+ return *m_pGlyphFaceCache;
+}
+
+inline
+Cmap & Face::cmap() const
+{
+ return *m_cmap;
+};
+
+inline
+json * Face::logger() const throw()
+{
+ return m_logger;
+}
+
+
+
+class Face::Table
+{
+ const Face * _f;
+ mutable const byte * _p;
+ size_t _sz;
+ bool _compressed;
+
+ Error decompress();
+
+ void release();
+
+public:
+ Table() throw();
+ Table(const Face & face, const Tag n, uint32 version=0xffffffff) throw();
+ ~Table() throw();
+ Table(const Table && rhs) throw();
+
+ operator const byte * () const throw();
+
+ size_t size() const throw();
+ Table & operator = (const Table && rhs) throw();
+};
+
+inline
+Face::Table::Table() throw()
+: _f(0), _p(0), _sz(0), _compressed(false)
+{
+}
+
+inline
+Face::Table::Table(const Table && rhs) throw()
+: _f(rhs._f), _p(rhs._p), _sz(rhs._sz), _compressed(rhs._compressed)
+{
+ rhs._p = 0;
+}
+
+inline
+Face::Table::~Table() throw()
+{
+ release();
+}
+
+inline
+Face::Table::operator const byte * () const throw()
+{
+ return _p;
+}
+
+inline
+size_t Face::Table::size() const throw()
+{
+ return _sz;
+}
+
+} // namespace graphite2
+
+struct gr_face : public graphite2::Face {};
diff --git a/gfx/graphite2/src/inc/FeatureMap.h b/gfx/graphite2/src/inc/FeatureMap.h
new file mode 100644
index 0000000000..0f05e941a2
--- /dev/null
+++ b/gfx/graphite2/src/inc/FeatureMap.h
@@ -0,0 +1,198 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+#include "inc/Main.h"
+#include "inc/FeatureVal.h"
+
+namespace graphite2 {
+
+// Forward declarations for implmentation types
+class FeatureMap;
+class Face;
+
+
+class FeatureSetting
+{
+public:
+ FeatureSetting(int16 theValue, uint16 labelId) : m_label(labelId), m_value(theValue) {};
+ uint16 label() const { return m_label; }
+ int16 value() const { return m_value; }
+
+ CLASS_NEW_DELETE;
+private:
+ FeatureSetting(const FeatureSetting & fs) : m_label(fs.m_label), m_value(fs.m_value) {};
+
+ uint16 m_label;
+ int16 m_value;
+};
+
+class FeatureRef
+{
+ typedef uint32 chunk_t;
+ static const uint8 SIZEOF_CHUNK = sizeof(chunk_t)*8;
+
+public:
+ enum flags_t : uint16 {
+ HIDDEN = 0x0800
+ };
+ FeatureRef() throw();
+ FeatureRef(const Face & face, unsigned short & bits_offset, uint32 max_val,
+ uint32 name, uint16 uiName, flags_t flags,
+ FeatureSetting *settings, uint16 num_set) throw();
+ ~FeatureRef() throw();
+
+ bool applyValToFeature(uint32 val, Features& pDest) const; //defined in GrFaceImp.h
+ void maskFeature(Features & pDest) const {
+ if (m_index < pDest.size()) //defensive
+ pDest[m_index] |= m_mask;
+ }
+
+ uint32 getFeatureVal(const Features& feats) const; //defined in GrFaceImp.h
+
+ uint32 getId() const { return m_id; }
+ uint16 getNameId() const { return m_nameid; }
+ uint16 getNumSettings() const { return m_numSet; }
+ uint16 getSettingName(uint16 index) const { return m_nameValues[index].label(); }
+ int16 getSettingValue(uint16 index) const { return m_nameValues[index].value(); }
+ flags_t getFlags() const { return m_flags; }
+ uint32 maxVal() const { return m_max; }
+ const Face & getFace() const { assert(m_face); return *m_face;}
+ const FeatureMap* getFeatureMap() const;// { return m_pFace;}
+
+ CLASS_NEW_DELETE;
+private:
+ FeatureRef(const FeatureRef & rhs);
+
+ const Face * m_face;
+ FeatureSetting * m_nameValues; // array of name table ids for feature values
+ chunk_t m_mask, // bit mask to get the value from the vector
+ m_max; // max value the value can take
+ uint32 m_id; // feature identifier/name
+ uint16 m_nameid, // Name table id for feature name
+ m_numSet; // number of values (number of entries in m_nameValues)
+ flags_t m_flags; // feature flags see FeatureRef::flags_t.
+ byte m_bits, // how many bits to shift the value into place
+ m_index; // index into the array to find the ulong to mask
+
+private: //unimplemented
+ FeatureRef& operator=(const FeatureRef&);
+};
+
+inline
+FeatureRef::FeatureRef() throw()
+: m_face(0),
+ m_nameValues(0),
+ m_mask(0), m_max(0),
+ m_id(0), m_nameid(0), m_numSet(0),
+ m_flags(flags_t(0)),
+ m_bits(0), m_index(0)
+{
+}
+
+
+class NameAndFeatureRef
+{
+ public:
+ NameAndFeatureRef(uint32 name = 0) : m_name(name) , m_pFRef(NULL){}
+ NameAndFeatureRef(FeatureRef const & p) : m_name(p.getId()), m_pFRef(&p) {}
+
+ bool operator<(const NameAndFeatureRef& rhs) const //orders by m_name
+ { return m_name<rhs.m_name; }
+
+ CLASS_NEW_DELETE
+
+ uint32 m_name;
+ const FeatureRef* m_pFRef;
+};
+
+class FeatureMap
+{
+public:
+ FeatureMap() : m_numFeats(0), m_feats(NULL), m_pNamedFeats(NULL) {}
+ ~FeatureMap() { delete[] m_feats; delete[] m_pNamedFeats; }
+
+ bool readFeats(const Face & face);
+ const FeatureRef *findFeatureRef(uint32 name) const;
+ FeatureRef *feature(uint16 index) const { return m_feats + index; }
+ //GrFeatureRef *featureRef(byte index) { return index < m_numFeats ? m_feats + index : NULL; }
+ const FeatureRef *featureRef(byte index) const { return index < m_numFeats ? m_feats + index : NULL; }
+ FeatureVal* cloneFeatures(uint32 langname/*0 means default*/) const; //call destroy_Features when done.
+ uint16 numFeats() const { return m_numFeats; };
+ CLASS_NEW_DELETE
+private:
+friend class SillMap;
+ uint16 m_numFeats;
+
+ FeatureRef *m_feats;
+ NameAndFeatureRef* m_pNamedFeats; //owned
+ FeatureVal m_defaultFeatures; //owned
+
+private: //defensive on m_feats, m_pNamedFeats, and m_defaultFeatures
+ FeatureMap(const FeatureMap&);
+ FeatureMap& operator=(const FeatureMap&);
+};
+
+
+class SillMap
+{
+private:
+ class LangFeaturePair
+ {
+ LangFeaturePair(const LangFeaturePair &);
+ LangFeaturePair & operator = (const LangFeaturePair &);
+
+ public:
+ LangFeaturePair() : m_lang(0), m_pFeatures(0) {}
+ ~LangFeaturePair() { delete m_pFeatures; }
+
+ uint32 m_lang;
+ Features* m_pFeatures; //owns
+ CLASS_NEW_DELETE
+ };
+public:
+ SillMap() : m_langFeats(NULL), m_numLanguages(0) {}
+ ~SillMap() { delete[] m_langFeats; }
+ bool readFace(const Face & face);
+ bool readSill(const Face & face);
+ FeatureVal* cloneFeatures(uint32 langname/*0 means default*/) const; //call destroy_Features when done.
+ uint16 numLanguages() const { return m_numLanguages; };
+ uint32 getLangName(uint16 index) const { return (index < m_numLanguages)? m_langFeats[index].m_lang : 0; };
+
+ const FeatureMap & theFeatureMap() const { return m_FeatureMap; };
+private:
+ FeatureMap m_FeatureMap; //of face
+ LangFeaturePair * m_langFeats;
+ uint16 m_numLanguages;
+
+private: //defensive on m_langFeats
+ SillMap(const SillMap&);
+ SillMap& operator=(const SillMap&);
+};
+
+} // namespace graphite2
+
+struct gr_feature_ref : public graphite2::FeatureRef {};
diff --git a/gfx/graphite2/src/inc/FeatureVal.h b/gfx/graphite2/src/inc/FeatureVal.h
new file mode 100644
index 0000000000..cd3f93b2b5
--- /dev/null
+++ b/gfx/graphite2/src/inc/FeatureVal.h
@@ -0,0 +1,68 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+#include <cstring>
+#include <cassert>
+#include "inc/Main.h"
+#include "inc/List.h"
+
+namespace graphite2 {
+
+class FeatureRef;
+class FeatureMap;
+
+class FeatureVal : public Vector<uint32>
+{
+public:
+ FeatureVal() : m_pMap(0) { }
+ FeatureVal(int num, const FeatureMap & pMap) : Vector<uint32>(num), m_pMap(&pMap) {}
+ FeatureVal(const FeatureVal & rhs) : Vector<uint32>(rhs), m_pMap(rhs.m_pMap) {}
+
+ FeatureVal & operator = (const FeatureVal & rhs) { Vector<uint32>::operator = (rhs); m_pMap = rhs.m_pMap; return *this; }
+
+ bool operator ==(const FeatureVal & b) const
+ {
+ size_t n = size();
+ if (n != b.size()) return false;
+
+ for(const_iterator l = begin(), r = b.begin(); n && *l == *r; --n, ++l, ++r);
+
+ return n == 0;
+ }
+
+ CLASS_NEW_DELETE
+private:
+ friend class FeatureRef; //so that FeatureRefs can manipulate m_vec directly
+ const FeatureMap* m_pMap;
+};
+
+typedef FeatureVal Features;
+
+} // namespace graphite2
+
+
+struct gr_feature_val : public graphite2::FeatureVal {};
diff --git a/gfx/graphite2/src/inc/FileFace.h b/gfx/graphite2/src/inc/FileFace.h
new file mode 100644
index 0000000000..35927847f8
--- /dev/null
+++ b/gfx/graphite2/src/inc/FileFace.h
@@ -0,0 +1,80 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2012, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+//#include "inc/FeatureMap.h"
+//#include "inc/GlyphsCache.h"
+//#include "inc/Silf.h"
+
+#ifndef GRAPHITE2_NFILEFACE
+
+#include <cstdio>
+#include <cassert>
+
+#include "graphite2/Font.h"
+
+#include "inc/Main.h"
+#include "inc/TtfTypes.h"
+#include "inc/TtfUtil.h"
+
+namespace graphite2 {
+
+
+class FileFace
+{
+ static const void * get_table_fn(const void* appFaceHandle, unsigned int name, size_t *len);
+ static void rel_table_fn(const void* appFaceHandle, const void *table_buffer);
+
+public:
+ static const gr_face_ops ops;
+
+ FileFace(const char *filename);
+ ~FileFace();
+
+ operator bool () const throw();
+ CLASS_NEW_DELETE;
+
+private: //defensive
+ FILE * _file;
+ size_t _file_len;
+
+ TtfUtil::Sfnt::OffsetSubTable * _header_tbl;
+ TtfUtil::Sfnt::OffsetSubTable::Entry * _table_dir;
+
+ FileFace(const FileFace&);
+ FileFace& operator=(const FileFace&);
+};
+
+inline
+FileFace::operator bool() const throw()
+{
+ return _file && _header_tbl && _table_dir;
+}
+
+} // namespace graphite2
+
+#endif //!GRAPHITE2_NFILEFACE
diff --git a/gfx/graphite2/src/inc/Font.h b/gfx/graphite2/src/inc/Font.h
new file mode 100644
index 0000000000..9bc9ffb510
--- /dev/null
+++ b/gfx/graphite2/src/inc/Font.h
@@ -0,0 +1,90 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+#include <cassert>
+#include "graphite2/Font.h"
+#include "inc/Main.h"
+#include "inc/Face.h"
+
+namespace graphite2 {
+
+#define INVALID_ADVANCE -1e38f // can't be a static const because non-integral
+
+class Font
+{
+public:
+ Font(float ppm, const Face & face, const void * appFontHandle=0, const gr_font_ops * ops=0);
+ virtual ~Font();
+
+ float advance(unsigned short glyphid) const;
+ float scale() const;
+ bool isHinted() const;
+ const Face & face() const;
+ operator bool () const throw() { return m_advances; }
+
+ CLASS_NEW_DELETE;
+private:
+ gr_font_ops m_ops;
+ const void * const m_appFontHandle;
+ float * m_advances; // One advance per glyph in pixels. Nan if not defined
+ const Face & m_face;
+ float m_scale; // scales from design units to ppm
+ bool m_hinted;
+
+ Font(const Font&);
+ Font& operator=(const Font&);
+};
+
+inline
+float Font::advance(unsigned short glyphid) const
+{
+ if (m_advances[glyphid] == INVALID_ADVANCE)
+ m_advances[glyphid] = (*m_ops.glyph_advance_x)(m_appFontHandle, glyphid);
+ return m_advances[glyphid];
+}
+
+inline
+float Font::scale() const
+{
+ return m_scale;
+}
+
+inline
+bool Font::isHinted() const
+{
+ return m_hinted;
+}
+
+inline
+const Face & Font::face() const
+{
+ return m_face;
+}
+
+} // namespace graphite2
+
+struct gr_font : public graphite2::Font {};
diff --git a/gfx/graphite2/src/inc/GlyphCache.h b/gfx/graphite2/src/inc/GlyphCache.h
new file mode 100644
index 0000000000..7d5324e522
--- /dev/null
+++ b/gfx/graphite2/src/inc/GlyphCache.h
@@ -0,0 +1,223 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2012, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+
+#include "graphite2/Font.h"
+#include "inc/Main.h"
+#include "inc/Position.h"
+#include "inc/GlyphFace.h"
+
+namespace graphite2 {
+
+class Face;
+class FeatureVal;
+class Segment;
+
+
+struct SlantBox
+{
+ static const SlantBox empty;
+
+// SlantBox(float psi = 0., float pdi = 0., float psa = 0., float pda = 0.) : si(psi), di(pdi), sa(psa), da(pda) {};
+ float width() const { return sa - si; }
+ float height() const { return da - di; }
+ float si; // min
+ float di; // min
+ float sa; // max
+ float da; // max
+};
+
+
+struct BBox
+{
+ BBox(float pxi = 0, float pyi = 0., float pxa = 0., float pya = 0.) : xi(pxi), yi(pyi), xa(pxa), ya(pya) {};
+ float width() const { return xa - xi; }
+ float height() const { return ya - yi; }
+ float xi; // min
+ float yi; // min
+ float xa; // max
+ float ya; // max
+};
+
+
+class GlyphBox
+{
+ GlyphBox(const GlyphBox &);
+ GlyphBox & operator = (const GlyphBox &);
+
+public:
+ GlyphBox(uint8 numsubs, unsigned short bitmap, Rect *slanted) : _num(numsubs), _bitmap(bitmap), _slant(*slanted) {};
+
+ void addSubBox(int subindex, int boundary, Rect *val) { _subs[subindex * 2 + boundary] = *val; }
+ Rect &subVal(int subindex, int boundary) { return _subs[subindex * 2 + boundary]; }
+ const Rect &slant() const { return _slant; }
+ uint8 num() const { return _num; }
+ const Rect *subs() const { return _subs; }
+
+private:
+ uint8 _num;
+ unsigned short _bitmap;
+ Rect _slant;
+ Rect _subs[1];
+};
+
+class GlyphCache
+{
+ class Loader;
+
+ GlyphCache(const GlyphCache&);
+ GlyphCache& operator=(const GlyphCache&);
+
+public:
+ GlyphCache(const Face & face, const uint32 face_options);
+ ~GlyphCache();
+
+ unsigned short numGlyphs() const throw();
+ unsigned short numAttrs() const throw();
+ unsigned short unitsPerEm() const throw();
+
+ const GlyphFace *glyph(unsigned short glyphid) const; //result may be changed by subsequent call with a different glyphid
+ const GlyphFace *glyphSafe(unsigned short glyphid) const;
+ float getBoundingMetric(unsigned short glyphid, uint8 metric) const;
+ uint8 numSubBounds(unsigned short glyphid) const;
+ float getSubBoundingMetric(unsigned short glyphid, uint8 subindex, uint8 metric) const;
+ const Rect & slant(unsigned short glyphid) const { return _boxes[glyphid] ? _boxes[glyphid]->slant() : _empty_slant_box; }
+ const SlantBox & getBoundingSlantBox(unsigned short glyphid) const;
+ const BBox & getBoundingBBox(unsigned short glyphid) const;
+ const SlantBox & getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const;
+ const BBox & getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const;
+ bool check(unsigned short glyphid) const;
+ bool hasBoxes() const { return _boxes != 0; }
+
+ CLASS_NEW_DELETE;
+
+private:
+ const Rect _empty_slant_box;
+ const Loader * _glyph_loader;
+ const GlyphFace * * _glyphs;
+ GlyphBox * * _boxes;
+ unsigned short _num_glyphs,
+ _num_attrs,
+ _upem;
+};
+
+inline
+unsigned short GlyphCache::numGlyphs() const throw()
+{
+ return _num_glyphs;
+}
+
+inline
+unsigned short GlyphCache::numAttrs() const throw()
+{
+ return _num_attrs;
+}
+
+inline
+unsigned short GlyphCache::unitsPerEm() const throw()
+{
+ return _upem;
+}
+
+inline
+bool GlyphCache::check(unsigned short glyphid) const
+{
+ return _boxes && glyphid < _num_glyphs;
+}
+
+inline
+const GlyphFace *GlyphCache::glyphSafe(unsigned short glyphid) const
+{
+ return glyphid < _num_glyphs ? glyph(glyphid) : NULL;
+}
+
+inline
+float GlyphCache::getBoundingMetric(unsigned short glyphid, uint8 metric) const
+{
+ if (glyphid >= _num_glyphs) return 0.;
+ switch (metric) {
+ case 0: return (float)(glyph(glyphid)->theBBox().bl.x); // x_min
+ case 1: return (float)(glyph(glyphid)->theBBox().bl.y); // y_min
+ case 2: return (float)(glyph(glyphid)->theBBox().tr.x); // x_max
+ case 3: return (float)(glyph(glyphid)->theBBox().tr.y); // y_max
+ case 4: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().bl.x : 0.f); // sum_min
+ case 5: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().bl.y : 0.f); // diff_min
+ case 6: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().tr.x : 0.f); // sum_max
+ case 7: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().tr.y : 0.f); // diff_max
+ default: return 0.;
+ }
+}
+
+inline const SlantBox &GlyphCache::getBoundingSlantBox(unsigned short glyphid) const
+{
+ return _boxes[glyphid] ? *(SlantBox *)(&(_boxes[glyphid]->slant())) : SlantBox::empty;
+}
+
+inline const BBox &GlyphCache::getBoundingBBox(unsigned short glyphid) const
+{
+ return *(BBox *)(&(glyph(glyphid)->theBBox()));
+}
+
+inline
+float GlyphCache::getSubBoundingMetric(unsigned short glyphid, uint8 subindex, uint8 metric) const
+{
+ GlyphBox *b = _boxes[glyphid];
+ if (b == NULL || subindex >= b->num()) return 0;
+
+ switch (metric) {
+ case 0: return b->subVal(subindex, 0).bl.x;
+ case 1: return b->subVal(subindex, 0).bl.y;
+ case 2: return b->subVal(subindex, 0).tr.x;
+ case 3: return b->subVal(subindex, 0).tr.y;
+ case 4: return b->subVal(subindex, 1).bl.x;
+ case 5: return b->subVal(subindex, 1).bl.y;
+ case 6: return b->subVal(subindex, 1).tr.x;
+ case 7: return b->subVal(subindex, 1).tr.y;
+ default: return 0.;
+ }
+}
+
+inline const SlantBox &GlyphCache::getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const
+{
+ GlyphBox *b = _boxes[glyphid];
+ return *(SlantBox *)(b->subs() + 2 * subindex + 1);
+}
+
+inline const BBox &GlyphCache::getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const
+{
+ GlyphBox *b = _boxes[glyphid];
+ return *(BBox *)(b->subs() + 2 * subindex);
+}
+
+inline
+uint8 GlyphCache::numSubBounds(unsigned short glyphid) const
+{
+ return _boxes[glyphid] ? _boxes[glyphid]->num() : 0;
+}
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/GlyphFace.h b/gfx/graphite2/src/inc/GlyphFace.h
new file mode 100644
index 0000000000..fc29056146
--- /dev/null
+++ b/gfx/graphite2/src/inc/GlyphFace.h
@@ -0,0 +1,83 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include "inc/Main.h"
+#include "inc/Position.h"
+#include "inc/Sparse.h"
+
+namespace graphite2 {
+
+enum metrics {
+ kgmetLsb = 0, kgmetRsb,
+ kgmetBbTop, kgmetBbBottom, kgmetBbLeft, kgmetBbRight,
+ kgmetBbHeight, kgmetBbWidth,
+ kgmetAdvWidth, kgmetAdvHeight,
+ kgmetAscent, kgmetDescent
+};
+
+
+class GlyphFace
+{
+public:
+ GlyphFace();
+ template<typename I>
+ GlyphFace(const Rect & bbox, const Position & adv, I first, const I last);
+
+ const Position & theAdvance() const;
+ const Rect & theBBox() const { return m_bbox; }
+ const sparse & attrs() const { return m_attrs; }
+ int32 getMetric(uint8 metric) const;
+
+ CLASS_NEW_DELETE;
+private:
+ Rect m_bbox; // bounding box metrics in design units
+ Position m_advance; // Advance width and height in design units
+ sparse m_attrs;
+};
+
+
+// Inlines: class GlyphFace
+//
+inline
+GlyphFace::GlyphFace()
+{}
+
+template<typename I>
+GlyphFace::GlyphFace(const Rect & bbox, const Position & adv, I first, const I last)
+: m_bbox(bbox),
+ m_advance(adv),
+ m_attrs(first, last)
+{
+}
+
+inline
+const Position & GlyphFace::theAdvance() const {
+ return m_advance;
+}
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Intervals.h b/gfx/graphite2/src/inc/Intervals.h
new file mode 100644
index 0000000000..81d23187b6
--- /dev/null
+++ b/gfx/graphite2/src/inc/Intervals.h
@@ -0,0 +1,234 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include <utility>
+
+#include "inc/Main.h"
+#include "inc/List.h"
+#include "inc/json.h"
+#include "inc/Position.h"
+
+// An IntervalSet represents the possible movement of a given glyph in a given direction
+// (horizontally, vertically, or diagonally).
+// A vector is needed to represent disjoint ranges, eg, -300..-150, 20..200, 500..750.
+// Each pair represents the min/max of a sub-range.
+
+namespace graphite2 {
+
+class Segment;
+
+enum zones_t {SD, XY};
+
+class Zones
+{
+ struct Exclusion
+ {
+ template<zones_t O>
+ static Exclusion weighted(float xmin, float xmax, float f, float a0,
+ float m, float xi, float ai, float c, bool nega);
+
+ float x, // x position
+ xm, // xmax position
+ c, // constant + sum(MiXi^2)
+ sm, // sum(Mi)
+ smx; // sum(MiXi)
+ bool open;
+
+ Exclusion(float x, float w, float smi, float smxi, float c);
+ Exclusion & operator += (Exclusion const & rhs);
+ uint8 outcode(float p) const;
+
+ Exclusion split_at(float p);
+ void left_trim(float p);
+
+ bool track_cost(float & cost, float & x, float origin) const;
+
+ private:
+ float test_position(float origin) const;
+ float cost(float x) const;
+ };
+
+ typedef Vector<Exclusion> exclusions;
+
+ typedef exclusions::iterator iterator;
+ typedef Exclusion * pointer;
+ typedef Exclusion & reference;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+public:
+ typedef exclusions::const_iterator const_iterator;
+ typedef Exclusion const * const_pointer;
+ typedef Exclusion const & const_reference;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+#if !defined GRAPHITE2_NTRACING
+ struct Debug
+ {
+ Exclusion _excl;
+ bool _isdel;
+ Vector<void *> _env;
+
+ Debug(Exclusion *e, bool isdel, json *dbg) : _excl(*e), _isdel(isdel), _env(dbg->getenvs()) { };
+ };
+
+ typedef Vector<Debug> debugs;
+ typedef debugs::const_iterator idebugs;
+ void addDebug(Exclusion *e);
+ void removeDebug(float pos, float posm);
+ void setdebug(json *dbgout) { _dbg = dbgout; }
+ idebugs dbgs_begin() const { return _dbgs.begin(); }
+ idebugs dbgs_end() const { return _dbgs.end(); }
+ void jsonDbgOut(Segment *seg) const;
+ Position position() const { return Position(_pos, _posm); }
+#endif
+
+ Zones();
+ template<zones_t O>
+ void initialise(float xmin, float xmax, float margin_len, float margin_weight, float ao);
+
+ void exclude(float xmin, float xmax);
+ void exclude_with_margins(float xmin, float xmax, int axis);
+
+ template<zones_t O>
+ void weighted(float xmin, float xmax, float f, float a0, float mi, float xi, float ai, float c, bool nega);
+ void weightedAxis(int axis, float xmin, float xmax, float f, float a0, float mi, float xi, float ai, float c, bool nega);
+
+ float closest( float origin, float &cost) const;
+
+ const_iterator begin() const { return _exclusions.begin(); }
+ const_iterator end() const { return _exclusions.end(); }
+
+private:
+ exclusions _exclusions;
+#if !defined GRAPHITE2_NTRACING
+ json * _dbg;
+ debugs _dbgs;
+#endif
+ float _margin_len,
+ _margin_weight,
+ _pos,
+ _posm;
+
+ void insert(Exclusion e);
+ void remove(float x, float xm);
+ const_iterator find_exclusion_under(float x) const;
+};
+
+
+inline
+Zones::Zones()
+: _margin_len(0), _margin_weight(0), _pos(0), _posm(0)
+{
+#if !defined GRAPHITE2_NTRACING
+ _dbg = 0;
+#endif
+ _exclusions.reserve(8);
+}
+
+inline
+Zones::Exclusion::Exclusion(float x_, float xm_, float smi, float smxi, float c_)
+: x(x_), xm(xm_), c(c_), sm(smi), smx(smxi), open(false)
+{ }
+
+template<zones_t O>
+inline
+void Zones::initialise(float xmin, float xmax, float margin_len,
+ float margin_weight, float a0)
+{
+ _margin_len = margin_len;
+ _margin_weight = margin_weight;
+ _pos = xmin;
+ _posm = xmax;
+ _exclusions.clear();
+ _exclusions.push_back(Exclusion::weighted<O>(xmin, xmax, 1, a0, 0, 0, 0, 0, false));
+ _exclusions.front().open = true;
+#if !defined GRAPHITE2_NTRACING
+ _dbgs.clear();
+#endif
+}
+
+inline
+void Zones::exclude(float xmin, float xmax) {
+ remove(xmin, xmax);
+}
+
+template<zones_t O>
+inline
+void Zones::weighted(float xmin, float xmax, float f, float a0,
+ float m, float xi, float ai, float c, bool nega) {
+ insert(Exclusion::weighted<O>(xmin, xmax, f, a0, m, xi, ai, c, nega));
+}
+
+inline
+void Zones::weightedAxis(int axis, float xmin, float xmax, float f, float a0,
+ float m, float xi, float ai, float c, bool nega) {
+ if (axis < 2)
+ weighted<XY>(xmin, xmax, f, a0, m, xi, ai, c, nega);
+ else
+ weighted<SD>(xmin, xmax, f, a0, m, xi, ai, c, nega);
+}
+
+#if !defined GRAPHITE2_NTRACING
+inline
+void Zones::addDebug(Exclusion *e) {
+ if (_dbg)
+ _dbgs.push_back(Debug(e, false, _dbg));
+}
+
+inline
+void Zones::removeDebug(float pos, float posm) {
+ if (_dbg)
+ {
+ Exclusion e(pos, posm, 0, 0, 0);
+ _dbgs.push_back(Debug(&e, true, _dbg));
+ }
+}
+#endif
+
+template<>
+inline
+Zones::Exclusion Zones::Exclusion::weighted<XY>(float xmin, float xmax, float f, float a0,
+ float m, float xi, GR_MAYBE_UNUSED float ai, float c, GR_MAYBE_UNUSED bool nega) {
+ return Exclusion(xmin, xmax,
+ m + f,
+ m * xi,
+ m * xi * xi + f * a0 * a0 + c);
+}
+
+template<>
+inline
+Zones::Exclusion Zones::Exclusion::weighted<SD>(float xmin, float xmax, float f, float a0,
+ float m, float xi, float ai,float c, bool nega) {
+ float xia = nega ? xi - ai : xi + ai;
+ return Exclusion(xmin, xmax,
+ 0.25f * (m + 2.f * f),
+ 0.25f * m * xia,
+ 0.25f * (m * xia * xia + 2.f * f * a0 * a0) + c);
+}
+
+} // end of namespace graphite2
diff --git a/gfx/graphite2/src/inc/List.h b/gfx/graphite2/src/inc/List.h
new file mode 100644
index 0000000000..a3b7a77961
--- /dev/null
+++ b/gfx/graphite2/src/inc/List.h
@@ -0,0 +1,168 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+
+// designed to have a limited subset of the std::vector api
+#pragma once
+
+#include <cstddef>
+#include <cassert>
+#include <cstring>
+#include <cstdlib>
+#include <new>
+
+#include "Main.h"
+
+namespace graphite2 {
+
+template <typename T>
+inline
+ptrdiff_t distance(T* first, T* last) { return last-first; }
+
+
+template <typename T>
+class Vector
+{
+ T * m_first, *m_last, *m_end;
+public:
+ typedef T & reference;
+ typedef const T & const_reference;
+ typedef T * iterator;
+ typedef const T * const_iterator;
+
+ Vector() : m_first(0), m_last(0), m_end(0) {}
+ Vector(size_t n, const T& value = T()) : m_first(0), m_last(0), m_end(0) { insert(begin(), n, value); }
+ Vector(const Vector<T> &rhs) : m_first(0), m_last(0), m_end(0) { insert(begin(), rhs.begin(), rhs.end()); }
+ template <typename I>
+ Vector(I first, const I last) : m_first(0), m_last(0), m_end(0) { insert(begin(), first, last); }
+ ~Vector() { clear(); free(m_first); }
+
+ iterator begin() { return m_first; }
+ const_iterator begin() const { return m_first; }
+
+ iterator end() { return m_last; }
+ const_iterator end() const { return m_last; }
+
+ bool empty() const { return m_first == m_last; }
+ size_t size() const { return m_last - m_first; }
+ size_t capacity() const{ return m_end - m_first; }
+
+ void reserve(size_t n);
+ void resize(size_t n, const T & v = T());
+
+ reference front() { assert(size() > 0); return *begin(); }
+ const_reference front() const { assert(size() > 0); return *begin(); }
+ reference back() { assert(size() > 0); return *(end()-1); }
+ const_reference back() const { assert(size() > 0); return *(end()-1); }
+
+ Vector<T> & operator = (const Vector<T> & rhs) { assign(rhs.begin(), rhs.end()); return *this; }
+ reference operator [] (size_t n) { assert(size() > n); return m_first[n]; }
+ const_reference operator [] (size_t n) const { assert(size() > n); return m_first[n]; }
+
+ void assign(size_t n, const T& u) { clear(); insert(begin(), n, u); }
+ void assign(const_iterator first, const_iterator last) { clear(); insert(begin(), first, last); }
+ iterator insert(iterator p, const T & x) { p = _insert_default(p, 1); new (p) T(x); return p; }
+ void insert(iterator p, size_t n, const T & x);
+ void insert(iterator p, const_iterator first, const_iterator last);
+ void pop_back() { assert(size() > 0); --m_last; }
+ void push_back(const T &v) { if (m_last == m_end) reserve(size()+1); new (m_last++) T(v); }
+
+ void clear() { erase(begin(), end()); }
+ iterator erase(iterator p) { return erase(p, p+1); }
+ iterator erase(iterator first, iterator last);
+
+private:
+ iterator _insert_default(iterator p, size_t n);
+};
+
+template <typename T>
+inline
+void Vector<T>::reserve(size_t n)
+{
+ if (n > capacity())
+ {
+ const ptrdiff_t sz = size();
+ size_t requested;
+ if (checked_mul(n,sizeof(T), requested)) std::abort();
+ m_first = static_cast<T*>(realloc(m_first, requested));
+ if (!m_first) std::abort();
+ m_last = m_first + sz;
+ m_end = m_first + n;
+ }
+}
+
+template <typename T>
+inline
+void Vector<T>::resize(size_t n, const T & v) {
+ const ptrdiff_t d = n-size();
+ if (d < 0) erase(end()+d, end());
+ else if (d > 0) insert(end(), d, v);
+}
+
+template<typename T>
+inline
+typename Vector<T>::iterator Vector<T>::_insert_default(iterator p, size_t n)
+{
+ assert(begin() <= p && p <= end());
+ const ptrdiff_t i = p - begin();
+ reserve(((size() + n + 7) >> 3) << 3);
+ p = begin() + i;
+ // Move tail if there is one
+ if (p != end()) memmove(p + n, p, distance(p,end())*sizeof(T));
+ m_last += n;
+ return p;
+}
+
+template<typename T>
+inline
+void Vector<T>::insert(iterator p, size_t n, const T & x)
+{
+ p = _insert_default(p, n);
+ // Copy in elements
+ for (; n; --n, ++p) { new (p) T(x); }
+}
+
+template<typename T>
+inline
+void Vector<T>::insert(iterator p, const_iterator first, const_iterator last)
+{
+ p = _insert_default(p, distance(first, last));
+ // Copy in elements
+ for (;first != last; ++first, ++p) { new (p) T(*first); }
+}
+
+template<typename T>
+inline
+typename Vector<T>::iterator Vector<T>::erase(iterator first, iterator last)
+{
+ for (iterator e = first; e != last; ++e) e->~T();
+ const size_t sz = distance(first, last);
+ if (m_last != last) memmove(first, last, distance(last,end())*sizeof(T));
+ m_last -= sz;
+ return first;
+}
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Machine.h b/gfx/graphite2/src/inc/Machine.h
new file mode 100644
index 0000000000..b23819fb98
--- /dev/null
+++ b/gfx/graphite2/src/inc/Machine.h
@@ -0,0 +1,207 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+// This general interpreter interface.
+// Author: Tim Eves
+
+// Build one of direct_machine.cpp or call_machine.cpp to implement this
+// interface.
+
+#pragma once
+#include <cstring>
+#include <limits>
+#include <graphite2/Types.h>
+#include "inc/Main.h"
+
+#if defined(__GNUC__)
+#if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ * 10) < 430
+#define HOT
+#if defined(__x86_64)
+#define REGPARM(n) __attribute__((regparm(n)))
+#else
+#define REGPARM(n)
+#endif
+#else
+#define HOT __attribute__((hot))
+#if defined(__x86_64)
+#define REGPARM(n) __attribute__((hot, regparm(n)))
+#else
+#define REGPARM(n)
+#endif
+#endif
+#else
+#define HOT
+#define REGPARM(n)
+#endif
+
+#if defined(__MINGW32__)
+// MinGW's <limits> at some point includes winnt.h which #define's a
+// DELETE macro, which conflicts with enum opcode below, so we undefine
+// it here.
+#undef DELETE
+#endif
+
+namespace graphite2 {
+
+// Forward declarations
+class Segment;
+class Slot;
+class SlotMap;
+
+
+namespace vm
+{
+
+
+typedef void * instr;
+typedef Slot * slotref;
+
+enum {VARARGS = 0xff, MAX_NAME_LEN=32};
+
+enum opcode {
+ NOP = 0,
+
+ PUSH_BYTE, PUSH_BYTEU, PUSH_SHORT, PUSH_SHORTU, PUSH_LONG,
+
+ ADD, SUB, MUL, DIV,
+ MIN_, MAX_,
+ NEG,
+ TRUNC8, TRUNC16,
+
+ COND,
+
+ AND, OR, NOT,
+ EQUAL, NOT_EQ,
+ LESS, GTR, LESS_EQ, GTR_EQ,
+
+ NEXT, NEXT_N, COPY_NEXT,
+ PUT_GLYPH_8BIT_OBS, PUT_SUBS_8BIT_OBS, PUT_COPY,
+ INSERT, DELETE,
+ ASSOC,
+ CNTXT_ITEM,
+
+ ATTR_SET, ATTR_ADD, ATTR_SUB,
+ ATTR_SET_SLOT,
+ IATTR_SET_SLOT,
+ PUSH_SLOT_ATTR, PUSH_GLYPH_ATTR_OBS,
+ PUSH_GLYPH_METRIC, PUSH_FEAT,
+ PUSH_ATT_TO_GATTR_OBS, PUSH_ATT_TO_GLYPH_METRIC,
+ PUSH_ISLOT_ATTR,
+
+ PUSH_IGLYPH_ATTR, // not implemented
+
+ POP_RET, RET_ZERO, RET_TRUE,
+ IATTR_SET, IATTR_ADD, IATTR_SUB,
+ PUSH_PROC_STATE, PUSH_VERSION,
+ PUT_SUBS, PUT_SUBS2, PUT_SUBS3,
+ PUT_GLYPH, PUSH_GLYPH_ATTR, PUSH_ATT_TO_GLYPH_ATTR,
+ BITOR, BITAND, BITNOT,
+ BITSET, SET_FEAT,
+ MAX_OPCODE,
+ // private opcodes for internal use only, comes after all other on disk opcodes
+ TEMP_COPY = MAX_OPCODE
+};
+
+struct opcode_t
+{
+ instr impl[2];
+ uint8 param_sz;
+ char name[MAX_NAME_LEN];
+};
+
+
+class Machine
+{
+public:
+ typedef int32 stack_t;
+ static size_t const STACK_ORDER = 10,
+ STACK_MAX = 1 << STACK_ORDER,
+ STACK_GUARD = 2;
+
+ class Code;
+
+ enum status_t {
+ finished = 0,
+ stack_underflow,
+ stack_not_empty,
+ stack_overflow,
+ slot_offset_out_bounds,
+ died_early
+ };
+
+ Machine(SlotMap &) throw();
+ static const opcode_t * getOpcodeTable() throw();
+
+ CLASS_NEW_DELETE;
+
+ SlotMap & slotMap() const throw();
+ status_t status() const throw();
+// operator bool () const throw();
+
+private:
+ void check_final_stack(const stack_t * const sp);
+ stack_t run(const instr * program, const byte * data,
+ slotref * & map) HOT;
+
+ SlotMap & _map;
+ stack_t _stack[STACK_MAX + 2*STACK_GUARD];
+ status_t _status;
+};
+
+inline Machine::Machine(SlotMap & map) throw()
+: _map(map), _status(finished)
+{
+ // Initialise stack guard +1 entries as the stack pointer points to the
+ // current top of stack, hence the first push will never write entry 0.
+ // Initialising the guard space like this is unnecessary and is only
+ // done to keep valgrind happy during fuzz testing. Hopefully loop
+ // unrolling will flatten this.
+ for (size_t n = STACK_GUARD + 1; n; --n) _stack[n-1] = 0;
+}
+
+inline SlotMap& Machine::slotMap() const throw()
+{
+ return _map;
+}
+
+inline Machine::status_t Machine::status() const throw()
+{
+ return _status;
+}
+
+inline void Machine::check_final_stack(const stack_t * const sp)
+{
+ if (_status != finished) return;
+
+ stack_t const * const base = _stack + STACK_GUARD,
+ * const limit = base + STACK_MAX;
+ if (sp < base) _status = stack_underflow; // This should be impossible now.
+ else if (sp >= limit) _status = stack_overflow; // So should this.
+ else if (sp != base) _status = stack_not_empty;
+}
+
+} // namespace vm
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Main.h b/gfx/graphite2/src/inc/Main.h
new file mode 100644
index 0000000000..ebf02dd553
--- /dev/null
+++ b/gfx/graphite2/src/inc/Main.h
@@ -0,0 +1,199 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include <cstdlib>
+#include "graphite2/Types.h"
+
+#ifdef GRAPHITE2_CUSTOM_HEADER
+#include GRAPHITE2_CUSTOM_HEADER
+#endif
+
+namespace graphite2 {
+
+typedef gr_uint8 uint8;
+typedef gr_uint8 byte;
+typedef gr_uint16 uint16;
+typedef gr_uint32 uint32;
+typedef gr_int8 int8;
+typedef gr_int16 int16;
+typedef gr_int32 int32;
+typedef size_t uintptr;
+
+#ifdef GRAPHITE2_TELEMETRY
+struct telemetry
+{
+ class category;
+
+ static size_t * _category;
+ static void set_category(size_t & t) throw() { _category = &t; }
+ static void stop() throw() { _category = 0; }
+ static void count_bytes(size_t n) throw() { if (_category) *_category += n; }
+
+ size_t misc,
+ silf,
+ glyph,
+ code,
+ states,
+ starts,
+ transitions;
+
+ telemetry() : misc(0), silf(0), glyph(0), code(0), states(0), starts(0), transitions(0) {}
+};
+
+class telemetry::category
+{
+ size_t * _prev;
+public:
+ category(size_t & t) : _prev(_category) { _category = &t; }
+ ~category() { _category = _prev; }
+};
+
+#else
+struct telemetry {};
+#endif
+
+// Checked multiplaction to catch overflow or underflow when allocating memory
+#if defined(__has_builtin)
+ #if __has_builtin(__builtin_mul_overflow)
+ #define HAVE_BUILTIN_OVERFLOW
+ #endif
+#elif defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__INTEL_COMPILER)
+ #define HAVE_BUILTIN_OVERFLOW
+#endif
+#if defined(__has_include)
+ #if __has_include(<intsafe.h>) && !defined(__CYGWIN__)
+ #define HAVE_INTSAFE_H
+ #endif
+#elif defined(_WIN32)
+ #define HAVE_INTSAFE_H
+#endif
+
+// Need to import intsafe into the top level namespace
+#if defined(HAVE_INTSAFE_H)
+} // namespace graphite2
+
+#include <intsafe.h>
+
+namespace graphite2 {
+#endif
+
+#if defined(HAVE_BUILTIN_OVERFLOW)
+inline
+bool checked_mul(const size_t a, const size_t b, size_t & t) {
+ return __builtin_mul_overflow(a, b, &t);
+}
+#elif defined(HAVE_INTSAFE_H)
+inline
+bool checked_mul(const size_t a, const size_t b, size_t & t) {
+ return SizeTMult(a, b, &t) == INTSAFE_E_ARITHMETIC_OVERFLOW;
+}
+#else
+inline
+bool checked_mul(const size_t a, const size_t b, size_t & t) {
+ t = a*b;
+ return (((a | b) & (~size_t(0) << (sizeof(size_t) << 2))) && (t / a != b));
+}
+#endif
+
+// typesafe wrapper around malloc for simple types
+// use free(pointer) to deallocate
+
+template <typename T> T * gralloc(size_t n)
+{
+ size_t total;
+ if (checked_mul(n, sizeof(T), total))
+ return 0;
+#ifdef GRAPHITE2_TELEMETRY
+ telemetry::count_bytes(total);
+#endif
+ return static_cast<T*>(malloc(total));
+}
+
+template <typename T> T * grzeroalloc(size_t n)
+{
+#ifdef GRAPHITE2_TELEMETRY
+ telemetry::count_bytes(sizeof(T) * n);
+#endif
+ return static_cast<T*>(calloc(n, sizeof(T)));
+}
+
+template <typename T>
+inline T min(const T a, const T b)
+{
+ return a < b ? a : b;
+}
+
+template <typename T>
+inline T max(const T a, const T b)
+{
+ return a > b ? a : b;
+}
+
+} // namespace graphite2
+
+#define CLASS_NEW_DELETE \
+ void * operator new (size_t size){ return gralloc<byte>(size);} \
+ void * operator new (size_t, void * p) throw() { return p; } \
+ void * operator new[] (size_t size) {return gralloc<byte>(size);} \
+ void * operator new[] (size_t, void * p) throw() { return p; } \
+ void operator delete (void * p) throw() { free(p);} \
+ void operator delete (void *, void *) throw() {} \
+ void operator delete[] (void * p)throw() { free(p); } \
+ void operator delete[] (void *, void *) throw() {}
+
+#if defined(__GNUC__) || defined(__clang__)
+#define GR_MAYBE_UNUSED __attribute__((unused))
+#else
+#define GR_MAYBE_UNUSED
+#endif
+
+#ifndef __has_cpp_attribute
+# define __has_cpp_attribute(x) 0
+#endif
+
+#if __has_cpp_attribute(clang::fallthrough)
+# define GR_FALLTHROUGH [[clang::fallthrough]]
+#elif __has_cpp_attribute(gnu::fallthrough)
+# define GR_FALLTHROUGH [[gnu::fallthrough]]
+#elif defined(_MSC_VER)
+ /*
+ * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
+ * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
+ */
+ #include <sal.h>
+ #define GR_FALLTHROUGH __fallthrough
+#elif __GNUC__ >= 7
+ #define GR_FALLTHROUGH __attribute__ ((fallthrough))
+#else
+ #define GR_FALLTHROUGH /* fallthrough */
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4800)
+#pragma warning(disable: 4355)
+#endif
diff --git a/gfx/graphite2/src/inc/NameTable.h b/gfx/graphite2/src/inc/NameTable.h
new file mode 100644
index 0000000000..0fdbeb4d85
--- /dev/null
+++ b/gfx/graphite2/src/inc/NameTable.h
@@ -0,0 +1,65 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include <graphite2/Segment.h>
+#include "inc/TtfTypes.h"
+#include "inc/locale2lcid.h"
+
+namespace graphite2 {
+
+class NameTable
+{
+ NameTable(const NameTable &);
+ NameTable & operator = (const NameTable &);
+
+public:
+ NameTable(const void * data, size_t length, uint16 platfromId=3, uint16 encodingID = 1);
+ ~NameTable() { free(const_cast<TtfUtil::Sfnt::FontNames *>(m_table)); }
+ enum eNameFallback {
+ eNoFallback = 0,
+ eEnUSFallbackOnly = 1,
+ eEnOrAnyFallback = 2
+ };
+ uint16 setPlatformEncoding(uint16 platfromId=3, uint16 encodingID = 1);
+ void * getName(uint16 & languageId, uint16 nameId, gr_encform enc, uint32 & length);
+ uint16 getLanguageId(const char * bcp47Locale);
+
+ CLASS_NEW_DELETE
+private:
+ uint16 m_platformId;
+ uint16 m_encodingId;
+ uint16 m_languageCount;
+ uint16 m_platformOffset; // offset of first NameRecord with for platform 3, encoding 1
+ uint16 m_platformLastRecord;
+ uint16 m_nameDataLength;
+ const TtfUtil::Sfnt::FontNames * m_table;
+ const uint8 * m_nameData;
+ Locale2Lang m_locale2Lang;
+};
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Pass.h b/gfx/graphite2/src/inc/Pass.h
new file mode 100644
index 0000000000..e687a87d8c
--- /dev/null
+++ b/gfx/graphite2/src/inc/Pass.h
@@ -0,0 +1,118 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include <cstdlib>
+#include "inc/Code.h"
+
+namespace graphite2 {
+
+class Segment;
+class Face;
+class Silf;
+struct Rule;
+struct RuleEntry;
+struct State;
+class FiniteStateMachine;
+class Error;
+class ShiftCollider;
+class KernCollider;
+class json;
+
+enum passtype;
+
+class Pass
+{
+public:
+ Pass();
+ ~Pass();
+
+ bool readPass(const byte * pPass, size_t pass_length, size_t subtable_base, Face & face,
+ enum passtype pt, uint32 version, Error &e);
+ bool runGraphite(vm::Machine & m, FiniteStateMachine & fsm, bool reverse) const;
+ void init(Silf *silf) { m_silf = silf; }
+ byte collisionLoops() const { return m_numCollRuns; }
+ bool reverseDir() const { return m_isReverseDir; }
+
+ CLASS_NEW_DELETE
+private:
+ void findNDoRule(Slot* & iSlot, vm::Machine &, FiniteStateMachine& fsm) const;
+ int doAction(const vm::Machine::Code* codeptr, Slot * & slot_out, vm::Machine &) const;
+ bool testPassConstraint(vm::Machine & m) const;
+ bool testConstraint(const Rule & r, vm::Machine &) const;
+ bool readRules(const byte * rule_map, const size_t num_entries,
+ const byte *precontext, const uint16 * sort_key,
+ const uint16 * o_constraint, const byte *constraint_data,
+ const uint16 * o_action, const byte * action_data,
+ Face &, enum passtype pt, Error &e);
+ bool readStates(const byte * starts, const byte * states, const byte * o_rule_map, Face &, Error &e);
+ bool readRanges(const byte * ranges, size_t num_ranges, Error &e);
+ uint16 glyphToCol(const uint16 gid) const;
+ bool runFSM(FiniteStateMachine & fsm, Slot * slot) const;
+ void dumpRuleEventConsidered(const FiniteStateMachine & fsm, const RuleEntry & re) const;
+ void dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * os) const;
+ void adjustSlot(int delta, Slot * & slot_out, SlotMap &) const;
+ bool collisionShift(Segment *seg, int dir, json * const dbgout) const;
+ bool collisionKern(Segment *seg, int dir, json * const dbgout) const;
+ bool collisionFinish(Segment *seg, GR_MAYBE_UNUSED json * const dbgout) const;
+ bool resolveCollisions(Segment *seg, Slot *slot, Slot *start, ShiftCollider &coll, bool isRev,
+ int dir, bool &moved, bool &hasCol, json * const dbgout) const;
+ float resolveKern(Segment *seg, Slot *slot, Slot *start, int dir,
+ float &ymin, float &ymax, json *const dbgout) const;
+
+ const Silf * m_silf;
+ uint16 * m_cols;
+ Rule * m_rules; // rules
+ RuleEntry * m_ruleMap;
+ uint16 * m_startStates; // prectxt length
+ uint16 * m_transitions;
+ State * m_states;
+ vm::Machine::Code * m_codes;
+ byte * m_progs;
+
+ byte m_numCollRuns;
+ byte m_kernColls;
+ byte m_iMaxLoop;
+ uint16 m_numGlyphs;
+ uint16 m_numRules;
+ uint16 m_numStates;
+ uint16 m_numTransition;
+ uint16 m_numSuccess;
+ uint16 m_successStart;
+ uint16 m_numColumns;
+ byte m_minPreCtxt;
+ byte m_maxPreCtxt;
+ byte m_colThreshold;
+ bool m_isReverseDir;
+ vm::Machine::Code m_cPConstraint;
+
+private: //defensive
+ Pass(const Pass&);
+ Pass& operator=(const Pass&);
+};
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Position.h b/gfx/graphite2/src/inc/Position.h
new file mode 100644
index 0000000000..510e4f4c41
--- /dev/null
+++ b/gfx/graphite2/src/inc/Position.h
@@ -0,0 +1,68 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+namespace graphite2 {
+
+class Position
+{
+public:
+ Position() : x(0), y(0) { }
+ Position(const float inx, const float iny) : x(inx), y(iny) {}
+ Position operator + (const Position& a) const { return Position(x + a.x, y + a.y); }
+ Position operator - (const Position& a) const { return Position(x - a.x, y - a.y); }
+ Position operator * (const float m) const { return Position(x * m, y * m); }
+ Position &operator += (const Position &a) { x += a.x; y += a.y; return *this; }
+ Position &operator *= (const float m) { x *= m; y *= m; return *this; }
+
+ float x;
+ float y;
+};
+
+class Rect
+{
+public :
+ Rect() {}
+ Rect(const Position& botLeft, const Position& topRight): bl(botLeft), tr(topRight) {}
+ Rect widen(const Rect& other) { return Rect(Position(bl.x > other.bl.x ? other.bl.x : bl.x, bl.y > other.bl.y ? other.bl.y : bl.y), Position(tr.x > other.tr.x ? tr.x : other.tr.x, tr.y > other.tr.y ? tr.y : other.tr.y)); }
+ Rect operator + (const Position &a) const { return Rect(Position(bl.x + a.x, bl.y + a.y), Position(tr.x + a.x, tr.y + a.y)); }
+ Rect operator - (const Position &a) const { return Rect(Position(bl.x - a.x, bl.y - a.y), Position(tr.x - a.x, tr.y - a.y)); }
+ Rect operator * (float m) const { return Rect(Position(bl.x, bl.y) * m, Position(tr.x, tr.y) * m); }
+ float width() const { return tr.x - bl.x; }
+ float height() const { return tr.y - bl.y; }
+
+ bool hitTest(Rect &other);
+
+ // returns Position(overlapx, overlapy) where overlap<0 if overlapping else positive)
+ Position overlap(Position &offset, Rect &other, Position &otherOffset);
+ //Position constrainedAvoid(Position &offset, Rect &box, Rect &sdbox, Position &other, Rect &obox, Rect &osdbox);
+
+ Position bl;
+ Position tr;
+};
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Rule.h b/gfx/graphite2/src/inc/Rule.h
new file mode 100644
index 0000000000..5964e003a6
--- /dev/null
+++ b/gfx/graphite2/src/inc/Rule.h
@@ -0,0 +1,305 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2011, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+
+#pragma once
+
+#include "inc/Code.h"
+#include "inc/Slot.h"
+
+namespace graphite2 {
+
+struct Rule {
+ const vm::Machine::Code * constraint,
+ * action;
+ unsigned short sort;
+ byte preContext;
+#ifndef NDEBUG
+ uint16 rule_idx;
+#endif
+
+ Rule();
+ ~Rule() {}
+
+ CLASS_NEW_DELETE;
+
+private:
+ Rule(const Rule &);
+ Rule & operator = (const Rule &);
+};
+
+inline
+Rule::Rule()
+: constraint(0),
+ action(0),
+ sort(0),
+ preContext(0)
+{
+#ifndef NDEBUG
+ rule_idx = 0;
+#endif
+}
+
+
+struct RuleEntry
+{
+ const Rule * rule;
+
+ inline
+ bool operator < (const RuleEntry &r) const
+ {
+ const unsigned short lsort = rule->sort, rsort = r.rule->sort;
+ return lsort > rsort || (lsort == rsort && rule < r.rule);
+ }
+
+ inline
+ bool operator == (const RuleEntry &r) const
+ {
+ return rule == r.rule;
+ }
+};
+
+
+struct State
+{
+ const RuleEntry * rules,
+ * rules_end;
+
+ bool empty() const;
+};
+
+inline
+bool State::empty() const
+{
+ return rules_end == rules;
+}
+
+
+class SlotMap
+{
+public:
+ enum {MAX_SLOTS=64};
+ SlotMap(Segment & seg, uint8 direction, size_t maxSize);
+
+ Slot * * begin();
+ Slot * * end();
+ size_t size() const;
+ unsigned short context() const;
+ void reset(Slot &, unsigned short);
+
+ Slot * const & operator[](int n) const;
+ Slot * & operator [] (int);
+ void pushSlot(Slot * const slot);
+ void collectGarbage(Slot *& aSlot);
+
+ Slot * highwater() { return m_highwater; }
+ void highwater(Slot *s) { m_highwater = s; m_highpassed = false; }
+ bool highpassed() const { return m_highpassed; }
+ void highpassed(bool v) { m_highpassed = v; }
+
+ uint8 dir() const { return m_dir; }
+ int decMax() { return --m_maxSize; }
+
+ Segment & segment;
+private:
+ Slot * m_slot_map[MAX_SLOTS+1];
+ unsigned short m_size;
+ unsigned short m_precontext;
+ Slot * m_highwater;
+ int m_maxSize;
+ uint8 m_dir;
+ bool m_highpassed;
+};
+
+
+class FiniteStateMachine
+{
+public:
+ enum {MAX_RULES=128};
+
+private:
+ class Rules
+ {
+ public:
+ Rules();
+ void clear();
+ const RuleEntry * begin() const;
+ const RuleEntry * end() const;
+ size_t size() const;
+
+ void accumulate_rules(const State &state);
+
+ private:
+ RuleEntry * m_begin,
+ * m_end,
+ m_rules[MAX_RULES*2];
+ };
+
+public:
+ FiniteStateMachine(SlotMap & map, json * logger);
+ void reset(Slot * & slot, const short unsigned int max_pre_ctxt);
+
+ Rules rules;
+ SlotMap & slots;
+ json * const dbgout;
+};
+
+
+inline
+FiniteStateMachine::FiniteStateMachine(SlotMap& map, json * logger)
+: slots(map),
+ dbgout(logger)
+{
+}
+
+inline
+void FiniteStateMachine::reset(Slot * & slot, const short unsigned int max_pre_ctxt)
+{
+ rules.clear();
+ int ctxt = 0;
+ for (; ctxt != max_pre_ctxt && slot->prev(); ++ctxt, slot = slot->prev());
+ slots.reset(*slot, ctxt);
+}
+
+inline
+FiniteStateMachine::Rules::Rules()
+ : m_begin(m_rules), m_end(m_rules)
+{
+}
+
+inline
+void FiniteStateMachine::Rules::clear()
+{
+ m_end = m_begin;
+}
+
+inline
+const RuleEntry * FiniteStateMachine::Rules::begin() const
+{
+ return m_begin;
+}
+
+inline
+const RuleEntry * FiniteStateMachine::Rules::end() const
+{
+ return m_end;
+}
+
+inline
+size_t FiniteStateMachine::Rules::size() const
+{
+ return m_end - m_begin;
+}
+
+inline
+void FiniteStateMachine::Rules::accumulate_rules(const State &state)
+{
+ // Only bother if there are rules in the State object.
+ if (state.empty()) return;
+
+ // Merge the new sorted rules list into the current sorted result set.
+ const RuleEntry * lre = begin(), * rre = state.rules;
+ RuleEntry * out = m_rules + (m_begin == m_rules)*MAX_RULES;
+ const RuleEntry * const lrend = out + MAX_RULES,
+ * const rrend = state.rules_end;
+ m_begin = out;
+ while (lre != end() && out != lrend)
+ {
+ if (*lre < *rre) *out++ = *lre++;
+ else if (*rre < *lre) { *out++ = *rre++; }
+ else { *out++ = *lre++; ++rre; }
+
+ if (rre == rrend)
+ {
+ while (lre != end() && out != lrend) { *out++ = *lre++; }
+ m_end = out;
+ return;
+ }
+ }
+ while (rre != rrend && out != lrend) { *out++ = *rre++; }
+ m_end = out;
+}
+
+inline
+SlotMap::SlotMap(Segment & seg, uint8 direction, size_t maxSize)
+: segment(seg), m_size(0), m_precontext(0), m_highwater(0),
+ m_maxSize(int(maxSize)), m_dir(direction), m_highpassed(false)
+{
+ m_slot_map[0] = 0;
+}
+
+inline
+Slot * * SlotMap::begin()
+{
+ return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting
+ // at start of segment.
+}
+
+inline
+Slot * * SlotMap::end()
+{
+ return m_slot_map + m_size + 1;
+}
+
+inline
+size_t SlotMap::size() const
+{
+ return m_size;
+}
+
+inline
+short unsigned int SlotMap::context() const
+{
+ return m_precontext;
+}
+
+inline
+void SlotMap::reset(Slot & slot, short unsigned int ctxt)
+{
+ m_size = 0;
+ m_precontext = ctxt;
+ *m_slot_map = slot.prev();
+}
+
+inline
+void SlotMap::pushSlot(Slot*const slot)
+{
+ m_slot_map[++m_size] = slot;
+}
+
+inline
+Slot * const & SlotMap::operator[](int n) const
+{
+ return m_slot_map[n + 1];
+}
+
+inline
+Slot * & SlotMap::operator[](int n)
+{
+ return m_slot_map[n + 1];
+}
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Segment.h b/gfx/graphite2/src/inc/Segment.h
new file mode 100644
index 0000000000..6cf83408d4
--- /dev/null
+++ b/gfx/graphite2/src/inc/Segment.h
@@ -0,0 +1,236 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include "inc/Main.h"
+
+#include <cassert>
+
+#include "inc/CharInfo.h"
+#include "inc/Face.h"
+#include "inc/FeatureVal.h"
+#include "inc/GlyphCache.h"
+#include "inc/GlyphFace.h"
+#include "inc/Slot.h"
+#include "inc/Position.h"
+#include "inc/List.h"
+#include "inc/Collider.h"
+
+#define MAX_SEG_GROWTH_FACTOR 64
+
+namespace graphite2 {
+
+typedef Vector<Features> FeatureList;
+typedef Vector<Slot *> SlotRope;
+typedef Vector<int16 *> AttributeRope;
+typedef Vector<SlotJustify *> JustifyRope;
+
+class Font;
+class Segment;
+class Silf;
+
+enum SpliceParam {
+/** sub-Segments longer than this are not cached
+ * (in Unicode code points) */
+ eMaxSpliceSize = 96
+};
+
+enum justFlags {
+ gr_justStartInline = 1,
+ gr_justEndInline = 2
+};
+
+class SegmentScopeState
+{
+private:
+ friend class Segment;
+ Slot * realFirstSlot;
+ Slot * slotBeforeScope;
+ Slot * slotAfterScope;
+ Slot * realLastSlot;
+ size_t numGlyphsOutsideScope;
+};
+
+class Segment
+{
+ // Prevent copying of any kind.
+ Segment(const Segment&);
+ Segment& operator=(const Segment&);
+
+public:
+
+ enum {
+ SEG_INITCOLLISIONS = 1,
+ SEG_HASCOLLISIONS = 2
+ };
+
+ size_t slotCount() const { return m_numGlyphs; } //one slot per glyph
+ void extendLength(ptrdiff_t num) { m_numGlyphs += num; }
+ Position advance() const { return m_advance; }
+ bool runGraphite() { if (m_silf) return m_face->runGraphite(this, m_silf); else return true;};
+ void chooseSilf(uint32 script) { m_silf = m_face->chooseSilf(script); }
+ const Silf *silf() const { return m_silf; }
+ size_t charInfoCount() const { return m_numCharinfo; }
+ const CharInfo *charinfo(unsigned int index) const { return index < m_numCharinfo ? m_charinfo + index : NULL; }
+ CharInfo *charinfo(unsigned int index) { return index < m_numCharinfo ? m_charinfo + index : NULL; }
+
+ Segment(size_t numchars, const Face* face, uint32 script, int dir);
+ ~Segment();
+ uint8 flags() const { return m_flags; }
+ void flags(uint8 f) { m_flags = f; }
+ Slot *first() { return m_first; }
+ void first(Slot *p) { m_first = p; }
+ Slot *last() { return m_last; }
+ void last(Slot *p) { m_last = p; }
+ void appendSlot(int i, int cid, int gid, int fid, size_t coffset);
+ Slot *newSlot();
+ void freeSlot(Slot *);
+ SlotJustify *newJustify();
+ void freeJustify(SlotJustify *aJustify);
+ Position positionSlots(const Font *font=0, Slot *first=0, Slot *last=0, bool isRtl = false, bool isFinal = true);
+ void associateChars(int offset, size_t num);
+ void linkClusters(Slot *first, Slot *last);
+ uint16 getClassGlyph(uint16 cid, uint16 offset) const { return m_silf->getClassGlyph(cid, offset); }
+ uint16 findClassIndex(uint16 cid, uint16 gid) const { return m_silf->findClassIndex(cid, gid); }
+ int addFeatures(const Features& feats) { m_feats.push_back(feats); return int(m_feats.size()) - 1; }
+ uint32 getFeature(int index, uint8 findex) const { const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex); if (!pFR) return 0; else return pFR->getFeatureVal(m_feats[index]); }
+ void setFeature(int index, uint8 findex, uint32 val) {
+ const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex);
+ if (pFR)
+ {
+ if (val > pFR->maxVal()) val = pFR->maxVal();
+ pFR->applyValToFeature(val, m_feats[index]);
+ } }
+ int8 dir() const { return m_dir; }
+ void dir(int8 val) { m_dir = val; }
+ bool currdir() const { return ((m_dir >> 6) ^ m_dir) & 1; }
+ uint8 passBits() const { return m_passBits; }
+ void mergePassBits(const uint8 val) { m_passBits &= val; }
+ int16 glyphAttr(uint16 gid, uint16 gattr) const { const GlyphFace * p = m_face->glyphs().glyphSafe(gid); return p ? p->attrs()[gattr] : 0; }
+ int32 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel, bool rtl) const;
+ float glyphAdvance(uint16 gid) const { return m_face->glyphs().glyph(gid)->theAdvance().x; }
+ const Rect &theGlyphBBoxTemporary(uint16 gid) const { return m_face->glyphs().glyph(gid)->theBBox(); } //warning value may become invalid when another glyph is accessed
+ Slot *findRoot(Slot *is) const { return is->attachedTo() ? findRoot(is->attachedTo()) : is; }
+ int numAttrs() const { return m_silf->numUser(); }
+ int defaultOriginal() const { return m_defaultOriginal; }
+ const Face * getFace() const { return m_face; }
+ const Features & getFeatures(unsigned int /*charIndex*/) { assert(m_feats.size() == 1); return m_feats[0]; }
+ void bidiPass(int paradir, uint8 aMirror);
+ int8 getSlotBidiClass(Slot *s) const;
+ void doMirror(uint16 aMirror);
+ Slot *addLineEnd(Slot *nSlot);
+ void delLineEnd(Slot *s);
+ bool hasJustification() const { return m_justifies.size() != 0; }
+ void reverseSlots();
+
+ bool isWhitespace(const int cid) const;
+ bool hasCollisionInfo() const { return (m_flags & SEG_HASCOLLISIONS) && m_collisions; }
+ SlotCollision *collisionInfo(const Slot *s) const { return m_collisions ? m_collisions + s->index() : 0; }
+ CLASS_NEW_DELETE
+
+public: //only used by: GrSegment* makeAndInitialize(const GrFont *font, const GrFace *face, uint32 script, const FeaturesHandle& pFeats/*must not be IsNull*/, encform enc, const void* pStart, size_t nChars, int dir);
+ bool read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void*pStart, size_t nChars);
+ void finalise(const Font *font, bool reverse=false);
+ float justify(Slot *pSlot, const Font *font, float width, enum justFlags flags, Slot *pFirst, Slot *pLast);
+ bool initCollisions();
+
+private:
+ Position m_advance; // whole segment advance
+ SlotRope m_slots; // Vector of slot buffers
+ AttributeRope m_userAttrs; // Vector of userAttrs buffers
+ JustifyRope m_justifies; // Slot justification info buffers
+ FeatureList m_feats; // feature settings referenced by charinfos in this segment
+ Slot * m_freeSlots; // linked list of free slots
+ SlotJustify * m_freeJustifies; // Slot justification blocks free list
+ CharInfo * m_charinfo; // character info, one per input character
+ SlotCollision * m_collisions;
+ const Face * m_face; // GrFace
+ const Silf * m_silf;
+ Slot * m_first; // first slot in segment
+ Slot * m_last; // last slot in segment
+ size_t m_bufSize, // how big a buffer to create when need more slots
+ m_numGlyphs,
+ m_numCharinfo; // size of the array and number of input characters
+ int m_defaultOriginal; // number of whitespace chars in the string
+ int8 m_dir;
+ uint8 m_flags, // General purpose flags
+ m_passBits; // if bit set then skip pass
+};
+
+inline
+int8 Segment::getSlotBidiClass(Slot *s) const
+{
+ int8 res = s->getBidiClass();
+ if (res != -1) return res;
+ res = int8(glyphAttr(s->gid(), m_silf->aBidi()));
+ s->setBidiClass(res);
+ return res;
+}
+
+inline
+void Segment::finalise(const Font *font, bool reverse)
+{
+ if (!m_first || !m_last) return;
+
+ m_advance = positionSlots(font, m_first, m_last, m_silf->dir(), true);
+ //associateChars(0, m_numCharinfo);
+ if (reverse && currdir() != (m_dir & 1))
+ reverseSlots();
+ linkClusters(m_first, m_last);
+}
+
+inline
+int32 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel, bool rtl) const {
+ if (attrLevel > 0)
+ {
+ Slot *is = findRoot(iSlot);
+ return is->clusterMetric(this, metric, attrLevel, rtl);
+ }
+ else
+ return m_face->getGlyphMetric(iSlot->gid(), metric);
+}
+
+inline
+bool Segment::isWhitespace(const int cid) const
+{
+ return ((cid >= 0x0009) * (cid <= 0x000D)
+ + (cid == 0x0020)
+ + (cid == 0x0085)
+ + (cid == 0x00A0)
+ + (cid == 0x1680)
+ + (cid == 0x180E)
+ + (cid >= 0x2000) * (cid <= 0x200A)
+ + (cid == 0x2028)
+ + (cid == 0x2029)
+ + (cid == 0x202F)
+ + (cid == 0x205F)
+ + (cid == 0x3000)) != 0;
+}
+
+} // namespace graphite2
+
+struct gr_segment : public graphite2::Segment {};
diff --git a/gfx/graphite2/src/inc/Silf.h b/gfx/graphite2/src/inc/Silf.h
new file mode 100644
index 0000000000..edc0c3a16d
--- /dev/null
+++ b/gfx/graphite2/src/inc/Silf.h
@@ -0,0 +1,128 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include "graphite2/Font.h"
+#include "inc/Main.h"
+#include "inc/Pass.h"
+
+namespace graphite2 {
+
+class Face;
+class Segment;
+class FeatureVal;
+class VMScratch;
+class Error;
+
+class Pseudo
+{
+public:
+ uint32 uid;
+ uint32 gid;
+ CLASS_NEW_DELETE;
+};
+
+class Justinfo
+{
+public:
+ Justinfo(uint8 stretch, uint8 shrink, uint8 step, uint8 weight) :
+ m_astretch(stretch), m_ashrink(shrink), m_astep(step),
+ m_aweight(weight) {};
+ uint8 attrStretch() const { return m_astretch; }
+ uint8 attrShrink() const { return m_ashrink; }
+ uint8 attrStep() const { return m_astep; }
+ uint8 attrWeight() const { return m_aweight; }
+
+private:
+ uint8 m_astretch;
+ uint8 m_ashrink;
+ uint8 m_astep;
+ uint8 m_aweight;
+};
+
+class Silf
+{
+ // Prevent copying
+ Silf(const Silf&);
+ Silf& operator=(const Silf&);
+
+public:
+ Silf() throw();
+ ~Silf() throw();
+
+ bool readGraphite(const byte * const pSilf, size_t lSilf, Face &face, uint32 version);
+ bool runGraphite(Segment *seg, uint8 firstPass=0, uint8 lastPass=0, int dobidi = 0) const;
+ uint16 findClassIndex(uint16 cid, uint16 gid) const;
+ uint16 getClassGlyph(uint16 cid, unsigned int index) const;
+ uint16 findPseudo(uint32 uid) const;
+ uint8 numUser() const { return m_aUser; }
+ uint8 aPseudo() const { return m_aPseudo; }
+ uint8 aBreak() const { return m_aBreak; }
+ uint8 aMirror() const {return m_aMirror; }
+ uint8 aPassBits() const { return m_aPassBits; }
+ uint8 aBidi() const { return m_aBidi; }
+ uint8 aCollision() const { return m_aCollision; }
+ uint8 substitutionPass() const { return m_sPass; }
+ uint8 positionPass() const { return m_pPass; }
+ uint8 justificationPass() const { return m_jPass; }
+ uint8 bidiPass() const { return m_bPass; }
+ uint8 numPasses() const { return m_numPasses; }
+ uint8 maxCompPerLig() const { return m_iMaxComp; }
+ uint16 numClasses() const { return m_nClass; }
+ byte flags() const { return m_flags; }
+ byte dir() const { return m_dir; }
+ uint8 numJustLevels() const { return m_numJusts; }
+ Justinfo *justAttrs() const { return m_justs; }
+ uint16 endLineGlyphid() const { return m_gEndLine; }
+ const gr_faceinfo *silfInfo() const { return &m_silfinfo; }
+
+ CLASS_NEW_DELETE;
+
+private:
+ size_t readClassMap(const byte *p, size_t data_len, uint32 version, Error &e);
+ template<typename T> inline uint32 readClassOffsets(const byte *&p, size_t data_len, Error &e);
+
+ Pass * m_passes;
+ Pseudo * m_pseudos;
+ uint32 * m_classOffsets;
+ uint16 * m_classData;
+ Justinfo * m_justs;
+ uint8 m_numPasses;
+ uint8 m_numJusts;
+ uint8 m_sPass, m_pPass, m_jPass, m_bPass,
+ m_flags, m_dir;
+
+ uint8 m_aPseudo, m_aBreak, m_aUser, m_aBidi, m_aMirror, m_aPassBits,
+ m_iMaxComp, m_aCollision;
+ uint16 m_aLig, m_numPseudo, m_nClass, m_nLinear,
+ m_gEndLine;
+ gr_faceinfo m_silfinfo;
+
+ void releaseBuffers() throw();
+};
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/Slot.h b/gfx/graphite2/src/inc/Slot.h
new file mode 100644
index 0000000000..df39d9a3bb
--- /dev/null
+++ b/gfx/graphite2/src/inc/Slot.h
@@ -0,0 +1,170 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include "graphite2/Types.h"
+#include "graphite2/Segment.h"
+#include "inc/Main.h"
+#include "inc/Font.h"
+#include "inc/Position.h"
+
+namespace graphite2 {
+
+typedef gr_attrCode attrCode;
+
+class GlyphFace;
+class Segment;
+
+struct SlotJustify
+{
+ static const int NUMJUSTPARAMS = 5;
+
+ SlotJustify(const SlotJustify &);
+ SlotJustify & operator = (const SlotJustify &);
+
+public:
+ static size_t size_of(size_t levels) { return sizeof(SlotJustify) + ((levels > 1 ? levels : 1)*NUMJUSTPARAMS - 1)*sizeof(int16); }
+
+ void LoadSlot(const Slot *s, const Segment *seg);
+
+ SlotJustify *next;
+ int16 values[1];
+};
+
+class Slot
+{
+ enum Flag
+ {
+ DELETED = 1,
+ INSERTED = 2,
+ COPIED = 4,
+ POSITIONED = 8,
+ ATTACHED = 16
+ };
+
+public:
+ struct iterator;
+
+ unsigned short gid() const { return m_glyphid; }
+ Position origin() const { return m_position; }
+ float advance() const { return m_advance.x; }
+ void advance(Position &val) { m_advance = val; }
+ Position advancePos() const { return m_advance; }
+ int before() const { return m_before; }
+ int after() const { return m_after; }
+ uint32 index() const { return m_index; }
+ void index(uint32 val) { m_index = val; }
+
+ Slot(int16 *m_userAttr = NULL);
+ void set(const Slot & slot, int charOffset, size_t numUserAttr, size_t justLevels, size_t numChars);
+ Slot *next() const { return m_next; }
+ void next(Slot *s) { m_next = s; }
+ Slot *prev() const { return m_prev; }
+ void prev(Slot *s) { m_prev = s; }
+ uint16 glyph() const { return m_realglyphid ? m_realglyphid : m_glyphid; }
+ void setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph = NULL);
+ void setRealGid(uint16 realGid) { m_realglyphid = realGid; }
+ void adjKern(const Position &pos) { m_shift = m_shift + pos; m_advance = m_advance + pos; }
+ void origin(const Position &pos) { m_position = pos + m_shift; }
+ void originate(int ind) { m_original = ind; }
+ int original() const { return m_original; }
+ void before(int ind) { m_before = ind; }
+ void after(int ind) { m_after = ind; }
+ bool isBase() const { return (!m_parent); }
+ void update(int numSlots, int numCharInfo, Position &relpos);
+ Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal, int depth = 0);
+ bool isDeleted() const { return (m_flags & DELETED) ? true : false; }
+ void markDeleted(bool state) { if (state) m_flags |= DELETED; else m_flags &= ~DELETED; }
+ bool isCopied() const { return (m_flags & COPIED) ? true : false; }
+ void markCopied(bool state) { if (state) m_flags |= COPIED; else m_flags &= ~COPIED; }
+ bool isPositioned() const { return (m_flags & POSITIONED) ? true : false; }
+ void markPositioned(bool state) { if (state) m_flags |= POSITIONED; else m_flags &= ~POSITIONED; }
+ bool isInsertBefore() const { return !(m_flags & INSERTED); }
+ uint8 getBidiLevel() const { return m_bidiLevel; }
+ void setBidiLevel(uint8 level) { m_bidiLevel = level; }
+ int8 getBidiClass(const Segment *seg);
+ int8 getBidiClass() const { return m_bidiCls; }
+ void setBidiClass(int8 cls) { m_bidiCls = cls; }
+ int16 *userAttrs() const { return m_userAttr; }
+ void userAttrs(int16 *p) { m_userAttr = p; }
+ void markInsertBefore(bool state) { if (!state) m_flags |= INSERTED; else m_flags &= ~INSERTED; }
+ void setAttr(Segment* seg, attrCode ind, uint8 subindex, int16 val, const SlotMap & map);
+ int getAttr(const Segment *seg, attrCode ind, uint8 subindex) const;
+ int getJustify(const Segment *seg, uint8 level, uint8 subindex) const;
+ void setJustify(Segment *seg, uint8 level, uint8 subindex, int16 value);
+ bool isLocalJustify() const { return m_justs != NULL; };
+ void attachTo(Slot *ap) { m_parent = ap; }
+ Slot *attachedTo() const { return m_parent; }
+ Position attachOffset() const { return m_attach - m_with; }
+ Slot* firstChild() const { return m_child; }
+ void firstChild(Slot *ap) { m_child = ap; }
+ bool child(Slot *ap);
+ Slot* nextSibling() const { return m_sibling; }
+ void nextSibling(Slot *ap) { m_sibling = ap; }
+ bool sibling(Slot *ap);
+ bool removeChild(Slot *ap);
+ int32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel, bool rtl);
+ void positionShift(Position a) { m_position += a; }
+ void floodShift(Position adj, int depth = 0);
+ float just() const { return m_just; }
+ void just(float j) { m_just = j; }
+ Slot *nextInCluster(const Slot *s) const;
+ bool isChildOf(const Slot *base) const;
+
+ CLASS_NEW_DELETE
+
+private:
+ Slot *m_next; // linked list of slots
+ Slot *m_prev;
+ unsigned short m_glyphid; // glyph id
+ uint16 m_realglyphid;
+ uint32 m_original; // charinfo that originated this slot (e.g. for feature values)
+ uint32 m_before; // charinfo index of before association
+ uint32 m_after; // charinfo index of after association
+ uint32 m_index; // slot index given to this slot during finalising
+ Slot *m_parent; // index to parent we are attached to
+ Slot *m_child; // index to first child slot that attaches to us
+ Slot *m_sibling; // index to next child that attaches to our parent
+ Position m_position; // absolute position of glyph
+ Position m_shift; // .shift slot attribute
+ Position m_advance; // .advance slot attribute
+ Position m_attach; // attachment point on us
+ Position m_with; // attachment point position on parent
+ float m_just; // Justification inserted space
+ uint8 m_flags; // holds bit flags
+ byte m_attLevel; // attachment level
+ int8 m_bidiCls; // bidirectional class
+ byte m_bidiLevel; // bidirectional level
+ int16 *m_userAttr; // pointer to user attributes
+ SlotJustify *m_justs; // pointer to justification parameters
+
+ friend class Segment;
+};
+
+} // namespace graphite2
+
+struct gr_slot : public graphite2::Slot {};
diff --git a/gfx/graphite2/src/inc/Sparse.h b/gfx/graphite2/src/inc/Sparse.h
new file mode 100644
index 0000000000..fcda890171
--- /dev/null
+++ b/gfx/graphite2/src/inc/Sparse.h
@@ -0,0 +1,168 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2011, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+#include <iterator>
+#include <utility>
+
+#include "inc/Main.h"
+
+namespace graphite2 {
+
+
+// A read-only packed fast sparse array of uint16 with uint16 keys.
+// Like most container classes this has capacity and size properties and these
+// refer to the number of stored entries and the number of addressable entries
+// as normal. However due the sparse nature the capacity is always <= than the
+// size.
+class sparse
+{
+public:
+ typedef uint16 key_type;
+ typedef uint16 mapped_type;
+ typedef std::pair<const key_type, mapped_type> value_type;
+
+private:
+ typedef unsigned long mask_t;
+
+ static const unsigned char SIZEOF_CHUNK = (sizeof(mask_t) - sizeof(key_type))*8;
+
+ struct chunk
+ {
+ mask_t mask:SIZEOF_CHUNK;
+ key_type offset;
+ };
+
+ static const chunk empty_chunk;
+ sparse(const sparse &);
+ sparse & operator = (const sparse &);
+
+public:
+ template<typename I>
+ sparse(I first, const I last);
+ sparse() throw();
+ ~sparse() throw();
+
+ operator bool () const throw();
+ mapped_type operator [] (const key_type k) const throw();
+
+ size_t capacity() const throw();
+ size_t size() const throw();
+
+ size_t _sizeof() const throw();
+
+ CLASS_NEW_DELETE;
+
+private:
+ union {
+ chunk * map;
+ mapped_type * values;
+ } m_array;
+ key_type m_nchunks;
+};
+
+
+inline
+sparse::sparse() throw() : m_nchunks(0)
+{
+ m_array.map = const_cast<graphite2::sparse::chunk *>(&empty_chunk);
+}
+
+
+template <typename I>
+sparse::sparse(I attr, const I last)
+: m_nchunks(0)
+{
+ m_array.map = 0;
+
+ // Find the maximum extent of the key space.
+ size_t n_values=0;
+ long lastkey = -1;
+ for (I i = attr; i != last; ++i, ++n_values)
+ {
+ const typename std::iterator_traits<I>::value_type v = *i;
+ if (v.second == 0) { --n_values; continue; }
+ if (v.first <= lastkey) { m_nchunks = 0; return; }
+
+ lastkey = v.first;
+ const key_type k = v.first / SIZEOF_CHUNK;
+ if (k >= m_nchunks) m_nchunks = k+1;
+ }
+ if (m_nchunks == 0)
+ {
+ m_array.map=const_cast<graphite2::sparse::chunk *>(&empty_chunk);
+ return;
+ }
+
+ m_array.values = grzeroalloc<mapped_type>((m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)
+ / sizeof(mapped_type)
+ + n_values);
+
+ if (m_array.values == 0)
+ return;
+
+ // coverity[forward_null : FALSE] Since m_array is union and m_array.values is not NULL
+ chunk * ci = m_array.map;
+ ci->offset = (m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)/sizeof(mapped_type);
+ mapped_type * vi = m_array.values + ci->offset;
+ for (; attr != last; ++attr, ++vi)
+ {
+ const typename std::iterator_traits<I>::value_type v = *attr;
+ if (v.second == 0) { --vi; continue; }
+
+ chunk * const ci_ = m_array.map + v.first/SIZEOF_CHUNK;
+
+ if (ci != ci_)
+ {
+ ci = ci_;
+ ci->offset = key_type(vi - m_array.values);
+ }
+
+ ci->mask |= 1UL << (SIZEOF_CHUNK - 1 - (v.first % SIZEOF_CHUNK));
+ *vi = v.second;
+ }
+}
+
+
+inline
+sparse::operator bool () const throw()
+{
+ return m_array.map != 0;
+}
+
+inline
+size_t sparse::size() const throw()
+{
+ return m_nchunks*SIZEOF_CHUNK;
+}
+
+inline
+size_t sparse::_sizeof() const throw()
+{
+ return sizeof(sparse) + capacity()*sizeof(mapped_type) + m_nchunks*sizeof(chunk);
+}
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/TtfTypes.h b/gfx/graphite2/src/inc/TtfTypes.h
new file mode 100644
index 0000000000..ae67915304
--- /dev/null
+++ b/gfx/graphite2/src/inc/TtfTypes.h
@@ -0,0 +1,419 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+/*--------------------------------------------------------------------*//*:Ignore this sentence.
+
+File: TtfTypes.h
+Responsibility: Tim Eves
+Last reviewed: Not yet.
+
+Description:
+Provides types required to represent the TTF basic types.
+-------------------------------------------------------------------------------*//*:End Ignore*/
+
+
+//**********************************************************************************************
+// Include files
+//**********************************************************************************************
+namespace graphite2
+{
+namespace TtfUtil
+{
+//**********************************************************************************************
+// Forward declarations
+//**********************************************************************************************
+
+
+//**********************************************************************************************
+// Type declarations
+//**********************************************************************************************
+typedef unsigned char uint8;
+typedef uint8 byte;
+typedef signed char int8;
+typedef unsigned short uint16;
+typedef short int16;
+typedef unsigned int uint32;
+typedef int int32;
+
+typedef int16 short_frac;
+typedef int32 fixed;
+typedef int16 fword;
+typedef uint16 ufword;
+typedef int16 f2dot14;
+typedef uint32 long_date_time[2];
+
+//**********************************************************************************************
+// Constants and enum types
+//**********************************************************************************************/
+enum
+{
+ OneFix = 1<<16
+};
+
+//**********************************************************************************************
+// Table declarations
+//**********************************************************************************************
+namespace Sfnt
+{
+#pragma pack(push,1) // We need this or the structure members aren't aligned
+ // correctly. Fortunately this form of pragma is supposed
+ // to be recognised by VS C++ too (at least according to
+ // MSDN).
+
+ struct OffsetSubTable
+ {
+ uint32 scaler_type;
+ uint16 num_tables,
+ search_range,
+ entry_selector,
+ range_shift;
+ struct Entry
+ {
+ uint32 tag,
+ checksum,
+ offset,
+ length;
+ } table_directory[1];
+
+ enum ScalerType
+ {
+ TrueTypeMac = 0x74727565U,
+ TrueTypeWin = 0x00010000U,
+ Type1 = 0x74797031U
+ };
+ };
+
+
+
+
+ struct CharacterCodeMap
+ {
+ uint16 version,
+ num_subtables;
+ struct
+ {
+ uint16 platform_id,
+ platform_specific_id;
+ uint32 offset;
+ } encoding[1];
+ };
+
+ struct CmapSubTable
+ {
+ uint16 format,
+ length,
+ language;
+ };
+
+ struct CmapSubTableFormat4 : CmapSubTable
+ {
+ uint16 seg_count_x2,
+ search_range,
+ entry_selector,
+ range_shift,
+ end_code[1];
+ // There are arrarys after this which need their
+ // start positions calculated since end_code is
+ // seg_count uint16s long.
+ };
+
+ struct CmapSubTableFormat12
+ {
+ fixed format;
+ uint32 length,
+ language,
+ num_groups;
+ struct
+ {
+ uint32 start_char_code,
+ end_char_code,
+ start_glyph_id;
+ } group[1];
+ };
+
+
+
+ struct FontHeader
+ {
+ fixed version,
+ font_revision;
+ uint32 check_sum_adjustment,
+ magic_number;
+ uint16 flags,
+ units_per_em;
+ long_date_time created,
+ modified;
+ fword x_min,
+ y_min,
+ x_max,
+ y_max;
+ uint16 mac_style,
+ lowest_rec_ppem;
+ int16 font_direction_hint,
+ index_to_loc_format,
+ glyph_data_format;
+ enum
+ {
+ MagicNumber = 0x5F0F3CF5,
+ GlypDataFormat = 0
+ };
+ enum {ShortIndexLocFormat, LongIndexLocFormat};
+ };
+
+
+
+
+ struct PostScriptGlyphName
+ {
+ fixed format,
+ italic_angle;
+ fword underline_position,
+ underline_thickness;
+ uint32 is_fixed_pitch,
+ min_mem_type42,
+ max_mem_type42,
+ min_mem_type1,
+ max_mem_type1;
+ enum
+ {
+ Format1 = 0x10000,
+ Format2 = 0x20000,
+ Format25 = 0x28000,
+ Format3 = 0x30000,
+ Format4 = 0x40000
+ };
+ };
+
+ struct PostScriptGlyphName2 : PostScriptGlyphName
+ {
+ uint16 number_of_glyphs,
+ glyph_name_index[1];
+ };
+
+ struct PostScriptGlyphName25 : PostScriptGlyphName
+ {
+ uint16 number_of_glyphs;
+ int8 offset[1];
+ };
+
+ struct PostScriptGlyphName3 : PostScriptGlyphName {};
+
+ struct PostScriptGlyphName4 : PostScriptGlyphName
+ {
+ uint16 glyph_to_char_map[1];
+ };
+
+
+ struct HorizontalHeader
+ {
+ fixed version;
+ fword ascent,
+ descent,
+ line_gap;
+ ufword advance_width_max;
+ fword min_left_side_bearing,
+ max_left_side_bearing,
+ x_max_element;
+ int16 caret_slope_rise,
+ caret_slope_run;
+ fword caret_offset;
+ int16 reserved[4],
+ metric_data_format;
+ uint16 num_long_hor_metrics;
+ };
+
+ struct MaximumProfile
+ {
+ fixed version;
+ uint16 num_glyphs,
+ max_points,
+ max_contours,
+ max_component_points,
+ max_component_contours,
+ max_zones,
+ max_twilight_points,
+ max_storage,
+ max_function_defs,
+ max_instruction_defs,
+ max_stack_elements,
+ max_size_of_instructions,
+ max_component_elements,
+ max_component_depth;
+ };
+
+
+ typedef byte Panose[10];
+
+ struct Compatibility0
+ {
+ uint16 version;
+ int16 x_avg_char_width;
+ uint16 weight_class,
+ width_class;
+ int16 fs_type,
+ y_subscript_x_size,
+ y_subscript_y_size,
+ y_subscript_x_offset,
+ y_subscript_y_offset,
+ y_superscript_x_size,
+ y_superscript_y_size,
+ y_superscript_x_offset,
+ y_superscript_y_offset,
+ y_strikeout_size,
+ y_strikeout_position,
+ family_class;
+ Panose panose;
+ uint32 unicode_range[4];
+ int8 ach_vend_id[4];
+ uint16 fs_selection,
+ fs_first_char_index,
+ fs_last_char_index, // Acording to Apple's spec this is where v0 should end
+ typo_ascender,
+ typo_descender,
+ type_linegap,
+ win_ascent,
+ win_descent;
+
+ enum
+ {
+ Italic =0x01,
+ Underscore=0x02,
+ Negative =0x04,
+ Outlined =0x08,
+ StrikeOut =0x10,
+ Bold =0x20
+ };
+ };
+
+ struct Compatibility1 : Compatibility0
+ {
+ uint32 codepage_range[2];
+ };
+
+ struct Compatibility2 : Compatibility1
+ {
+ int16 x_height,
+ cap_height;
+ uint16 default_char,
+ break_char,
+ max_context;
+ };
+
+ struct Compatibility3 : Compatibility2 {};
+
+ typedef Compatibility3 Compatibility;
+
+
+ struct NameRecord
+ {
+ uint16 platform_id,
+ platform_specific_id,
+ language_id,
+ name_id,
+ length,
+ offset;
+ enum {Unicode, Mactintosh, Reserved, Microsoft};
+ enum
+ {
+ Copyright, Family, Subfamily, UniqueSubfamily,
+ Fullname, Version, PostScript
+ };
+ };
+
+ struct LangTagRecord
+ {
+ uint16 length,
+ offset;
+ };
+
+ struct FontNames
+ {
+ uint16 format,
+ count,
+ string_offset;
+ NameRecord name_record[1];
+ };
+
+
+ struct HorizontalMetric
+ {
+ uint16 advance_width;
+ int16 left_side_bearing;
+ };
+
+
+ struct Glyph
+ {
+ int16 number_of_contours;
+ fword x_min,
+ y_min,
+ x_max,
+ y_max;
+ };
+
+ struct SimpleGlyph : Glyph
+ {
+ uint16 end_pts_of_contours[1];
+ enum
+ {
+ OnCurve = 0x01,
+ XShort = 0x02,
+ YShort = 0x04,
+ Repeat = 0x08,
+ XIsSame = 0x10,
+ XIsPos = 0x10,
+ YIsSame = 0x20,
+ YIsPos = 0x20
+ };
+ };
+
+ struct CompoundGlyph : Glyph
+ {
+ uint16 flags,
+ glyph_index;
+ enum
+ {
+ Arg1Arg2Words = 0x01,
+ ArgsAreXYValues = 0x02,
+ RoundXYToGrid = 0x04,
+ HaveScale = 0x08,
+ MoreComponents = 0x20,
+ HaveXAndYScale = 0x40,
+ HaveTwoByTwo = 0x80,
+ HaveInstructions = 0x100,
+ UseMyMetrics = 0x200,
+ OverlapCompund = 0x400,
+ ScaledOffset = 0x800,
+ UnscaledOffset = 0x1000
+ };
+ };
+
+#pragma pack(pop)
+} // end of namespace Sfnt
+
+} // end of namespace TtfUtil
+} // end of namespace graphite2
diff --git a/gfx/graphite2/src/inc/TtfUtil.h b/gfx/graphite2/src/inc/TtfUtil.h
new file mode 100644
index 0000000000..3952bc06fb
--- /dev/null
+++ b/gfx/graphite2/src/inc/TtfUtil.h
@@ -0,0 +1,208 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+/*--------------------------------------------------------------------*//*:Ignore this sentence.
+
+File: TtfUtil.h
+Responsibility: Alan Ward
+Last reviewed: Not yet.
+
+Description:
+ Utility class for handling TrueType font files.
+----------------------------------------------------------------------------------------------*/
+
+
+#include <cstddef>
+
+namespace graphite2
+{
+namespace TtfUtil
+{
+
+#define OVERFLOW_OFFSET_CHECK(p, o) (o + reinterpret_cast<size_t>(p) < reinterpret_cast<size_t>(p))
+
+typedef long fontTableId32;
+typedef unsigned short gid16;
+
+#define TTF_TAG(a,b,c,d) ((a << 24UL) + (b << 16UL) + (c << 8UL) + (d))
+
+// Enumeration used to specify a table in a TTF file
+class Tag
+{
+ unsigned int _v;
+public:
+ Tag(const char n[5]) throw() : _v(TTF_TAG(n[0],n[1],n[2],n[3])) {}
+ Tag(const unsigned int tag) throw() : _v(tag) {}
+
+ operator unsigned int () const throw () { return _v; }
+
+ enum
+ {
+ Feat = TTF_TAG('F','e','a','t'),
+ Glat = TTF_TAG('G','l','a','t'),
+ Gloc = TTF_TAG('G','l','o','c'),
+ Sile = TTF_TAG('S','i','l','e'),
+ Silf = TTF_TAG('S','i','l','f'),
+ Sill = TTF_TAG('S','i','l','l'),
+ cmap = TTF_TAG('c','m','a','p'),
+ cvt = TTF_TAG('c','v','t',' '),
+ cryp = TTF_TAG('c','r','y','p'),
+ head = TTF_TAG('h','e','a','d'),
+ fpgm = TTF_TAG('f','p','g','m'),
+ gdir = TTF_TAG('g','d','i','r'),
+ glyf = TTF_TAG('g','l','y','f'),
+ hdmx = TTF_TAG('h','d','m','x'),
+ hhea = TTF_TAG('h','h','e','a'),
+ hmtx = TTF_TAG('h','m','t','x'),
+ loca = TTF_TAG('l','o','c','a'),
+ kern = TTF_TAG('k','e','r','n'),
+ LTSH = TTF_TAG('L','T','S','H'),
+ maxp = TTF_TAG('m','a','x','p'),
+ name = TTF_TAG('n','a','m','e'),
+ OS_2 = TTF_TAG('O','S','/','2'),
+ post = TTF_TAG('p','o','s','t'),
+ prep = TTF_TAG('p','r','e','p')
+ };
+};
+
+/*----------------------------------------------------------------------------------------------
+ Class providing utility methods to parse a TrueType font file (TTF).
+ Callling application handles all file input and memory allocation.
+ Assumes minimal knowledge of TTF file format.
+----------------------------------------------------------------------------------------------*/
+ ////////////////////////////////// tools to find & check TTF tables
+ bool GetHeaderInfo(size_t & lOffset, size_t & lSize);
+ bool CheckHeader(const void * pHdr);
+ bool GetTableDirInfo(const void * pHdr, size_t & lOffset, size_t & lSize);
+ bool GetTableInfo(const Tag TableTag, const void * pHdr, const void * pTableDir,
+ size_t & lOffset, size_t & lSize);
+ bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize);
+
+ ////////////////////////////////// simple font wide info
+ size_t GlyphCount(const void * pMaxp);
+#ifdef ALL_TTFUTILS
+ size_t MaxCompositeComponentCount(const void * pMaxp);
+ size_t MaxCompositeLevelCount(const void * pMaxp);
+ size_t LocaGlyphCount(size_t lLocaSize, const void * pHead); // throw (std::domain_error);
+#endif
+ int DesignUnits(const void * pHead);
+#ifdef ALL_TTFUTILS
+ int HeadTableCheckSum(const void * pHead);
+ void HeadTableCreateTime(const void * pHead, unsigned int * pnDateBC, unsigned int * pnDateAD);
+ void HeadTableModifyTime(const void * pHead, unsigned int * pnDateBC, unsigned int * pnDateAD);
+ bool IsItalic(const void * pHead);
+ int FontAscent(const void * pOs2);
+ int FontDescent(const void * pOs2);
+ bool FontOs2Style(const void *pOs2, bool & fBold, bool & fItalic);
+ bool Get31EngFamilyInfo(const void * pName, size_t & lOffset, size_t & lSize);
+ bool Get31EngFullFontInfo(const void * pName, size_t & lOffset, size_t & lSize);
+ bool Get30EngFamilyInfo(const void * pName, size_t & lOffset, size_t & lSize);
+ bool Get30EngFullFontInfo(const void * pName, size_t & lOffset, size_t & lSize);
+ int PostLookup(const void * pPost, size_t lPostSize, const void * pMaxp,
+ const char * pPostName);
+#endif
+
+ ////////////////////////////////// utility methods helpful for name table
+ bool GetNameInfo(const void * pName, int nPlatformId, int nEncodingId,
+ int nLangId, int nNameId, size_t & lOffset, size_t & lSize);
+ //size_t NameTableLength(const byte * pTable);
+#ifdef ALL_TTFUTILS
+ int GetLangsForNames(const void * pName, int nPlatformId, int nEncodingId,
+ int *nameIdList, int cNameIds, short *langIdList);
+ void SwapWString(void * pWStr, size_t nSize = 0); // throw (std::invalid_argument);
+#endif
+
+ ////////////////////////////////// cmap lookup tools
+ const void * FindCmapSubtable(const void * pCmap, int nPlatformId = 3,
+ int nEncodingId = 1, size_t length = 0);
+ bool CheckCmapSubtable4(const void * pCmap31, const void * pCmapEnd /*, unsigned int maxgid*/);
+ gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, int rangeKey = 0);
+ unsigned int CmapSubtable4NextCodepoint(const void *pCmap31, unsigned int nUnicodeId,
+ int * pRangeKey = 0);
+ bool CheckCmapSubtable12(const void *pCmap310, const void * pCmapEnd /*, unsigned int maxgid*/);
+ gid16 CmapSubtable12Lookup(const void * pCmap310, unsigned int uUnicodeId, int rangeKey = 0);
+ unsigned int CmapSubtable12NextCodepoint(const void *pCmap310, unsigned int nUnicodeId,
+ int * pRangeKey = 0);
+
+ ///////////////////////////////// horizontal metric data for a glyph
+ bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize,
+ const void * pHhea, int & nLsb, unsigned int & nAdvWid);
+
+ ////////////////////////////////// primitives for loca and glyf lookup
+ size_t LocaLookup(gid16 nGlyphId, const void * pLoca, size_t lLocaSize,
+ const void * pHead); // throw (std::out_of_range);
+ void * GlyfLookup(const void * pGlyf, size_t lGlyfOffset, size_t lTableLen);
+
+ ////////////////////////////////// primitves for simple glyph data
+ bool GlyfBox(const void * pSimpleGlyf, int & xMin, int & yMin,
+ int & xMax, int & yMax);
+
+#ifdef ALL_TTFUTILS
+ int GlyfContourCount(const void * pSimpleGlyf);
+ bool GlyfContourEndPoints(const void * pSimpleGlyf, int * prgnContourEndPoint,
+ int cnPointsTotal, size_t & cnPoints);
+ bool GlyfPoints(const void * pSimpleGlyf, int * prgnX, int * prgnY,
+ char * prgbFlag, int cnPointsTotal, int & cnPoints);
+
+ // primitive to find the glyph ids in a composite glyph
+ bool GetComponentGlyphIds(const void * pSimpleGlyf, int * prgnCompId,
+ size_t cnCompIdTotal, size_t & cnCompId);
+ // primitive to find the placement data for a component in a composite glyph
+ bool GetComponentPlacement(const void * pSimpleGlyf, int nCompId,
+ bool fOffset, int & a, int & b);
+ // primitive to find the transform data for a component in a composite glyph
+ bool GetComponentTransform(const void * pSimpleGlyf, int nCompId,
+ float & flt11, float & flt12, float & flt21, float & flt22, bool & fTransOffset);
+#endif
+
+ ////////////////////////////////// operate on composite or simple glyph (auto glyf lookup)
+ void * GlyfLookup(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
+ size_t lGlyfSize, size_t lLocaSize, const void * pHead); // primitive used by below methods
+
+#ifdef ALL_TTFUTILS
+ // below are primary user methods for handling glyf data
+ bool IsSpace(gid16 nGlyphId, const void * pLoca, size_t lLocaSize, const void * pHead);
+ bool IsDeepComposite(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
+ size_t lGlyfSize, size_t lLocaSize, const void * pHead);
+
+ bool GlyfBox(gid16 nGlyphId, const void * pGlyf, const void * pLoca, size_t lGlyfSize, size_t lLocaSize,
+ const void * pHead, int & xMin, int & yMin, int & xMax, int & yMax);
+ bool GlyfContourCount(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
+ size_t lGlyfSize, size_t lLocaSize, const void *pHead, size_t & cnContours);
+ bool GlyfContourEndPoints(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
+ size_t lGlyfSize, size_t lLocaSize, const void * pHead, int * prgnContourEndPoint, size_t cnPoints);
+ bool GlyfPoints(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
+ size_t lGlyfSize, size_t lLocaSize, const void * pHead, const int * prgnContourEndPoint, size_t cnEndPoints,
+ int * prgnX, int * prgnY, bool * prgfOnCurve, size_t cnPoints);
+
+ // utitily method used by high-level GlyfPoints
+ bool SimplifyFlags(char * prgbFlags, int cnPoints);
+ bool CalcAbsolutePoints(int * prgnX, int * prgnY, int cnPoints);
+#endif
+
+} // end of namespace TtfUtil
+} // end of namespace graphite2
diff --git a/gfx/graphite2/src/inc/UtfCodec.h b/gfx/graphite2/src/inc/UtfCodec.h
new file mode 100644
index 0000000000..24a343d8d9
--- /dev/null
+++ b/gfx/graphite2/src/inc/UtfCodec.h
@@ -0,0 +1,251 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2011, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+#include <cstdlib>
+#include "inc/Main.h"
+
+namespace graphite2 {
+
+typedef uint32 uchar_t;
+
+template <int N>
+struct _utf_codec
+{
+ typedef uchar_t codeunit_t;
+
+ static void put(codeunit_t * cp, const uchar_t , int8 & len) throw();
+ static uchar_t get(const codeunit_t * cp, int8 & len) throw();
+ static bool validate(const codeunit_t * s, const codeunit_t * const e) throw();
+};
+
+
+template <>
+struct _utf_codec<32>
+{
+private:
+ static const uchar_t limit = 0x110000;
+public:
+ typedef uint32 codeunit_t;
+
+ inline
+ static void put(codeunit_t * cp, const uchar_t usv, int8 & l) throw()
+ {
+ *cp = usv; l = 1;
+ }
+
+ inline
+ static uchar_t get(const codeunit_t * cp, int8 & l) throw()
+ {
+ if (cp[0] < limit) { l = 1; return cp[0]; }
+ else { l = -1; return 0xFFFD; }
+ }
+
+ inline
+ static bool validate(const codeunit_t * s, const codeunit_t * const e) throw()
+ {
+ return s <= e;
+ }
+};
+
+
+template <>
+struct _utf_codec<16>
+{
+private:
+ static const int32 lead_offset = 0xD800 - (0x10000 >> 10);
+ static const int32 surrogate_offset = 0x10000 - (0xD800 << 10) - 0xDC00;
+public:
+ typedef uint16 codeunit_t;
+
+ inline
+ static void put(codeunit_t * cp, const uchar_t usv, int8 & l) throw()
+ {
+ if (usv < 0x10000) { l = 1; cp[0] = codeunit_t(usv); }
+ else
+ {
+ cp[0] = codeunit_t(lead_offset + (usv >> 10));
+ cp[1] = codeunit_t(0xDC00 + (usv & 0x3FF));
+ l = 2;
+ }
+ }
+
+ inline
+ static uchar_t get(const codeunit_t * cp, int8 & l) throw()
+ {
+ const uint32 uh = cp[0];
+ l = 1;
+
+ if (uh < 0xD800|| uh > 0xDFFF) { return uh; }
+ if (uh > 0xDBFF) { l = -1; return 0xFFFD; }
+ const uint32 ul = cp[1];
+ if (ul < 0xDC00 || ul > 0xDFFF) { l = -1; return 0xFFFD; }
+ ++l;
+ return (uh<<10) + ul + surrogate_offset;
+ }
+
+ inline
+ static bool validate(const codeunit_t * s, const codeunit_t * const e) throw()
+ {
+ const ptrdiff_t n = e-s;
+ if (n <= 0) return n == 0;
+ const uint32 u = *(e-1); // Get the last codepoint
+ return (u < 0xD800 || u > 0xDBFF);
+ }
+};
+
+
+template <>
+struct _utf_codec<8>
+{
+private:
+ static const int8 sz_lut[16];
+ static const byte mask_lut[5];
+ static const uchar_t limit = 0x110000;
+
+public:
+ typedef uint8 codeunit_t;
+
+ inline
+ static void put(codeunit_t * cp, const uchar_t usv, int8 & l) throw()
+ {
+ if (usv < 0x80) {l = 1; cp[0] = usv; return; }
+ if (usv < 0x0800) {l = 2; cp[0] = 0xC0 + (usv >> 6); cp[1] = 0x80 + (usv & 0x3F); return; }
+ if (usv < 0x10000) {l = 3; cp[0] = 0xE0 + (usv >> 12); cp[1] = 0x80 + ((usv >> 6) & 0x3F); cp[2] = 0x80 + (usv & 0x3F); return; }
+ else {l = 4; cp[0] = 0xF0 + (usv >> 18); cp[1] = 0x80 + ((usv >> 12) & 0x3F); cp[2] = 0x80 + ((usv >> 6) & 0x3F); cp[3] = 0x80 + (usv & 0x3F); return; }
+ }
+
+ inline
+ static uchar_t get(const codeunit_t * cp, int8 & l) throw()
+ {
+ const int8 seq_sz = sz_lut[*cp >> 4];
+ uchar_t u = *cp & mask_lut[seq_sz];
+ l = 1;
+ bool toolong = false;
+
+ switch(seq_sz) {
+ case 4: u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong = (u < 0x10); GR_FALLTHROUGH;
+ // no break
+ case 3: u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x20); GR_FALLTHROUGH;
+ // no break
+ case 2: u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x80); GR_FALLTHROUGH;
+ // no break
+ case 1: break;
+ case 0: l = -1; return 0xFFFD;
+ }
+
+ if (l != seq_sz || toolong || u >= limit)
+ {
+ l = -l;
+ return 0xFFFD;
+ }
+ return u;
+ }
+
+ inline
+ static bool validate(const codeunit_t * s, const codeunit_t * const e) throw()
+ {
+ const ptrdiff_t n = e-s;
+ if (n <= 0) return n == 0;
+ s += (n-1);
+ if (*s < 0x80) return true;
+ if (*s >= 0xC0) return false;
+ if (n == 1) return true;
+ if (*--s < 0x80) return true;
+ if (*s >= 0xE0) return false;
+ if (n == 2 || *s >= 0xC0) return true;
+ if (*--s < 0x80) return true;
+ if (*s >= 0xF0) return false;
+ return true;
+ }
+
+};
+
+
+template <typename C>
+class _utf_iterator
+{
+ typedef _utf_codec<sizeof(C)*8> codec;
+
+ C * cp;
+ mutable int8 sl;
+
+public:
+ typedef C codeunit_type;
+ typedef uchar_t value_type;
+ typedef uchar_t * pointer;
+
+ class reference
+ {
+ const _utf_iterator & _i;
+
+ reference(const _utf_iterator & i): _i(i) {}
+ public:
+ operator value_type () const throw () { return codec::get(_i.cp, _i.sl); }
+ reference & operator = (const value_type usv) throw() { codec::put(_i.cp, usv, _i.sl); return *this; }
+
+ friend class _utf_iterator;
+ };
+
+
+ _utf_iterator(const void * us=0) : cp(reinterpret_cast<C *>(const_cast<void *>(us))), sl(1) { }
+
+ _utf_iterator & operator ++ () { cp += abs(sl); return *this; }
+ _utf_iterator operator ++ (int) { _utf_iterator tmp(*this); operator++(); return tmp; }
+
+ bool operator == (const _utf_iterator & rhs) const throw() { return cp >= rhs.cp; }
+ bool operator != (const _utf_iterator & rhs) const throw() { return !operator==(rhs); }
+
+ reference operator * () const throw() { return *this; }
+ pointer operator ->() const throw() { return &operator *(); }
+
+ operator codeunit_type * () const throw() { return cp; }
+
+ bool error() const throw() { return sl < 1; }
+ bool validate(const _utf_iterator & e) { return codec::validate(cp, e.cp); }
+};
+
+template <typename C>
+struct utf
+{
+ typedef typename _utf_codec<sizeof(C)*8>::codeunit_t codeunit_t;
+
+ typedef _utf_iterator<C> iterator;
+ typedef _utf_iterator<const C> const_iterator;
+
+ inline
+ static bool validate(codeunit_t * s, codeunit_t * e) throw() {
+ return _utf_codec<sizeof(C)*8>::validate(s,e);
+ }
+};
+
+
+typedef utf<uint32> utf32;
+typedef utf<uint16> utf16;
+typedef utf<uint8> utf8;
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/bits.h b/gfx/graphite2/src/inc/bits.h
new file mode 100644
index 0000000000..9365986a10
--- /dev/null
+++ b/gfx/graphite2/src/inc/bits.h
@@ -0,0 +1,150 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2012, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+
+namespace graphite2
+{
+
+
+#if defined GRAPHITE2_BUILTINS && (defined __GNUC__ || defined __clang__)
+
+template<typename T>
+inline unsigned int bit_set_count(T v)
+{
+ return __builtin_popcount(v);
+}
+
+template<>
+inline unsigned int bit_set_count(int16 v)
+{
+ return __builtin_popcount(static_cast<uint16>(v));
+}
+
+template<>
+inline unsigned int bit_set_count(int8 v)
+{
+ return __builtin_popcount(static_cast<uint8>(v));
+}
+
+template<>
+inline unsigned int bit_set_count(unsigned long v)
+{
+ return __builtin_popcountl(v);
+}
+
+template<>
+inline unsigned int bit_set_count(signed long v)
+{
+ return __builtin_popcountl(v);
+}
+
+template<>
+inline unsigned int bit_set_count(unsigned long long v)
+{
+ return __builtin_popcountll(v);
+}
+
+template<>
+inline unsigned int bit_set_count(signed long long v)
+{
+ return __builtin_popcountll(v);
+}
+
+#else
+
+template<typename T>
+inline unsigned int bit_set_count(T v)
+{
+ static size_t const ONES = ~0;
+
+ v = v - ((v >> 1) & T(ONES/3)); // temp
+ v = (v & T(ONES/15*3)) + ((v >> 2) & T(ONES/15*3)); // temp
+ v = (v + (v >> 4)) & T(ONES/255*15); // temp
+ return (T)(v * T(ONES/255)) >> (sizeof(T)-1)*8; // count
+}
+
+#endif
+
+//TODO: Changed these to uintmax_t when we go to C++11
+template<int S>
+inline size_t _mask_over_val(size_t v)
+{
+ v = _mask_over_val<S/2>(v);
+ v |= v >> S*4;
+ return v;
+}
+
+//TODO: Changed these to uintmax_t when we go to C++11
+template<>
+inline size_t _mask_over_val<1>(size_t v)
+{
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ return v;
+}
+
+template<typename T>
+inline T mask_over_val(T v)
+{
+ return T(_mask_over_val<sizeof(T)>(v));
+}
+
+template<typename T>
+inline unsigned long next_highest_power2(T v)
+{
+ return _mask_over_val<sizeof(T)>(v-1)+1;
+}
+
+template<typename T>
+inline unsigned int log_binary(T v)
+{
+ return bit_set_count(mask_over_val(v))-1;
+}
+
+template<typename T>
+inline T has_zero(const T x)
+{
+ return (x - T(~T(0)/255)) & ~x & T(~T(0)/255*128);
+}
+
+template<typename T>
+inline T zero_bytes(const T x, unsigned char n)
+{
+ const T t = T(~T(0)/255*n);
+ return T((has_zero(x^t) >> 7)*n);
+}
+
+#if 0
+inline float float_round(float x, uint32 m)
+{
+ *reinterpret_cast<unsigned int *>(&x) &= m;
+ return *reinterpret_cast<float *>(&x);
+}
+#endif
+
+}
diff --git a/gfx/graphite2/src/inc/debug.h b/gfx/graphite2/src/inc/debug.h
new file mode 100644
index 0000000000..97175eb2cc
--- /dev/null
+++ b/gfx/graphite2/src/inc/debug.h
@@ -0,0 +1,89 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2011, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+// debug.h
+//
+// Created on: 22 Dec 2011
+// Author: tim
+
+#pragma once
+
+#if !defined GRAPHITE2_NTRACING
+
+#include <utility>
+#include "inc/json.h"
+#include "inc/Position.h"
+
+namespace graphite2
+{
+
+class CharInfo;
+class Segment;
+class Slot;
+
+typedef std::pair<const Segment * const, const Slot * const> dslot;
+struct objectid
+{
+ char name[16];
+ objectid(const dslot &) throw();
+ objectid(const Segment * const p) throw();
+};
+
+
+json & operator << (json & j, const Position &) throw();
+json & operator << (json & j, const Rect &) throw();
+json & operator << (json & j, const CharInfo &) throw();
+json & operator << (json & j, const dslot &) throw();
+json & operator << (json & j, const objectid &) throw();
+json & operator << (json & j, const telemetry &) throw();
+
+
+
+inline
+json & operator << (json & j, const Position & p) throw()
+{
+ return j << json::flat << json::array << p.x << p.y << json::close;
+}
+
+
+inline
+json & operator << (json & j, const Rect & p) throw()
+{
+ return j << json::flat << json::array << p.bl.x << p.bl.y << p.tr.x << p.tr.y << json::close;
+}
+
+
+inline
+json & operator << (json & j, const objectid & sid) throw()
+{
+ return j << sid.name;
+}
+
+
+} // namespace graphite2
+
+#endif //!defined GRAPHITE2_NTRACING
+
diff --git a/gfx/graphite2/src/inc/json.h b/gfx/graphite2/src/inc/json.h
new file mode 100644
index 0000000000..554cd9a3d1
--- /dev/null
+++ b/gfx/graphite2/src/inc/json.h
@@ -0,0 +1,178 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2011, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+// JSON pretty printer for graphite font debug output logging.
+// Created on: 15 Dec 2011
+// Author: Tim Eves
+
+#pragma once
+
+#include "inc/Main.h"
+#include <cassert>
+#include <cstdio>
+#include <cstdint>
+#include "inc/List.h"
+
+namespace graphite2 {
+
+class json
+{
+ // Prevent copying
+ json(const json &);
+ json & operator = (const json &);
+
+ typedef void (*_context_t)(json &);
+
+ FILE * const _stream;
+ char _contexts[128], // context stack
+ * _context, // current context (top of stack)
+ * _flatten; // if !0 points to context above which
+ // pretty printed output should occur.
+ Vector<void *> _env;
+
+ void context(const char current) throw();
+ void indent(const int d=0) throw();
+ void push_context(const char, const char) throw();
+ void pop_context() throw();
+
+public:
+ class closer;
+
+ using string = const char *;
+ using number = double;
+ enum class integer : std::intmax_t {};
+ enum class integer_u : std::uintmax_t {};
+ using boolean = bool;
+ static const std::nullptr_t null;
+
+ void setenv(unsigned int index, void *val) { _env.reserve(index + 1); if (index >= _env.size()) _env.insert(_env.end(), _env.size() - index + 1, 0); _env[index] = val; }
+ void *getenv(unsigned int index) const { return _env[index]; }
+ const Vector<void *> &getenvs() const { return _env; }
+
+ static void flat(json &) throw();
+ static void close(json &) throw();
+ static void object(json &) throw();
+ static void array(json &) throw();
+ static void item(json &) throw();
+
+ json(FILE * stream) throw();
+ ~json() throw ();
+
+ FILE * stream() const throw();
+
+ json & operator << (string) throw();
+ json & operator << (number) throw();
+ json & operator << (integer) throw();
+ json & operator << (integer_u) throw();
+ json & operator << (boolean) throw();
+ json & operator << (std::nullptr_t) throw();
+ json & operator << (_context_t) throw();
+
+ operator bool() const throw();
+ bool good() const throw();
+ bool eof() const throw();
+
+ CLASS_NEW_DELETE;
+};
+
+class json::closer
+{
+ // Prevent copying.
+ closer(const closer &);
+ closer & operator = (const closer &);
+
+ json * const _j;
+public:
+ closer(json * const j) : _j(j) {}
+ ~closer() throw() { if (_j) *_j << close; }
+};
+
+inline
+json::json(FILE * s) throw()
+: _stream(s), _context(_contexts), _flatten(0)
+{
+ if (good())
+ fflush(s);
+}
+
+
+inline
+json::~json() throw ()
+{
+ while (_context > _contexts) pop_context();
+}
+
+inline
+FILE * json::stream() const throw() { return _stream; }
+
+
+inline
+json & json::operator << (json::_context_t ctxt) throw()
+{
+ ctxt(*this);
+ return *this;
+}
+
+inline
+json & operator << (json & j, signed char d) throw() { return j << json::integer(d); }
+
+inline
+json & operator << (json & j, unsigned char d) throw() { return j << json::integer_u(d); }
+
+inline
+json & operator << (json & j, short int d) throw() { return j << json::integer(d); }
+
+inline
+json & operator << (json & j, unsigned short int d) throw() { return j << json::integer_u(d); }
+
+inline
+json & operator << (json & j, int d) throw() { return j << json::integer(d); }
+
+inline
+json & operator << (json & j, unsigned int d) throw() { return j << json::integer_u(d); }
+
+inline
+json & operator << (json & j, long int d) throw() { return j << json::integer(d); }
+
+inline
+json & operator << (json & j, unsigned long int d) throw() { return j << json::integer_u(d); }
+
+inline
+json & operator << (json & j, long long int d) throw() { return j << json::integer(d); }
+
+inline
+json & operator << (json & j, unsigned long long int d) throw() { return j << json::integer_u(d); }
+
+inline
+json::operator bool() const throw() { return good(); }
+
+inline
+bool json::good() const throw() { return _stream && ferror(_stream) == 0; }
+
+inline
+bool json::eof() const throw() { return feof(_stream) != 0; }
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/locale2lcid.h b/gfx/graphite2/src/inc/locale2lcid.h
new file mode 100644
index 0000000000..25d5c0a3c8
--- /dev/null
+++ b/gfx/graphite2/src/inc/locale2lcid.h
@@ -0,0 +1,450 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+#include <cstring>
+#include <cassert>
+
+#include "inc/Main.h"
+
+
+namespace graphite2 {
+
+struct IsoLangEntry
+{
+ unsigned short mnLang;
+ char maLangStr[4];
+ char maCountry[3];
+};
+
+// Windows Language ID, Locale ISO-639 language, country code as used in
+// naming table of OpenType fonts
+const IsoLangEntry LANG_ENTRIES[] = {
+ { 0x0401, "ar","SA" }, // Arabic Saudi Arabia
+ { 0x0402, "bg","BG" }, // Bulgarian Bulgaria
+ { 0x0403, "ca","ES" }, // Catalan Catalan
+ { 0x0404, "zh","TW" }, // Chinese Taiwan
+ { 0x0405, "cs","CZ" }, // Czech Czech Republic
+ { 0x0406, "da","DK" }, // Danish Denmark
+ { 0x0407, "de","DE" }, // German Germany
+ { 0x0408, "el","GR" }, // Greek Greece
+ { 0x0409, "en","US" }, // English United States
+ { 0x040A, "es","ES" }, // Spanish (Traditional Sort) Spain
+ { 0x040B, "fi","FI" }, // Finnish Finland
+ { 0x040C, "fr","FR" }, // French France
+ { 0x040D, "he","IL" }, // Hebrew Israel
+ { 0x040E, "hu","HU" }, // Hungarian Hungary
+ { 0x040F, "is","IS" }, // Icelandic Iceland
+ { 0x0410, "it","IT" }, // Italian Italy
+ { 0x0411, "jp","JP" }, // Japanese Japan
+ { 0x0412, "ko","KR" }, // Korean Korea
+ { 0x0413, "nl","NL" }, // Dutch Netherlands
+ { 0x0414, "no","NO" }, // Norwegian (Bokmal) Norway
+ { 0x0415, "pl","PL" }, // Polish Poland
+ { 0x0416, "pt","BR" }, // Portuguese Brazil
+ { 0x0417, "rm","CH" }, // Romansh Switzerland
+ { 0x0418, "ro","RO" }, // Romanian Romania
+ { 0x0419, "ru","RU" }, // Russian Russia
+ { 0x041A, "hr","HR" }, // Croatian Croatia
+ { 0x041B, "sk","SK" }, // Slovak Slovakia
+ { 0x041C, "sq","AL" }, // Albanian Albania
+ { 0x041D, "sv","SE" }, // Swedish Sweden
+ { 0x041E, "th","TH" }, // Thai Thailand
+ { 0x041F, "tr","TR" }, // Turkish Turkey
+ { 0x0420, "ur","PK" }, // Urdu Islamic Republic of Pakistan
+ { 0x0421, "id","ID" }, // Indonesian Indonesia
+ { 0x0422, "uk","UA" }, // Ukrainian Ukraine
+ { 0x0423, "be","BY" }, // Belarusian Belarus
+ { 0x0424, "sl","SI" }, // Slovenian Slovenia
+ { 0x0425, "et","EE" }, // Estonian Estonia
+ { 0x0426, "lv","LV" }, // Latvian Latvia
+ { 0x0427, "lt","LT" }, // Lithuanian Lithuania
+ { 0x0428, "tg","TJ" }, // Tajik (Cyrillic) Tajikistan
+ { 0x042A, "vi","VN" }, // Vietnamese Vietnam
+ { 0x042B, "hy","AM" }, // Armenian Armenia
+ { 0x042C, "az","AZ" }, // Azeri (Latin) Azerbaijan
+ { 0x042D, "eu","" }, // Basque Basque
+ { 0x042E, "hsb","DE" }, // Upper Sorbian Germany
+ { 0x042F, "mk","MK" }, // Macedonian (FYROM) Former Yugoslav Republic of Macedonia
+ { 0x0432, "tn","ZA" }, // Setswana South Africa
+ { 0x0434, "xh","ZA" }, // isiXhosa South Africa
+ { 0x0435, "zu","ZA" }, // isiZulu South Africa
+ { 0x0436, "af","ZA" }, // Afrikaans South Africa
+ { 0x0437, "ka","GE" }, // Georgian Georgia
+ { 0x0438, "fo","FO" }, // Faroese Faroe Islands
+ { 0x0439, "hi","IN" }, // Hindi India
+ { 0x043A, "mt","MT" }, // Maltese Malta
+ { 0x043B, "se","NO" }, // Sami (Northern) Norway
+ { 0x043E, "ms","MY" }, // Malay Malaysia
+ { 0x043F, "kk","KZ" }, // Kazakh Kazakhstan
+ { 0x0440, "ky","KG" }, // Kyrgyz Kyrgyzstan
+ { 0x0441, "sw","KE" }, // Kiswahili Kenya
+ { 0x0442, "tk","TM" }, // Turkmen Turkmenistan
+ { 0x0443, "uz","UZ" }, // Uzbek (Latin) Uzbekistan
+ { 0x0444, "tt","RU" }, // Tatar Russia
+ { 0x0445, "bn","IN" }, // Bengali India
+ { 0x0446, "pa","IN" }, // Punjabi India
+ { 0x0447, "gu","IN" }, // Gujarati India
+ { 0x0448, "or","IN" }, // Oriya India
+ { 0x0448, "wo","SN" }, // Wolof Senegal
+ { 0x0449, "ta","IN" }, // Tamil India
+ { 0x044A, "te","IN" }, // Telugu India
+ { 0x044B, "kn","IN" }, // Kannada India
+ { 0x044C, "ml","IN" }, // Malayalam India
+ { 0x044D, "as","IN" }, // Assamese India
+ { 0x044E, "mr","IN" }, // Marathi India
+ { 0x044F, "sa","IN" }, // Sanskrit India
+ { 0x0450, "mn","MN" }, // Mongolian (Cyrillic) Mongolia
+ { 0x0451, "bo","CN" }, // Tibetan PRC
+ { 0x0452, "cy","GB" }, // Welsh United Kingdom
+ { 0x0453, "km","KH" }, // Khmer Cambodia
+ { 0x0454, "lo","LA" }, // Lao Lao P.D.R.
+ { 0x0455, "my","MM" }, // Burmese Myanmar - not listed in Microsoft docs anymore
+ { 0x0456, "gl","ES" }, // Galician Galician
+ { 0x0457, "kok","IN" }, // Konkani India
+ { 0x045A, "syr","TR" }, // Syriac Syria
+ { 0x045B, "si","LK" }, // Sinhala Sri Lanka
+ { 0x045D, "iu","CA" }, // Inuktitut Canada
+ { 0x045E, "am","ET" }, // Amharic Ethiopia
+ { 0x0461, "ne","NP" }, // Nepali Nepal
+ { 0x0462, "fy","NL" }, // Frisian Netherlands
+ { 0x0463, "ps","AF" }, // Pashto Afghanistan
+ { 0x0464, "fil","PH" }, // Filipino Philippines
+ { 0x0465, "dv","MV" }, // Divehi Maldives
+ { 0x0468, "ha","NG" }, // Hausa (Latin) Nigeria
+ { 0x046A, "yo","NG" }, // Yoruba Nigeria
+ { 0x046B, "qu","BO" }, // Quechua Bolivia
+ { 0x046C, "st","ZA" }, // Sesotho sa Leboa South Africa
+ { 0x046D, "ba","RU" }, // Bashkir Russia
+ { 0x046E, "lb","LU" }, // Luxembourgish Luxembourg
+ { 0x046F, "kl","GL" }, // Greenlandic Greenland
+ { 0x0470, "ig","NG" }, // Igbo Nigeria
+ { 0x0478, "ii","CN" }, // Yi PRC
+ { 0x047A, "arn","CL" }, // Mapudungun Chile
+ { 0x047C, "moh","CA" }, // Mohawk Mohawk
+ { 0x047E, "br","FR" }, // Breton France
+ { 0x0480, "ug","CN" }, // Uighur PRC
+ { 0x0481, "mi","NZ" }, // Maori New Zealand
+ { 0x0482, "oc","FR" }, // Occitan France
+ { 0x0483, "co","FR" }, // Corsican France
+ { 0x0484, "gsw","FR" }, // Alsatian France
+ { 0x0485, "sah","RU" }, // Yakut Russia
+ { 0x0486, "qut","GT" }, // K'iche Guatemala
+ { 0x0487, "rw","RW" }, // Kinyarwanda Rwanda
+ { 0x048C, "gbz","AF" }, // Dari Afghanistan
+ { 0x0801, "ar","IQ" }, // Arabic Iraq
+ { 0x0804, "zn","CH" }, // Chinese People's Republic of China
+ { 0x0807, "de","CH" }, // German Switzerland
+ { 0x0809, "en","GB" }, // English United Kingdom
+ { 0x080A, "es","MX" }, // Spanish Mexico
+ { 0x080C, "fr","BE" }, // French Belgium
+ { 0x0810, "it","CH" }, // Italian Switzerland
+ { 0x0813, "nl","BE" }, // Dutch Belgium
+ { 0x0814, "nn","NO" }, // Norwegian (Nynorsk) Norway
+ { 0x0816, "pt","PT" }, // Portuguese Portugal
+ { 0x081A, "sh","RS" }, // Serbian (Latin) Serbia
+ { 0x081D, "sv","FI" }, // Sweden Finland
+ { 0x082C, "az","AZ" }, // Azeri (Cyrillic) Azerbaijan
+ { 0x082E, "dsb","DE" }, // Lower Sorbian Germany
+ { 0x083B, "se","SE" }, // Sami (Northern) Sweden
+ { 0x083C, "ga","IE" }, // Irish Ireland
+ { 0x083E, "ms","BN" }, // Malay Brunei Darussalam
+ { 0x0843, "uz","UZ" }, // Uzbek (Cyrillic) Uzbekistan
+ { 0x0845, "bn","BD" }, // Bengali Bangladesh
+ { 0x0850, "mn","MN" }, // Mongolian (Traditional) People's Republic of China
+ { 0x085D, "iu","CA" }, // Inuktitut (Latin) Canada
+ { 0x085F, "ber","DZ" }, // Tamazight (Latin) Algeria
+ { 0x086B, "es","EC" }, // Quechua Ecuador
+ { 0x0C01, "ar","EG" }, // Arabic Egypt
+ { 0x0C04, "zh","HK" }, // Chinese Hong Kong S.A.R.
+ { 0x0C07, "de","AT" }, // German Austria
+ { 0x0C09, "en","AU" }, // English Australia
+ { 0x0C0A, "es","ES" }, // Spanish (Modern Sort) Spain
+ { 0x0C0C, "fr","CA" }, // French Canada
+ { 0x0C1A, "sr","CS" }, // Serbian (Cyrillic) Serbia
+ { 0x0C3B, "se","FI" }, // Sami (Northern) Finland
+ { 0x0C6B, "qu","PE" }, // Quechua Peru
+ { 0x1001, "ar","LY" }, // Arabic Libya
+ { 0x1004, "zh","SG" }, // Chinese Singapore
+ { 0x1007, "de","LU" }, // German Luxembourg
+ { 0x1009, "en","CA" }, // English Canada
+ { 0x100A, "es","GT" }, // Spanish Guatemala
+ { 0x100C, "fr","CH" }, // French Switzerland
+ { 0x101A, "hr","BA" }, // Croatian (Latin) Bosnia and Herzegovina
+ { 0x103B, "smj","NO" }, // Sami (Lule) Norway
+ { 0x1401, "ar","DZ" }, // Arabic Algeria
+ { 0x1404, "zh","MO" }, // Chinese Macao S.A.R.
+ { 0x1407, "de","LI" }, // German Liechtenstein
+ { 0x1409, "en","NZ" }, // English New Zealand
+ { 0x140A, "es","CR" }, // Spanish Costa Rica
+ { 0x140C, "fr","LU" }, // French Luxembourg
+ { 0x141A, "bs","BA" }, // Bosnian (Latin) Bosnia and Herzegovina
+ { 0x143B, "smj","SE" }, // Sami (Lule) Sweden
+ { 0x1801, "ar","MA" }, // Arabic Morocco
+ { 0x1809, "en","IE" }, // English Ireland
+ { 0x180A, "es","PA" }, // Spanish Panama
+ { 0x180C, "fr","MC" }, // French Principality of Monoco
+ { 0x181A, "sh","BA" }, // Serbian (Latin) Bosnia and Herzegovina
+ { 0x183B, "sma","NO" }, // Sami (Southern) Norway
+ { 0x1C01, "ar","TN" }, // Arabic Tunisia
+ { 0x1C09, "en","ZA" }, // English South Africa
+ { 0x1C0A, "es","DO" }, // Spanish Dominican Republic
+ { 0x1C1A, "sr","BA" }, // Serbian (Cyrillic) Bosnia and Herzegovina
+ { 0x1C3B, "sma","SE" }, // Sami (Southern) Sweden
+ { 0x2001, "ar","OM" }, // Arabic Oman
+ { 0x2009, "en","JM" }, // English Jamaica
+ { 0x200A, "es","VE" }, // Spanish Venezuela
+ { 0x201A, "bs","BA" }, // Bosnian (Cyrillic) Bosnia and Herzegovina
+ { 0x203B, "sms","FI" }, // Sami (Skolt) Finland
+ { 0x2401, "ar","YE" }, // Arabic Yemen
+ { 0x2409, "en","BS" }, // English Caribbean
+ { 0x240A, "es","CO" }, // Spanish Colombia
+ { 0x243B, "smn","FI" }, // Sami (Inari) Finland
+ { 0x2801, "ar","SY" }, // Arabic Syria
+ { 0x2809, "en","BZ" }, // English Belize
+ { 0x280A, "es","PE" }, // Spanish Peru
+ { 0x2C01, "ar","JO" }, // Arabic Jordan
+ { 0x2C09, "en","TT" }, // English Trinidad and Tobago
+ { 0x2C0A, "es","AR" }, // Spanish Argentina
+ { 0x3001, "ar","LB" }, // Arabic Lebanon
+ { 0x3009, "en","ZW" }, // English Zimbabwe
+ { 0x300A, "es","EC" }, // Spanish Ecuador
+ { 0x3401, "ar","KW" }, // Arabic Kuwait
+ { 0x3409, "en","PH" }, // English Republic of the Philippines
+ { 0x340A, "es","CL" }, // Spanish Chile
+ { 0x3801, "ar","AE" }, // Arabic U.A.E.
+ { 0x380A, "es","UY" }, // Spanish Uruguay
+ { 0x3C01, "ar","BH" }, // Arabic Bahrain
+ { 0x3C0A, "es","PY" }, // Spanish Paraguay
+ { 0x4001, "ar","QA" }, // Arabic Qatar
+ { 0x4009, "en","IN" }, // English India
+ { 0x400A, "es","BO" }, // Spanish Bolivia
+ { 0x4409, "en","MY" }, // English Malaysia
+ { 0x440A, "es","SV" }, // Spanish El Salvador
+ { 0x4809, "en","SG" }, // English Singapore
+ { 0x480A, "es","HN" }, // Spanish Honduras
+ { 0x4C0A, "es","NI" }, // Spanish Nicaragua
+ { 0x500A, "es","PR" }, // Spanish Puerto Rico
+ { 0x540A, "es","US" } // Spanish United States
+};
+
+class Locale2Lang
+{
+ Locale2Lang(const Locale2Lang &);
+ Locale2Lang & operator = (const Locale2Lang &);
+
+public:
+ Locale2Lang() : mSeedPosition(128)
+ {
+ memset((void*)mLangLookup, 0, sizeof(mLangLookup));
+ // create a tri lookup on first 2 letters of language code
+ static const int maxIndex = sizeof(LANG_ENTRIES)/sizeof(IsoLangEntry);
+ for (int i = 0; i < maxIndex; i++)
+ {
+ size_t a = LANG_ENTRIES[i].maLangStr[0] - 'a';
+ size_t b = LANG_ENTRIES[i].maLangStr[1] - 'a';
+ if (mLangLookup[a][b])
+ {
+ const IsoLangEntry ** old = mLangLookup[a][b];
+ int len = 1;
+ while (old[len]) len++;
+ len += 2;
+ mLangLookup[a][b] = gralloc<const IsoLangEntry *>(len);
+ if (!mLangLookup[a][b])
+ {
+ mLangLookup[a][b] = old;
+ continue;
+ }
+ mLangLookup[a][b][--len] = NULL;
+ mLangLookup[a][b][--len] = &LANG_ENTRIES[i];
+ while (--len >= 0)
+ {
+ assert(len >= 0);
+ mLangLookup[a][b][len] = old[len];
+ }
+ free(old);
+ }
+ else
+ {
+ mLangLookup[a][b] = gralloc<const IsoLangEntry *>(2);
+ if (!mLangLookup[a][b]) continue;
+ mLangLookup[a][b][1] = NULL;
+ mLangLookup[a][b][0] = &LANG_ENTRIES[i];
+ }
+ }
+ while (2 * mSeedPosition < maxIndex)
+ mSeedPosition *= 2;
+ };
+ ~Locale2Lang()
+ {
+ for (int i = 0; i != 26; ++i)
+ for (int j = 0; j != 26; ++j)
+ free(mLangLookup[i][j]);
+ }
+ unsigned short getMsId(const char * locale) const
+ {
+ size_t length = strlen(locale);
+ size_t langLength = length;
+ const char * language = locale;
+ const char * script = NULL;
+ const char * region = NULL;
+ size_t regionLength = 0;
+ const char * dash = strchr(locale, '-');
+ if (dash && (dash != locale))
+ {
+ langLength = (dash - locale);
+ size_t nextPartLength = length - langLength - 1;
+ if (nextPartLength >= 2)
+ {
+ script = ++dash;
+ dash = strchr(dash, '-');
+ if (dash)
+ {
+ nextPartLength = (dash - script);
+ region = ++dash;
+ }
+ if (nextPartLength == 2 &&
+ (locale[langLength+1] > 0x40) && (locale[langLength+1] < 0x5B) &&
+ (locale[langLength+2] > 0x40) && (locale[langLength+2] < 0x5B))
+ {
+ region = script;
+ regionLength = nextPartLength;
+ script = NULL;
+ }
+ else if (nextPartLength == 4)
+ {
+ if (dash)
+ {
+ dash = strchr(dash, '-');
+ if (dash)
+ {
+ nextPartLength = (dash - region);
+ }
+ else
+ {
+ nextPartLength = langLength - (region - locale);
+ }
+ regionLength = nextPartLength;
+ }
+ }
+ }
+ }
+ size_t a = 'e' - 'a';
+ size_t b = 'n' - 'a';
+ unsigned short langId = 0;
+ int i = 0;
+ switch (langLength)
+ {
+ case 2:
+ {
+ a = language[0] - 'a';
+ b = language[1] - 'a';
+ if ((a < 26) && (b < 26) && mLangLookup[a][b])
+ {
+ while (mLangLookup[a][b][i])
+ {
+ if (mLangLookup[a][b][i]->maLangStr[2] != '\0')
+ {
+ ++i;
+ continue;
+ }
+ if (region && (strncmp(mLangLookup[a][b][i]->maCountry, region, regionLength) == 0))
+ {
+ langId = mLangLookup[a][b][i]->mnLang;
+ break;
+ }
+ else if (langId == 0)
+ {
+ // possible fallback code
+ langId = mLangLookup[a][b][i]->mnLang;
+ }
+ ++i;
+ }
+ }
+ }
+ break;
+ case 3:
+ {
+ a = language[0] - 'a';
+ b = language[1] - 'a';
+ if (mLangLookup[a][b])
+ {
+ while (mLangLookup[a][b][i])
+ {
+ if (mLangLookup[a][b][i]->maLangStr[2] != language[2])
+ {
+ ++i;
+ continue;
+ }
+ if (region && (strncmp(mLangLookup[a][b][i]->maCountry, region, regionLength) == 0))
+ {
+ langId = mLangLookup[a][b][i]->mnLang;
+ break;
+ }
+ else if (langId == 0)
+ {
+ // possible fallback code
+ langId = mLangLookup[a][b][i]->mnLang;
+ }
+ ++i;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if (langId == 0) langId = 0x409;
+ return langId;
+ }
+ const IsoLangEntry * findEntryById(unsigned short langId) const
+ {
+ static const int maxIndex = sizeof(LANG_ENTRIES)/sizeof(IsoLangEntry);
+ int window = mSeedPosition;
+ int guess = mSeedPosition - 1;
+ while (LANG_ENTRIES[guess].mnLang != langId)
+ {
+ window /= 2;
+ if (window == 0) return NULL;
+ guess += (LANG_ENTRIES[guess].mnLang > langId)? -window : window;
+ while (guess >= maxIndex)
+ {
+ window /= 2;
+ guess -= window;
+ assert(window);
+ }
+ }
+ return &LANG_ENTRIES[guess];
+ }
+
+ CLASS_NEW_DELETE;
+
+private:
+ const IsoLangEntry ** mLangLookup[26][26];
+ int mSeedPosition;
+};
+
+} // namespace graphite2
diff --git a/gfx/graphite2/src/inc/opcode_table.h b/gfx/graphite2/src/inc/opcode_table.h
new file mode 100644
index 0000000000..cb5acde9a4
--- /dev/null
+++ b/gfx/graphite2/src/inc/opcode_table.h
@@ -0,0 +1,124 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+// This file will be pulled into and integrated into a machine implmentation
+// DO NOT build directly
+#pragma once
+
+#define do2(n) do_(n) ,do_(n)
+#define NILOP 0U
+
+// types or parameters are: (.. is inclusive)
+// number - any byte
+// output_class - 0 .. silf.m_nClass
+// input_class - 0 .. silf.m_nClass
+// sattrnum - 0 .. 29 (gr_slatJWidth) , 55 (gr_slatUserDefn)
+// attrid - 0 .. silf.numUser() where sattrnum == 55; 0..silf.m_iMaxComp where sattrnum == 15 otherwise 0
+// gattrnum - 0 .. face->getGlyphFaceCache->numAttrs()
+// gmetric - 0 .. 11 (kgmetDescent)
+// featidx - 0 .. face.numFeatures()
+// level - any byte
+static const opcode_t opcode_table[] =
+{
+ {{do2(nop)}, 0, "NOP"},
+
+ {{do2(push_byte)}, 1, "PUSH_BYTE"}, // number
+ {{do2(push_byte_u)}, 1, "PUSH_BYTE_U"}, // number
+ {{do2(push_short)}, 2, "PUSH_SHORT"}, // number number
+ {{do2(push_short_u)}, 2, "PUSH_SHORT_U"}, // number number
+ {{do2(push_long)}, 4, "PUSH_LONG"}, // number number number number
+
+ {{do2(add)}, 0, "ADD"},
+ {{do2(sub)}, 0, "SUB"},
+ {{do2(mul)}, 0, "MUL"},
+ {{do2(div_)}, 0, "DIV"},
+ {{do2(min_)}, 0, "MIN"},
+ {{do2(max_)}, 0, "MAX"},
+ {{do2(neg)}, 0, "NEG"},
+ {{do2(trunc8)}, 0, "TRUNC8"},
+ {{do2(trunc16)}, 0, "TRUNC16"},
+
+ {{do2(cond)}, 0, "COND"},
+ {{do2(and_)}, 0, "AND"}, // 0x10
+ {{do2(or_)}, 0, "OR"},
+ {{do2(not_)}, 0, "NOT"},
+ {{do2(equal)}, 0, "EQUAL"},
+ {{do2(not_eq_)}, 0, "NOT_EQ"},
+ {{do2(less)}, 0, "LESS"},
+ {{do2(gtr)}, 0, "GTR"},
+ {{do2(less_eq)}, 0, "LESS_EQ"},
+ {{do2(gtr_eq)}, 0, "GTR_EQ"}, // 0x18
+
+ {{do_(next), NILOP}, 0, "NEXT"},
+ {{NILOP, NILOP}, 1, "NEXT_N"}, // number <= smap.end - map
+ {{do_(next), NILOP}, 0, "COPY_NEXT"},
+ {{do_(put_glyph_8bit_obs), NILOP}, 1, "PUT_GLYPH_8BIT_OBS"}, // output_class
+ {{do_(put_subs_8bit_obs), NILOP}, 3, "PUT_SUBS_8BIT_OBS"}, // slot input_class output_class
+ {{do_(put_copy), NILOP}, 1, "PUT_COPY"}, // slot
+ {{do_(insert), NILOP}, 0, "INSERT"},
+ {{do_(delete_), NILOP}, 0, "DELETE"}, // 0x20
+ {{do_(assoc), NILOP}, VARARGS, "ASSOC"},
+ {{NILOP ,do_(cntxt_item)}, 2, "CNTXT_ITEM"}, // slot offset
+
+ {{do_(attr_set), NILOP}, 1, "ATTR_SET"}, // sattrnum
+ {{do_(attr_add), NILOP}, 1, "ATTR_ADD"}, // sattrnum
+ {{do_(attr_sub), NILOP}, 1, "ATTR_SUB"}, // sattrnum
+ {{do_(attr_set_slot), NILOP}, 1, "ATTR_SET_SLOT"}, // sattrnum
+ {{do_(iattr_set_slot), NILOP}, 2, "IATTR_SET_SLOT"}, // sattrnum attrid
+ {{do2(push_slot_attr)}, 2, "PUSH_SLOT_ATTR"}, // sattrnum slot
+ {{do2(push_glyph_attr_obs)}, 2, "PUSH_GLYPH_ATTR_OBS"}, // gattrnum slot
+ {{do2(push_glyph_metric)}, 3, "PUSH_GLYPH_METRIC"}, // gmetric slot level
+ {{do2(push_feat)}, 2, "PUSH_FEAT"}, // featidx slot
+
+ {{do2(push_att_to_gattr_obs)}, 2, "PUSH_ATT_TO_GATTR_OBS"}, // gattrnum slot
+ {{do2(push_att_to_glyph_metric)}, 3, "PUSH_ATT_TO_GLYPH_METRIC"}, // gmetric slot level
+ {{do2(push_islot_attr)}, 3, "PUSH_ISLOT_ATTR"}, // sattrnum slot attrid
+
+ {{NILOP,NILOP}, 3, "PUSH_IGLYPH_ATTR"},
+
+ {{do2(pop_ret)}, 0, "POP_RET"}, // 0x30
+ {{do2(ret_zero)}, 0, "RET_ZERO"},
+ {{do2(ret_true)}, 0, "RET_TRUE"},
+
+ {{do_(iattr_set), NILOP}, 2, "IATTR_SET"}, // sattrnum attrid
+ {{do_(iattr_add), NILOP}, 2, "IATTR_ADD"}, // sattrnum attrid
+ {{do_(iattr_sub), NILOP}, 2, "IATTR_SUB"}, // sattrnum attrid
+ {{do2(push_proc_state)}, 1, "PUSH_PROC_STATE"}, // dummy
+ {{do2(push_version)}, 0, "PUSH_VERSION"},
+ {{do_(put_subs), NILOP}, 5, "PUT_SUBS"}, // slot input_class input_class output_class output_class
+ {{NILOP,NILOP}, 0, "PUT_SUBS2"},
+ {{NILOP,NILOP}, 0, "PUT_SUBS3"},
+ {{do_(put_glyph), NILOP}, 2, "PUT_GLYPH"}, // output_class output_class
+ {{do2(push_glyph_attr)}, 3, "PUSH_GLYPH_ATTR"}, // gattrnum gattrnum slot
+ {{do2(push_att_to_glyph_attr)}, 3, "PUSH_ATT_TO_GLYPH_ATTR"}, // gattrnum gattrnum slot
+ {{do2(bor)}, 0, "BITOR"},
+ {{do2(band)}, 0, "BITAND"},
+ {{do2(bnot)}, 0, "BITNOT"}, // 0x40
+ {{do2(setbits)}, 4, "BITSET"},
+ {{do_(set_feat), NILOP}, 2, "SET_FEAT"}, // featidx slot
+ // private opcodes for internal use only, comes after all other on disk opcodes.
+ {{do_(temp_copy), NILOP}, 0, "TEMP_COPY"}
+};
diff --git a/gfx/graphite2/src/inc/opcodes.h b/gfx/graphite2/src/inc/opcodes.h
new file mode 100644
index 0000000000..ff2f1741e2
--- /dev/null
+++ b/gfx/graphite2/src/inc/opcodes.h
@@ -0,0 +1,691 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+// This file will be pulled into and integrated into a machine implmentation
+// DO NOT build directly and under no circumstances ever #include headers in
+// here or you will break the direct_machine.
+//
+// Implementers' notes
+// ==================
+// You have access to a few primitives and the full C++ code:
+// declare_params(n) Tells the interpreter how many bytes of parameter
+// space to claim for this instruction uses and
+// initialises the param pointer. You *must* before the
+// first use of param.
+// use_params(n) Claim n extra bytes of param space beyond what was
+// claimed using delcare_param.
+// param A const byte pointer for the parameter space claimed by
+// this instruction.
+// binop(op) Implement a binary operation on the stack using the
+// specified C++ operator.
+// NOT_IMPLEMENTED Any instruction body containing this will exit the
+// program with an assertion error. Instructions that are
+// not implemented should also be marked NILOP in the
+// opcodes tables this will cause the code class to spot
+// them in a live code stream and throw a runtime_error
+// instead.
+// push(n) Push the value n onto the stack.
+// pop() Pop the top most value and return it.
+//
+// You have access to the following named fast 'registers':
+// sp = The pointer to the current top of stack, the last value
+// pushed.
+// seg = A reference to the Segment this code is running over.
+// is = The current slot index
+// isb = The original base slot index at the start of this rule
+// isf = The first positioned slot
+// isl = The last positioned slot
+// ip = The current instruction pointer
+// endPos = Position of advance of last cluster
+// dir = writing system directionality of the font
+
+
+// #define NOT_IMPLEMENTED assert(false)
+// #define NOT_IMPLEMENTED
+
+#define binop(op) const uint32 a = pop(); *sp = uint32(*sp) op a
+#define sbinop(op) const int32 a = pop(); *sp = int32(*sp) op a
+#define use_params(n) dp += n
+
+#define declare_params(n) const byte * param = dp; \
+ use_params(n);
+
+#define push(n) { *++sp = n; }
+#define pop() (*sp--)
+#define slotat(x) (map[(x)])
+#define DIE { is=seg.last(); status = Machine::died_early; EXIT(1); }
+#define POSITIONED 1
+
+STARTOP(nop)
+ do {} while (0);
+ENDOP
+
+STARTOP(push_byte)
+ declare_params(1);
+ push(int8(*param));
+ENDOP
+
+STARTOP(push_byte_u)
+ declare_params(1);
+ push(uint8(*param));
+ENDOP
+
+STARTOP(push_short)
+ declare_params(2);
+ const int16 r = int16(param[0]) << 8
+ | uint8(param[1]);
+ push(r);
+ENDOP
+
+STARTOP(push_short_u)
+ declare_params(2);
+ const uint16 r = uint16(param[0]) << 8
+ | uint8(param[1]);
+ push(r);
+ENDOP
+
+STARTOP(push_long)
+ declare_params(4);
+ const int32 r = int32(param[0]) << 24
+ | uint32(param[1]) << 16
+ | uint32(param[2]) << 8
+ | uint8(param[3]);
+ push(r);
+ENDOP
+
+STARTOP(add)
+ binop(+);
+ENDOP
+
+STARTOP(sub)
+ binop(-);
+ENDOP
+
+STARTOP(mul)
+ binop(*);
+ENDOP
+
+STARTOP(div_)
+ const int32 b = pop();
+ const int32 a = int32(*sp);
+ if (b == 0 || (a == std::numeric_limits<int32>::min() && b == -1)) DIE;
+ *sp = int32(*sp) / b;
+ENDOP
+
+STARTOP(min_)
+ const int32 a = pop(), b = *sp;
+ if (a < b) *sp = a;
+ENDOP
+
+STARTOP(max_)
+ const int32 a = pop(), b = *sp;
+ if (a > b) *sp = a;
+ENDOP
+
+STARTOP(neg)
+ *sp = uint32(-int32(*sp));
+ENDOP
+
+STARTOP(trunc8)
+ *sp = uint8(*sp);
+ENDOP
+
+STARTOP(trunc16)
+ *sp = uint16(*sp);
+ENDOP
+
+STARTOP(cond)
+ const uint32 f = pop(), t = pop(), c = pop();
+ push(c ? t : f);
+ENDOP
+
+STARTOP(and_)
+ binop(&&);
+ENDOP
+
+STARTOP(or_)
+ binop(||);
+ENDOP
+
+STARTOP(not_)
+ *sp = !*sp;
+ENDOP
+
+STARTOP(equal)
+ binop(==);
+ENDOP
+
+STARTOP(not_eq_)
+ binop(!=);
+ENDOP
+
+STARTOP(less)
+ sbinop(<);
+ENDOP
+
+STARTOP(gtr)
+ sbinop(>);
+ENDOP
+
+STARTOP(less_eq)
+ sbinop(<=);
+ENDOP
+
+STARTOP(gtr_eq)
+ sbinop(>=);
+ENDOP
+
+STARTOP(next)
+ if (map - &smap[0] >= int(smap.size())) DIE
+ if (is)
+ {
+ if (is == smap.highwater())
+ smap.highpassed(true);
+ is = is->next();
+ }
+ ++map;
+ENDOP
+
+//STARTOP(next_n)
+// use_params(1);
+// NOT_IMPLEMENTED;
+ //declare_params(1);
+ //const size_t num = uint8(*param);
+//ENDOP
+
+//STARTOP(copy_next)
+// if (is) is = is->next();
+// ++map;
+// ENDOP
+
+STARTOP(put_glyph_8bit_obs)
+ declare_params(1);
+ const unsigned int output_class = uint8(*param);
+ is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
+ENDOP
+
+STARTOP(put_subs_8bit_obs)
+ declare_params(3);
+ const int slot_ref = int8(param[0]);
+ const unsigned int input_class = uint8(param[1]),
+ output_class = uint8(param[2]);
+ uint16 index;
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ index = seg.findClassIndex(input_class, slot->gid());
+ is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
+ }
+ENDOP
+
+STARTOP(put_copy)
+ declare_params(1);
+ const int slot_ref = int8(*param);
+ if (is && !is->isDeleted())
+ {
+ slotref ref = slotat(slot_ref);
+ if (ref && ref != is)
+ {
+ int16 *tempUserAttrs = is->userAttrs();
+ if (is->attachedTo() || is->firstChild()) DIE
+ Slot *prev = is->prev();
+ Slot *next = is->next();
+ memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16));
+ memcpy(is, ref, sizeof(Slot));
+ is->firstChild(NULL);
+ is->nextSibling(NULL);
+ is->userAttrs(tempUserAttrs);
+ is->next(next);
+ is->prev(prev);
+ if (is->attachedTo())
+ is->attachedTo()->child(is);
+ }
+ is->markCopied(false);
+ is->markDeleted(false);
+ }
+ENDOP
+
+STARTOP(insert)
+ if (smap.decMax() <= 0) DIE;
+ Slot *newSlot = seg.newSlot();
+ if (!newSlot) DIE;
+ Slot *iss = is;
+ while (iss && iss->isDeleted()) iss = iss->next();
+ if (!iss)
+ {
+ if (seg.last())
+ {
+ seg.last()->next(newSlot);
+ newSlot->prev(seg.last());
+ newSlot->before(seg.last()->before());
+ seg.last(newSlot);
+ }
+ else
+ {
+ seg.first(newSlot);
+ seg.last(newSlot);
+ }
+ }
+ else if (iss->prev())
+ {
+ iss->prev()->next(newSlot);
+ newSlot->prev(iss->prev());
+ newSlot->before(iss->prev()->after());
+ }
+ else
+ {
+ newSlot->prev(NULL);
+ newSlot->before(iss->before());
+ seg.first(newSlot);
+ }
+ newSlot->next(iss);
+ if (iss)
+ {
+ iss->prev(newSlot);
+ newSlot->originate(iss->original());
+ newSlot->after(iss->before());
+ }
+ else if (newSlot->prev())
+ {
+ newSlot->originate(newSlot->prev()->original());
+ newSlot->after(newSlot->prev()->after());
+ }
+ else
+ {
+ newSlot->originate(seg.defaultOriginal());
+ }
+ if (is == smap.highwater())
+ smap.highpassed(false);
+ is = newSlot;
+ seg.extendLength(1);
+ if (map != &smap[-1])
+ --map;
+ENDOP
+
+STARTOP(delete_)
+ if (!is || is->isDeleted()) DIE
+ is->markDeleted(true);
+ if (is->prev())
+ is->prev()->next(is->next());
+ else
+ seg.first(is->next());
+
+ if (is->next())
+ is->next()->prev(is->prev());
+ else
+ seg.last(is->prev());
+
+
+ if (is == smap.highwater())
+ smap.highwater(is->next());
+ if (is->prev())
+ is = is->prev();
+ seg.extendLength(-1);
+ENDOP
+
+STARTOP(assoc)
+ declare_params(1);
+ unsigned int num = uint8(*param);
+ const int8 * assocs = reinterpret_cast<const int8 *>(param+1);
+ use_params(num);
+ int max = -1;
+ int min = -1;
+
+ while (num-- > 0)
+ {
+ int sr = *assocs++;
+ slotref ts = slotat(sr);
+ if (ts && (min == -1 || ts->before() < min)) min = ts->before();
+ if (ts && ts->after() > max) max = ts->after();
+ }
+ if (min > -1) // implies max > -1
+ {
+ is->before(min);
+ is->after(max);
+ }
+ENDOP
+
+STARTOP(cntxt_item)
+ // It turns out this is a cunningly disguised condition forward jump.
+ declare_params(3);
+ const int is_arg = int8(param[0]);
+ const size_t iskip = uint8(param[1]),
+ dskip = uint8(param[2]);
+
+ if (mapb + is_arg != map)
+ {
+ ip += iskip;
+ dp += dskip;
+ push(true);
+ }
+ENDOP
+
+STARTOP(attr_set)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const int val = pop();
+ is->setAttr(&seg, slat, 0, val, smap);
+ENDOP
+
+STARTOP(attr_add)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const uint32_t val = pop();
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
+ is->setAttr(&seg, slat, 0, int32_t(val + res), smap);
+ENDOP
+
+STARTOP(attr_sub)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const uint32_t val = pop();
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
+ is->setAttr(&seg, slat, 0, int32_t(res - val), smap);
+ENDOP
+
+STARTOP(attr_set_slot)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const int offset = int(map - smap.begin())*int(slat == gr_slatAttTo);
+ const int val = pop() + offset;
+ is->setAttr(&seg, slat, offset, val, smap);
+ENDOP
+
+STARTOP(iattr_set_slot)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const uint8 idx = uint8(param[1]);
+ const int val = int(pop() + (map - smap.begin())*int(slat == gr_slatAttTo));
+ is->setAttr(&seg, slat, idx, val, smap);
+ENDOP
+
+STARTOP(push_slot_attr)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const int slot_ref = int8(param[1]);
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ int res = slot->getAttr(&seg, slat, 0);
+ push(res);
+ }
+ENDOP
+
+STARTOP(push_glyph_attr_obs)
+ declare_params(2);
+ const unsigned int glyph_attr = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
+ENDOP
+
+STARTOP(push_glyph_metric)
+ declare_params(3);
+ const unsigned int glyph_attr = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ const signed int attr_level = uint8(param[2]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ push(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir));
+ENDOP
+
+STARTOP(push_feat)
+ declare_params(2);
+ const unsigned int feat = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ uint8 fid = seg.charinfo(slot->original())->fid();
+ push(seg.getFeature(fid, feat));
+ }
+ENDOP
+
+STARTOP(push_att_to_gattr_obs)
+ declare_params(2);
+ const unsigned int glyph_attr = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ slotref att = slot->attachedTo();
+ if (att) slot = att;
+ push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
+ }
+ENDOP
+
+STARTOP(push_att_to_glyph_metric)
+ declare_params(3);
+ const unsigned int glyph_attr = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ const signed int attr_level = uint8(param[2]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ slotref att = slot->attachedTo();
+ if (att) slot = att;
+ push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir)));
+ }
+ENDOP
+
+STARTOP(push_islot_attr)
+ declare_params(3);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const int slot_ref = int8(param[1]),
+ idx = uint8(param[2]);
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ int res = slot->getAttr(&seg, slat, idx);
+ push(res);
+ }
+ENDOP
+
+#if 0
+STARTOP(push_iglyph_attr) // not implemented
+ NOT_IMPLEMENTED;
+ENDOP
+#endif
+
+STARTOP(pop_ret)
+ const uint32 ret = pop();
+ EXIT(ret);
+ENDOP
+
+STARTOP(ret_zero)
+ EXIT(0);
+ENDOP
+
+STARTOP(ret_true)
+ EXIT(1);
+ENDOP
+
+STARTOP(iattr_set)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const uint8 idx = uint8(param[1]);
+ const int val = pop();
+ is->setAttr(&seg, slat, idx, val, smap);
+ENDOP
+
+STARTOP(iattr_add)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const uint8 idx = uint8(param[1]);
+ const uint32_t val = pop();
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
+ is->setAttr(&seg, slat, idx, int32_t(val + res), smap);
+ENDOP
+
+STARTOP(iattr_sub)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const uint8 idx = uint8(param[1]);
+ const uint32_t val = pop();
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
+ is->setAttr(&seg, slat, idx, int32_t(res - val), smap);
+ENDOP
+
+STARTOP(push_proc_state)
+ use_params(1);
+ push(1);
+ENDOP
+
+STARTOP(push_version)
+ push(0x00030000);
+ENDOP
+
+STARTOP(put_subs)
+ declare_params(5);
+ const int slot_ref = int8(param[0]);
+ const unsigned int input_class = uint8(param[1]) << 8
+ | uint8(param[2]);
+ const unsigned int output_class = uint8(param[3]) << 8
+ | uint8(param[4]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ int index = seg.findClassIndex(input_class, slot->gid());
+ is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
+ }
+ENDOP
+
+#if 0
+STARTOP(put_subs2) // not implemented
+ NOT_IMPLEMENTED;
+ENDOP
+
+STARTOP(put_subs3) // not implemented
+ NOT_IMPLEMENTED;
+ENDOP
+#endif
+
+STARTOP(put_glyph)
+ declare_params(2);
+ const unsigned int output_class = uint8(param[0]) << 8
+ | uint8(param[1]);
+ is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
+ENDOP
+
+STARTOP(push_glyph_attr)
+ declare_params(3);
+ const unsigned int glyph_attr = uint8(param[0]) << 8
+ | uint8(param[1]);
+ const int slot_ref = int8(param[2]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
+ENDOP
+
+STARTOP(push_att_to_glyph_attr)
+ declare_params(3);
+ const unsigned int glyph_attr = uint8(param[0]) << 8
+ | uint8(param[1]);
+ const int slot_ref = int8(param[2]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ slotref att = slot->attachedTo();
+ if (att) slot = att;
+ push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
+ }
+ENDOP
+
+STARTOP(temp_copy)
+ slotref newSlot = seg.newSlot();
+ if (!newSlot || !is) DIE;
+ int16 *tempUserAttrs = newSlot->userAttrs();
+ memcpy(newSlot, is, sizeof(Slot));
+ memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16));
+ newSlot->userAttrs(tempUserAttrs);
+ newSlot->markCopied(true);
+ *map = newSlot;
+ENDOP
+
+STARTOP(band)
+ binop(&);
+ENDOP
+
+STARTOP(bor)
+ binop(|);
+ENDOP
+
+STARTOP(bnot)
+ *sp = ~*sp;
+ENDOP
+
+STARTOP(setbits)
+ declare_params(4);
+ const uint16 m = uint16(param[0]) << 8
+ | uint8(param[1]);
+ const uint16 v = uint16(param[2]) << 8
+ | uint8(param[3]);
+ *sp = ((*sp) & ~m) | v;
+ENDOP
+
+STARTOP(set_feat)
+ declare_params(2);
+ const unsigned int feat = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ uint8 fid = seg.charinfo(slot->original())->fid();
+ seg.setFeature(fid, feat, pop());
+ }
+ENDOP