diff options
Diffstat (limited to 'gfx/graphite2/src/inc')
43 files changed, 7464 insertions, 0 deletions
diff --git a/gfx/graphite2/src/inc/Bidi.h b/gfx/graphite2/src/inc/Bidi.h new file mode 100644 index 0000000000..9593c7e149 --- /dev/null +++ b/gfx/graphite2/src/inc/Bidi.h @@ -0,0 +1,126 @@ +/* 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 + +namespace graphite2 +{ + +class BracketPair +{ +public: + BracketPair(uint16 g, Slot *s, uint8 b, BracketPair *p, BracketPair *l) : _open(s), _close(0), _parent(p), _next(0), _prev(l), _gid(g), _mask(0), _before(b) {}; + uint16 gid() const { return _gid; } + Slot *open() const { return _open; } + Slot *close() const { return _close; } + uint8 mask() const { return _mask; } + int8 before() const { return _before; } + BracketPair *parent() const { return _parent; } + void close(Slot *s) { _close = s; } + BracketPair *next() const { return _next; } + BracketPair *prev() const { return _prev; } + void next(BracketPair *n) { _next = n; } + void orin(uint8 m) { _mask |= m; } +private: + Slot * _open; // Slot of opening paren + Slot * _close; // Slot of closing paren + BracketPair * _parent; // pair this pair is in or NULL + BracketPair * _next; // next pair along the string + BracketPair * _prev; // pair that closed last before we opened + uint16 _gid; // gid of closing paren + uint8 _mask; // bitmap (2 bits) of directions within the pair + int8 _before; // most recent strong type (L, R, OPP, CPP) +}; + +class BracketPairStack +{ +public: + BracketPairStack(int s) : _stack(grzeroalloc<BracketPair>(s)), _ip(_stack - 1), _top(0), _last(0), _lastclose(0), _size(s) {} + ~BracketPairStack() { free(_stack); } + +public: + BracketPair *scan(uint16 gid); + void close(BracketPair *tos, Slot *s); + BracketPair *push(uint16 gid, Slot *pos, uint8 before, int prevopen); + void orin(uint8 mask); + void clear() { _ip = _stack - 1; _top = 0; _last = 0; _lastclose = 0; } + int size() const { return _size; } + BracketPair *start() const { return _stack; } + + CLASS_NEW_DELETE + +private: + + BracketPair *_stack; // start of storage + BracketPair *_ip; // where to add the next pair + BracketPair *_top; // current parent + BracketPair *_last; // end of next() chain + BracketPair *_lastclose; // last pair to close + int _size; // capacity +}; + +inline BracketPair *BracketPairStack::scan(uint16 gid) +{ + BracketPair *res = _top; + while (res >= _stack) + { + if (res->gid() == gid) + return res; + res = res->parent(); + } + return 0; +} + +inline void BracketPairStack::close(BracketPair *tos, Slot *s) +{ + for ( ; _last && _last != tos && !_last->close(); _last = _last->parent()) + { } + tos->close(s); + _last->next(NULL); + _lastclose = tos; + _top = tos->parent(); +} + +inline BracketPair *BracketPairStack::push(uint16 gid, Slot *pos, uint8 before, int prevopen) +{ + if (++_ip - _stack < _size && _stack) + { + ::new (_ip) BracketPair(gid, pos, before, _top, prevopen ? _last : _lastclose); + if (_last) _last->next(_ip); + _last = _ip; + } + _top = _ip; + return _ip; +} + +inline void BracketPairStack::orin(uint8 mask) +{ + BracketPair *t = _top; + for ( ; t; t = t->parent()) + t->orin(mask); +} + +} diff --git a/gfx/graphite2/src/inc/CachedFace.h b/gfx/graphite2/src/inc/CachedFace.h new file mode 100644 index 0000000000..53674754ee --- /dev/null +++ b/gfx/graphite2/src/inc/CachedFace.h @@ -0,0 +1,56 @@ +/* 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 + +#ifndef GRAPHITE2_NSEGCACHE + +#include "inc/Face.h" + +namespace graphite2 { + +class SegCacheStore; +class SegCache; + +class CachedFace : public Face +{ + CachedFace(const CachedFace &); + CachedFace & operator = (const CachedFace &); + +public: + CachedFace(const void* appFaceHandle/*non-NULL*/, const gr_face_ops & ops); + bool setupCache(unsigned int cacheSize); + virtual ~CachedFace(); + virtual bool runGraphite(Segment *seg, const Silf *silf) const; + SegCacheStore * cacheStore() { return m_cacheStore; } +private: + SegCacheStore * m_cacheStore; +}; + +} // namespace graphite2 + +#endif + diff --git a/gfx/graphite2/src/inc/CharInfo.h b/gfx/graphite2/src/inc/CharInfo.h new file mode 100644 index 0000000000..d9e56eeed6 --- /dev/null +++ b/gfx/graphite2/src/inc/CharInfo.h @@ -0,0 +1,67 @@ +/* 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..3985ae416e --- /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 / 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..5d953b4a4c --- /dev/null +++ b/gfx/graphite2/src/inc/Collider.h @@ -0,0 +1,244 @@ +/* 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 + +#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) +{ +#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..61351c416e --- /dev/null +++ b/gfx/graphite2/src/inc/Compression.h @@ -0,0 +1,103 @@ +/* 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; + +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..3d81864d10 --- /dev/null +++ b/gfx/graphite2/src/inc/Decompressor.h @@ -0,0 +1,56 @@ +/* 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..fc84ec2789 --- /dev/null +++ b/gfx/graphite2/src/inc/Endian.h @@ -0,0 +1,112 @@ +/* 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..07d70b78e7 --- /dev/null +++ b/gfx/graphite2/src/inc/Error.h @@ -0,0 +1,135 @@ +/* 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..43ea431968 --- /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; + uint32 _sz; + bool _compressed; + + Error decompress(); + + void releaseBuffers(); + +public: + Table() throw(); + Table(const Face & face, const Tag n, uint32 version=0xffffffff) throw(); + Table(const Table & rhs) throw(); + ~Table() throw(); + + operator const byte * () const throw(); + + Table & operator = (const Table & rhs) throw(); + size_t size() const 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() +{ + releaseBuffers(); +} + +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..fc845f6e16 --- /dev/null +++ b/gfx/graphite2/src/inc/FeatureMap.h @@ -0,0 +1,193 @@ +/* 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: + FeatureRef(); + FeatureRef(const Face & face, unsigned short & bits_offset, uint32 max_val, + uint32 name, uint16 uiName, uint16 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(); } + uint32 maxVal() const { return m_max; } + const Face* getFace() const { return m_pFace;} + const FeatureMap* getFeatureMap() const;// { return m_pFace;} + + CLASS_NEW_DELETE; +private: + FeatureRef(const FeatureRef & rhs); + + const Face * m_pFace; //not NULL + 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_flags, // feature flags (unused at the moment but read from the font) + m_numSet; // number of values (number of entries in m_nameValues) + 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() +: m_pFace(0), m_nameValues(0), + m_mask(0), m_max(0), m_id(0), + m_nameid(0), m_flags(0), m_numSet(0), + m_bits(0), m_index(0) +{ +} + + +class NameAndFeatureRef +{ + public: + NameAndFeatureRef(uint32 name = 0) : m_name(name) , m_pFRef(NULL){} + NameAndFeatureRef(const FeatureRef* p/*not NULL*/) : 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..5fbcf08206 --- /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..81e501bab2 --- /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..bc7084050e --- /dev/null +++ b/gfx/graphite2/src/inc/Font.h @@ -0,0 +1,89 @@ +/* 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; + + 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..3c0add58d0 --- /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..41685a55f4 --- /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/GlyphFaceCache.h b/gfx/graphite2/src/inc/GlyphFaceCache.h new file mode 100644 index 0000000000..4afdfbe017 --- /dev/null +++ b/gfx/graphite2/src/inc/GlyphFaceCache.h @@ -0,0 +1,103 @@ +/* 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/GlyphFace.h" +#include "graphite2/Font.h" + +namespace graphite2 { + +class Segment; +class Face; +class FeatureVal; + + +class GlyphFaceCacheHeader +{ +public: + bool initialize(const Face & face, const bool dumb_font); //return result indicates success. Do not use if failed. + unsigned short numGlyphs() const { return m_nGlyphs; } + unsigned short numAttrs() const { return m_numAttrs; } + +private: +friend class Face; +friend class GlyphFace; + const byte* m_pHead, + * m_pHHea, + * m_pHmtx, + * m_pGlat, + * m_pGloc, + * m_pGlyf, + * m_pLoca; + size_t m_lHmtx, + m_lGlat, + m_lGlyf, + m_lLoca; + + uint32 m_fGlat; + unsigned short m_numAttrs, // number of glyph attributes per glyph + m_nGlyphsWithGraphics, //i.e. boundary box and advance + m_nGlyphsWithAttributes, + m_nGlyphs; // number of glyphs in the font. Max of the above 2. + bool m_locFlagsUse32Bit; +}; + +class GlyphFaceCache : public GlyphFaceCacheHeader +{ +public: + static GlyphFaceCache* makeCache(const GlyphFaceCacheHeader& hdr /*, EGlyphCacheStrategy requested */); + + GlyphFaceCache(const GlyphFaceCacheHeader& hdr); + ~GlyphFaceCache(); + + const GlyphFace *glyphSafe(unsigned short glyphid) const { return glyphid<numGlyphs()?glyph(glyphid):NULL; } + uint16 glyphAttr(uint16 gid, uint8 gattr) const { if (gattr>=numAttrs()) return 0; const GlyphFace*p=glyphSafe(gid); return p?p->getAttr(gattr):0; } + + void * operator new (size_t s, const GlyphFaceCacheHeader& hdr) + { + return malloc(s + sizeof(GlyphFace*)*hdr.numGlyphs()); + } + // delete in case an exception is thrown in constructor + void operator delete(void* p, const GlyphFaceCacheHeader& ) throw() + { + free(p); + } + + const GlyphFace *glyph(unsigned short glyphid) const; //result may be changed by subsequent call with a different glyphid + void loadAllGlyphs(); + + CLASS_NEW_DELETE + +private: + GlyphFace **glyphPtrDirect(unsigned short glyphid) const { return (GlyphFace **)((const char*)(this)+sizeof(GlyphFaceCache)+sizeof(GlyphFace*)*glyphid);} + +private: //defensive + GlyphFaceCache(const GlyphFaceCache&); + GlyphFaceCache& operator=(const GlyphFaceCache&); +}; + +} // namespace graphite2 diff --git a/gfx/graphite2/src/inc/Intervals.h b/gfx/graphite2/src/inc/Intervals.h new file mode 100644 index 0000000000..34fecce179 --- /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..020560235c --- /dev/null +++ b/gfx/graphite2/src/inc/List.h @@ -0,0 +1,165 @@ +/* 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> + + +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(); + m_first = static_cast<T*>(realloc(m_first, n*sizeof(T))); + 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..1a01b7a43f --- /dev/null +++ b/gfx/graphite2/src/inc/Machine.h @@ -0,0 +1,200 @@ +/* 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 <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 + +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) +{ + 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..deeffcccd5 --- /dev/null +++ b/gfx/graphite2/src/inc/Main.h @@ -0,0 +1,146 @@ +/* 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 + +// typesafe wrapper around malloc for simple types +// use free(pointer) to deallocate + +template <typename T> T * gralloc(size_t n) +{ +#ifdef GRAPHITE2_TELEMETRY + telemetry::count_bytes(sizeof(T) * n); +#endif + return static_cast<T*>(malloc(sizeof(T) * n)); +} + +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 + +#if defined(__clang__) && __cplusplus >= 201103L + /* clang's fallthrough annotations are only available starting in C++11. */ + #define GR_FALLTHROUGH [[clang::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 +#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..074d501d95 --- /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..97bc1cdf7a --- /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..5ac21a1759 --- /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, int 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, int maxSize) +: segment(seg), m_size(0), m_precontext(0), m_highwater(0), + m_maxSize(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/SegCache.h b/gfx/graphite2/src/inc/SegCache.h new file mode 100644 index 0000000000..b360f7c933 --- /dev/null +++ b/gfx/graphite2/src/inc/SegCache.h @@ -0,0 +1,316 @@ +/* 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 + +#ifndef GRAPHITE2_NSEGCACHE + +#include <graphite2/Segment.h> +#include "inc/Main.h" +#include "inc/Slot.h" +#include "inc/FeatureVal.h" +#include "inc/SegCacheEntry.h" +#include "inc/Segment.h" + +namespace graphite2 { + +class SegCache; +class SegCacheEntry; +class SegCacheStore; + +/** + * SegPrefixEntry stores lists of word/syllable segments + * with one list for each word length. The prefix size should be chosen so that + * these list sizes stay small since they will be searched iteratively. + */ +class SegCachePrefixEntry +{ + SegCachePrefixEntry(const SegCachePrefixEntry &); + SegCachePrefixEntry & operator = (const SegCachePrefixEntry &); + +public: + SegCachePrefixEntry() : m_lastPurge(0) + { + memset(m_entryCounts, 0, sizeof m_entryCounts); + memset(m_entryBSIndex, 0, sizeof m_entryBSIndex); + memset(m_entries, 0, sizeof m_entries); + } + + ~SegCachePrefixEntry() + { + for (size_t j = 0; j < eMaxSpliceSize; j++) + { + if (m_entryCounts[j]) + { + assert(m_entries[j]); + for (size_t k = 0; k < m_entryCounts[j]; k++) + m_entries[j][k].clear(); + + free(m_entries[j]); + } + } + } + const SegCacheEntry * find(const uint16 * cmapGlyphs, size_t length) const + { + if (length <= ePrefixLength) + { + assert(m_entryCounts[length-1] <= 1); + if (m_entries[length-1]) + return m_entries[length-1]; + return NULL; + } + SegCacheEntry * entry = NULL; + findPosition(cmapGlyphs, length, &entry); + return entry; + } + SegCacheEntry * cache(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, unsigned long long totalAccessCount) + { + size_t listSize = m_entryBSIndex[length-1]? (m_entryBSIndex[length-1] << 1) - 1 : 0; + SegCacheEntry * newEntries = NULL; + if (m_entryCounts[length-1] + 1u > listSize) + { + if (m_entryCounts[length-1] == 0) + listSize = 1; + else + { + // the problem comes when you get incremental numeric ids in a large doc + if (listSize >= eMaxSuffixCount) + return NULL; + listSize = (m_entryBSIndex[length-1] << 2) - 1; + } + newEntries = gralloc<SegCacheEntry>(listSize); + if (!newEntries) + return NULL; + } + + uint16 insertPos = 0; + if (m_entryCounts[length-1] > 0) + { + insertPos = findPosition(cmapGlyphs, length, NULL); + if (!newEntries) + { + // same buffer, shift entries up + memmove(m_entries[length-1] + insertPos + 1, m_entries[length-1] + insertPos, + sizeof(SegCacheEntry) * (m_entryCounts[length-1] - insertPos)); + } + else + { + memcpy(newEntries, m_entries[length-1], sizeof(SegCacheEntry) * (insertPos)); + memcpy(newEntries + insertPos + 1, m_entries[length-1] + insertPos, + sizeof(SegCacheEntry) * (m_entryCounts[length-1] - insertPos)); + + free(m_entries[length-1]); + m_entries[length-1] = newEntries; + assert (m_entryBSIndex[length-1]); + m_entryBSIndex[length-1] <<= 1; + } + } + else + { + m_entryBSIndex[length-1] = 1; + m_entries[length-1] = newEntries; + } + m_entryCounts[length-1] += 1; + new (m_entries[length-1] + insertPos) + SegCacheEntry(cmapGlyphs, length, seg, charOffset, totalAccessCount); + return m_entries[length-1] + insertPos; + } + uint32 purge(unsigned long long minAccessCount, unsigned long long oldAccessTime, + unsigned long long currentTime); + CLASS_NEW_DELETE +private: + uint16 findPosition(const uint16 * cmapGlyphs, uint16 length, SegCacheEntry ** entry) const + { + int dir = 0; + if (m_entryCounts[length-1] == 0) + { + if (entry) *entry = NULL; + return 0; + } + else if (m_entryCounts[length-1] == 1) + { + // optimize single entry case + for (int i = ePrefixLength; i < length; i++) + { + if (cmapGlyphs[i] > m_entries[length-1][0].m_unicode[i]) + { + return 1; + } + else if (cmapGlyphs[i] < m_entries[length-1][0].m_unicode[i]) + { + return 0; + } + } + if (entry) + *entry = m_entries[length-1]; + return 0; + } + uint16 searchIndex = m_entryBSIndex[length-1] - 1; + uint16 stepSize = m_entryBSIndex[length-1] >> 1; + size_t prevIndex = searchIndex; + do + { + dir = 0; + if (searchIndex >= m_entryCounts[length-1]) + { + dir = -1; + searchIndex -= stepSize; + stepSize >>= 1; + } + else + { + for (int i = ePrefixLength; i < length; i++) + { + if (cmapGlyphs[i] > m_entries[length-1][searchIndex].m_unicode[i]) + { + dir = 1; + searchIndex += stepSize; + stepSize >>= 1; + break; + } + else if (cmapGlyphs[i] < m_entries[length-1][searchIndex].m_unicode[i]) + { + dir = -1; + searchIndex -= stepSize; + stepSize >>= 1; + break; + } + } + } + if (prevIndex == searchIndex) + break; + prevIndex = searchIndex; + } while (dir != 0); + if (entry) + { + if (dir == 0) + *entry = m_entries[length-1] + searchIndex; + else + *entry = NULL; + } + else + { + // if entry is null, then this is for inserting a new value, which + // shouldn't already be in the cache + assert(dir != 0); + if (dir > 0) + ++searchIndex; + } + return searchIndex; + } + /** m_entries is a null terminated list of entries */ + uint16 m_entryCounts[eMaxSpliceSize]; + uint16 m_entryBSIndex[eMaxSpliceSize]; + SegCacheEntry * m_entries[eMaxSpliceSize]; + unsigned long long m_lastPurge; +}; + + +#define SEG_CACHE_MIN_INDEX (store->maxCmapGid()) +#define SEG_CACHE_MAX_INDEX (store->maxCmapGid()+1u) +#define SEG_CACHE_UNSET_INDEX (store->maxCmapGid()+2u) + +union SegCachePrefixArray +{ + void ** raw; + SegCachePrefixArray * array; + SegCachePrefixEntry ** prefixEntries; + uintptr * range; +}; + +class SegCache +{ +public: + SegCache(const SegCacheStore * store, const Features& features); + ~SegCache(); + + const SegCacheEntry * find(const uint16 * cmapGlyphs, size_t length) const; + SegCacheEntry * cache(SegCacheStore * store, const uint16 * cmapGlyphs, size_t length, Segment * seg, size_t charOffset); + void purge(SegCacheStore * store); + + long long totalAccessCount() const { return m_totalAccessCount; } + size_t segmentCount() const { return m_segmentCount; } + const Features & features() const { return m_features; } + void clear(SegCacheStore * store); + + CLASS_NEW_DELETE +private: + void freeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level); + void purgeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level, + unsigned long long minAccessCount, unsigned long long oldAccessTime); + + uint16 m_prefixLength; +// uint16 m_maxCachedSegLength; + size_t m_segmentCount; + SegCachePrefixArray m_prefixes; + Features m_features; + mutable unsigned long long m_totalAccessCount; + mutable unsigned long long m_totalMisses; + float m_purgeFactor; +}; + +inline const SegCacheEntry * SegCache::find(const uint16 * cmapGlyphs, size_t length) const +{ + uint16 pos = 0; + if (!length || length > eMaxSpliceSize) return NULL; + SegCachePrefixArray pEntry = m_prefixes.array[cmapGlyphs[0]]; + while (++pos < m_prefixLength - 1) + { + if (!pEntry.raw) + { + ++m_totalMisses; + return NULL; + } + pEntry = pEntry.array[(pos < length)? cmapGlyphs[pos] : 0]; + } + if (!pEntry.raw) + { + ++m_totalMisses; + return NULL; + } + SegCachePrefixEntry * prefixEntry = pEntry.prefixEntries[(pos < length)? cmapGlyphs[pos] : 0]; + if (!prefixEntry) + { + ++m_totalMisses; + return NULL; + } + const SegCacheEntry * entry = prefixEntry->find(cmapGlyphs, length); + if (entry) + { + ++m_totalAccessCount; + entry->accessed(m_totalAccessCount); + } + else + { + ++m_totalMisses; + } + return entry; +} + +} // namespace graphite2 + +#endif + diff --git a/gfx/graphite2/src/inc/SegCacheEntry.h b/gfx/graphite2/src/inc/SegCacheEntry.h new file mode 100644 index 0000000000..9a7d930677 --- /dev/null +++ b/gfx/graphite2/src/inc/SegCacheEntry.h @@ -0,0 +1,121 @@ +/* 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 + +#ifndef GRAPHITE2_NSEGCACHE + +#include "inc/Main.h" +#include "inc/Slot.h" + +namespace graphite2 { + +class Segment; +class Slot; +class SegCacheEntry; +class SegCachePrefixEntry; + +enum SegCacheParameters { + /** number of characters used in initial prefix tree */ + ePrefixLength = 2, + /** Segments more recent than maxSegmentCount() / eAgeFactor are kept */ + eAgeFactor = 4, + /** Segments are purged according to the formular: + * accessCount < (totalAccesses)/(ePurgeFactor * maxSegments) */ + ePurgeFactor = 5, + /** Maximum number of Segments to store which have the same + * prefix. Needed to prevent unique identifiers flooding the cache */ + eMaxSuffixCount = 15 + +}; + +class SegCacheCharInfo +{ +public: + uint16 m_unicode; + uint16 m_before; + uint16 m_after; +}; + +/** + * SegCacheEntry stores the result of running the engine for specific unicode + * code points in the typical mid-line situation. + */ +class SegCacheEntry +{ + // Prevent any implict copying; + SegCacheEntry(const SegCacheEntry &); + SegCacheEntry & operator = (const SegCacheEntry &); + + friend class SegCachePrefixEntry; +public: + SegCacheEntry() : + m_glyphLength(0), m_unicode(NULL), m_glyph(NULL), m_attr(NULL), m_justs(0), + m_accessCount(0), m_lastAccess(0) + {} + SegCacheEntry(const uint16 * cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime); + ~SegCacheEntry() { clear(); }; + void clear(); + size_t glyphLength() const { return m_glyphLength; } + const Slot * first() const { return m_glyph; } + const Slot * last() const { return m_glyph + (m_glyphLength - 1); } + + /** Total number of times this entry has been accessed since creation */ + unsigned long long accessCount() const { return m_accessCount; } + /** "time" of last access where "time" is measured in accesses to the cache owning this entry */ + void accessed(unsigned long long cacheTime) const + { + m_lastAccess = cacheTime; ++m_accessCount; + }; + + int compareRank(const SegCacheEntry & entry) const + { + if (m_accessCount > entry.m_accessCount) return 1; + else if (m_accessCount < entry.m_accessCount) return 1; + else if (m_lastAccess > entry.m_lastAccess) return 1; + else if (m_lastAccess < entry.m_lastAccess) return -1; + return 0; + } + unsigned long long lastAccess() const { return m_lastAccess; }; + + CLASS_NEW_DELETE; +private: + + size_t m_glyphLength; + /** glyph ids resulting from cmap mapping from unicode to glyph before substitution + * the length of this array is determined by the position in the SegCachePrefixEntry */ + uint16 * m_unicode; + /** slots after shapping and positioning */ + Slot * m_glyph; + int16 * m_attr; + byte * m_justs; + mutable unsigned long long m_accessCount; + mutable unsigned long long m_lastAccess; +}; + +} // namespace graphite2 + +#endif diff --git a/gfx/graphite2/src/inc/SegCacheStore.h b/gfx/graphite2/src/inc/SegCacheStore.h new file mode 100644 index 0000000000..1e6a6e216e --- /dev/null +++ b/gfx/graphite2/src/inc/SegCacheStore.h @@ -0,0 +1,127 @@ +/* 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 + +#ifndef GRAPHITE2_NSEGCACHE + +#include "inc/Main.h" +#include "inc/CmapCache.h" +#include "inc/SegCache.h" + +namespace graphite2 { + +class SegCache; +class Face; + +class SilfSegCache +{ + SilfSegCache(const SilfSegCache &); + SilfSegCache & operator = (const SilfSegCache &); + +public: + SilfSegCache() : m_caches(NULL), m_cacheCount(0) {}; + ~SilfSegCache() + { + assert(m_caches == NULL); + } + void clear(SegCacheStore * cacheStore) + { + for (size_t i = 0; i < m_cacheCount; i++) + { + m_caches[i]->clear(cacheStore); + delete m_caches[i]; + } + free(m_caches); + m_caches = NULL; + m_cacheCount = 0; + } + SegCache * getOrCreate(SegCacheStore * cacheStore, const Features & features) + { + for (size_t i = 0; i < m_cacheCount; i++) + { + if (m_caches[i]->features() == features) + return m_caches[i]; + } + SegCache ** newData = gralloc<SegCache*>(m_cacheCount+1); + if (newData) + { + if (m_cacheCount > 0) + { + memcpy(newData, m_caches, sizeof(SegCache*) * m_cacheCount); + free(m_caches); + } + m_caches = newData; + m_caches[m_cacheCount] = new SegCache(cacheStore, features); + m_cacheCount++; + return m_caches[m_cacheCount - 1]; + } + return NULL; + } + CLASS_NEW_DELETE +private: + SegCache ** m_caches; + size_t m_cacheCount; +}; + +class SegCacheStore +{ + SegCacheStore(const SegCacheStore &); + SegCacheStore & operator = (const SegCacheStore &); + +public: + SegCacheStore(const Face & face, unsigned int numSilf, size_t maxSegments); + ~SegCacheStore() + { + for (size_t i = 0; i < m_numSilf; i++) + { + m_caches[i].clear(this); + } + delete [] m_caches; + m_caches = NULL; + } + SegCache * getOrCreate(unsigned int i, const Features & features) + { + return m_caches[i].getOrCreate(this, features); + } + bool isSpaceGlyph(uint16 gid) const { return (gid == m_spaceGid) || (gid == m_zwspGid); } + uint16 maxCmapGid() const { return m_maxCmapGid; } + uint32 maxSegmentCount() const { return m_maxSegments; }; + + CLASS_NEW_DELETE +private: + SilfSegCache * m_caches; + uint8 m_numSilf; + uint32 m_maxSegments; + uint16 m_maxCmapGid; + uint16 m_spaceGid; + uint16 m_zwspGid; +}; + +} // namespace graphite2 + +#endif + diff --git a/gfx/graphite2/src/inc/Segment.h b/gfx/graphite2/src/inc/Segment.h new file mode 100644 index 0000000000..bcba1f2a87 --- /dev/null +++ b/gfx/graphite2/src/inc/Segment.h @@ -0,0 +1,248 @@ +/* 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; + +#ifndef GRAPHITE2_NSEGCACHE +class SegmentScopeState; +#endif +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 + }; + + unsigned int slotCount() const { return m_numGlyphs; } //one slot per glyph + void extendLength(int 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; } + unsigned int 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(unsigned int numchars, const Face* face, uint32 script, int dir); + ~Segment(); +#ifndef GRAPHITE2_NSEGCACHE + SegmentScopeState setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength); + void removeScope(SegmentScopeState & state); + void append(const Segment &other); + void splice(size_t offset, size_t length, Slot * const startSlot, + Slot * endSlot, const Slot * srcSlot, + const size_t numGlyphs); +#endif + 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, int 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 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; } + unsigned int passBits() const { return m_passBits; } + void mergePassBits(const unsigned int 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 + unsigned int 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 + m_passBits; // if bit set then skip pass + int m_defaultOriginal; // number of whitespace chars in the string + int8 m_dir; + uint8 m_flags; // General purpose flags +}; + +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) 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/Shrinker.h b/gfx/graphite2/src/inc/Shrinker.h new file mode 100644 index 0000000000..e4db2f135a --- /dev/null +++ b/gfx/graphite2/src/inc/Shrinker.h @@ -0,0 +1,119 @@ +/* Copyright (c) 2012, Siyuan Fu <fusiyuan2010@gmail.com> + Copyright (c) 2015, SIL International + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +#include <cassert> +#include <cstddef> +#include <cstring> + +#include <iterator> + +//the code from LZ4 +#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) +# define expect(expr,value) (__builtin_expect ((expr),(value)) ) +#else +# define expect(expr,value) (expr) +#endif +#define likely(expr) expect((expr) != 0, 1) +#define unlikely(expr) expect((expr) != 0, 0) +//////////////////// + + +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; + +template<int S> +inline +void unaligned_copy(void * d, void const * s) { + ::memcpy(d, s, S); +} + +inline +u8 * memcpy_nooverlap(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 * memcpy_nooverlap_surpass(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; + while (n--) {*d++ = *s++; } + + return d; +} + + +inline +u8 * memcpy_(u8 * d, u8 const * s, size_t n) { + if (likely(d>s+sizeof(unsigned long))) + return memcpy_nooverlap(d,s,n); + else while (n--) *d++ = *s++; + return d; +} + +} // end of anonymous namespace + + diff --git a/gfx/graphite2/src/inc/Silf.h b/gfx/graphite2/src/inc/Silf.h new file mode 100644 index 0000000000..8e49f70c94 --- /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..daa1124473 --- /dev/null +++ b/gfx/graphite2/src/inc/Slot.h @@ -0,0 +1,172 @@ +/* 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 SegCacheEntry; +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 SegCacheEntry; + 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..4a8e3fa7d1 --- /dev/null +++ b/gfx/graphite2/src/inc/Sparse.h @@ -0,0 +1,171 @@ +/* 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) + { + free(m_array.values); m_array.map=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 = 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..ea20e5775f --- /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(1) // We need this or the structure members aren't alligned + // correctly. Fortunately this form of pragma is supposed + // to be recongnised 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() +} // 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..fe1c2a585f --- /dev/null +++ b/gfx/graphite2/src/inc/TtfUtil.h @@ -0,0 +1,206 @@ +/* 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 +{ + +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 long _v; +public: + Tag(const char n[5]) throw() : _v(TTF_TAG(n[0],n[1],n[2],n[3])) {} + Tag(const unsigned long tag) throw() : _v(tag) {} + + operator unsigned long () 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..9dc760fdcd --- /dev/null +++ b/gfx/graphite2/src/inc/UtfCodec.h @@ -0,0 +1,249 @@ +/* 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 * 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(codeunit_t * s, codeunit_t * e) throw() + { + return e > s; + } +}; + + +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; } + const uint32 ul = cp[1]; + if (uh > 0xDBFF || ul < 0xDC00 || ul > 0xDFFF) { l = -1; return 0xFFFD; } + ++l; + return (uh<<10) + ul + surrogate_offset; + } + + inline + static bool validate(codeunit_t * s, codeunit_t * e) throw() + { + const ptrdiff_t n = e-s; + if (n <= 0) return n == 0; + const uint32 u = *(s+(n-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(codeunit_t * s, codeunit_t * 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; } +}; + +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..615c6cba67 --- /dev/null +++ b/gfx/graphite2/src/inc/bits.h @@ -0,0 +1,146 @@ +/* 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) +{ + v = v - ((v >> 1) & T(~(0UL)/3)); // temp + v = (v & T(~(0UL)/15*3)) + ((v >> 2) & T(~(0UL)/15*3)); // temp + v = (v + (v >> 4)) & T(~(0UL)/255*15); // temp + return (T)(v * T(~(0UL)/255)) >> (sizeof(T)-1)*8; // count +} + +#endif + + +template<int S> +inline unsigned long _mask_over_val(unsigned long v) +{ + v = _mask_over_val<S/2>(v); + v |= v >> S*4; + return v; +} + +template<> +inline unsigned long _mask_over_val<1>(unsigned long v) +{ + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + return v; +} + +template<typename T> +inline T mask_over_val(T v) +{ + return _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..90b8573d65 --- /dev/null +++ b/gfx/graphite2/src/inc/json.h @@ -0,0 +1,172 @@ +/* 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 "inc/List.h" + +namespace graphite2 { + +class json +{ + // Prevent copying + json(const json &); + json & operator = (const json &); + + typedef void (*_context_t)(json &); + class _null_t {}; + + 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; + + typedef const char * string; + typedef double number; + typedef long signed int integer; + typedef bool boolean; + static const _null_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 << (long unsigned int d) throw(); + json & operator << (boolean) throw(); + json & operator << (_null_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, short signed int d) throw() { return j << json::integer(d); } + +inline +json & operator << (json & j, signed int d) throw() { return j << json::integer(d); } + +inline +json & operator << (json & j, unsigned char d) throw() { return j << json::integer(d); } + +inline +json & operator << (json & j, short unsigned int d) throw() { return j << json::integer(d); } + +inline +json & operator << (json & j, unsigned int d) throw() { return j << json::integer(d); } + +inline +json & operator << (json & j, char c) throw () +{ + const char str[2] = {c,0}; + return j << str; +} + +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..50ae1d4d07 --- /dev/null +++ b/gfx/graphite2/src/inc/opcode_table.h @@ -0,0 +1,125 @@ +/* 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"}, + {{do_(next_n), 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..3b6dd3fc3d --- /dev/null +++ b/gfx/graphite2/src/inc/opcodes.h @@ -0,0 +1,689 @@ +/* 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 every #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_) + if (*sp == 0) DIE; + sbinop(/); +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 = int(pop()); + is->setAttr(&seg, slat, 0, val, smap); +ENDOP + +STARTOP(attr_add) + declare_params(1); + const attrCode slat = attrCode(uint8(*param)); + const int val = int(pop()); + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) + { + seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir()); + flags |= POSITIONED; + } + int res = is->getAttr(&seg, slat, 0); + is->setAttr(&seg, slat, 0, val + res, smap); +ENDOP + +STARTOP(attr_sub) + declare_params(1); + const attrCode slat = attrCode(uint8(*param)); + const int val = int(pop()); + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) + { + seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir()); + flags |= POSITIONED; + } + int res = is->getAttr(&seg, slat, 0); + is->setAttr(&seg, slat, 0, res - val, smap); +ENDOP + +STARTOP(attr_set_slot) + declare_params(1); + const attrCode slat = attrCode(uint8(*param)); + const int offset = (map - smap.begin())*int(slat == gr_slatAttTo); + const int val = int(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 size_t 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 size_t idx = uint8(param[1]); + const int val = int(pop()); + is->setAttr(&seg, slat, idx, val, smap); +ENDOP + +STARTOP(iattr_add) + declare_params(2); + const attrCode slat = attrCode(uint8(param[0])); + const size_t idx = uint8(param[1]); + const int val = int(pop()); + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) + { + seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir()); + flags |= POSITIONED; + } + int res = is->getAttr(&seg, slat, idx); + is->setAttr(&seg, slat, idx, val + res, smap); +ENDOP + +STARTOP(iattr_sub) + declare_params(2); + const attrCode slat = attrCode(uint8(param[0])); + const size_t idx = uint8(param[1]); + const int val = int(pop()); + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) + { + seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir()); + flags |= POSITIONED; + } + int res = is->getAttr(&seg, slat, idx); + is->setAttr(&seg, slat, idx, 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 + |