initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

43
thirdparty/graphite/src/inc/CharInfo.h vendored Normal file
View File

@@ -0,0 +1,43 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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 {};

59
thirdparty/graphite/src/inc/CmapCache.h vendored Normal file
View File

@@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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

148
thirdparty/graphite/src/inc/Code.h vendored Normal file
View File

@@ -0,0 +1,148 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
// This class represents loaded graphite stack machine code. It performs
// basic sanity checks, on the incoming code to prevent more obvious problems
// from crashing graphite.
// Author: Tim Eves
#pragma once
#include <cassert>
#include <graphite2/Types.h>
#include "inc/Main.h"
#include "inc/Machine.h"
namespace graphite2 {
class Silf;
class Face;
enum passtype {
PASS_TYPE_UNKNOWN = 0,
PASS_TYPE_LINEBREAK,
PASS_TYPE_SUBSTITUTE,
PASS_TYPE_POSITIONING,
PASS_TYPE_JUSTIFICATION
};
namespace vm {
class Machine::Code
{
public:
enum status_t
{
loaded,
alloc_failed,
invalid_opcode,
unimplemented_opcode_used,
out_of_range_data,
jump_past_end,
arguments_exhausted,
missing_return,
nested_context_item,
underfull_stack
};
private:
class decoder;
instr * _code;
byte * _data;
size_t _data_size,
_instr_count;
byte _max_ref;
mutable status_t _status;
bool _constraint,
_modify,
_delete;
mutable bool _own;
void release_buffers() throw ();
void failure(const status_t) throw();
public:
static size_t estimateCodeDataOut(size_t num_bytecodes, int nRules, int nSlots);
Code() throw();
Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
uint8 pre_context, uint16 rule_length, const Silf &, const Face &,
enum passtype pt, byte * * const _out = 0);
Code(const Machine::Code &) throw();
~Code() throw();
Code & operator=(const Code &rhs) throw();
operator bool () const throw() { return _code && status() == loaded; }
status_t status() const throw() { return _status; }
bool constraint() const throw() { return _constraint; }
size_t dataSize() const throw() { return _data_size; }
size_t instructionCount() const throw() { return _instr_count; }
bool immutable() const throw() { return !(_delete || _modify); }
bool deletes() const throw() { return _delete; }
size_t maxRef() const throw() { return _max_ref; }
void externalProgramMoved(ptrdiff_t) throw();
int32 run(Machine &m, slotref * & map) const;
CLASS_NEW_DELETE;
};
inline
size_t Machine::Code::estimateCodeDataOut(size_t n_bc, int nRules, int nSlots)
{
// max is: all codes are instructions + 1 for each rule + max tempcopies
// allocate space for separate maximal code and data then merge them later
return (n_bc + nRules + nSlots) * sizeof(instr) + n_bc * sizeof(byte);
}
inline Machine::Code::Code() throw()
: _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0),
_status(loaded), _constraint(false), _modify(false), _delete(false),
_own(false)
{
}
inline Machine::Code::Code(const Machine::Code &obj) throw ()
: _code(obj._code),
_data(obj._data),
_data_size(obj._data_size),
_instr_count(obj._instr_count),
_max_ref(obj._max_ref),
_status(obj._status),
_constraint(obj._constraint),
_modify(obj._modify),
_delete(obj._delete),
_own(obj._own)
{
obj._own = false;
}
inline Machine::Code & Machine::Code::operator=(const Machine::Code &rhs) throw() {
if (_instr_count > 0)
release_buffers();
_code = rhs._code;
_data = rhs._data;
_data_size = rhs._data_size;
_instr_count = rhs._instr_count;
_status = rhs._status;
_constraint = rhs._constraint;
_modify = rhs._modify;
_delete = rhs._delete;
_own = rhs._own;
rhs._own = false;
return *this;
}
inline void Machine::Code::externalProgramMoved(ptrdiff_t dist) throw()
{
if (_code && !_own)
{
_code += dist / signed(sizeof(instr));
_data += dist;
}
}
} // namespace vm
} // namespace graphite2

222
thirdparty/graphite/src/inc/Collider.h vendored Normal file
View File

@@ -0,0 +1,222 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
#include "inc/List.h"
#include "inc/Position.h"
#include "inc/Intervals.h"
#include "inc/debug.h"
namespace graphite2 {
class json;
class Slot;
class Segment;
#define SLOTCOLSETUINTPROP(x, y) uint16 x() const { return _ ##x; } void y (uint16 v) { _ ##x = v; }
#define SLOTCOLSETINTPROP(x, y) int16 x() const { return _ ##x; } void y (int16 v) { _ ##x = v; }
#define SLOTCOLSETPOSITIONPROP(x, y) const Position &x() const { return _ ##x; } void y (const Position &v) { _ ##x = v; }
// Slot attributes related to collision-fixing
class SlotCollision
{
public:
enum {
// COLL_TESTONLY = 0, // default - test other glyphs for collision with this one, but don't move this one
COLL_FIX = 1, // fix collisions involving this glyph
COLL_IGNORE = 2, // ignore this glyph altogether
COLL_START = 4, // start of range of possible collisions
COLL_END = 8, // end of range of possible collisions
COLL_KERN = 16, // collisions with this glyph are fixed by adding kerning space after it
COLL_ISCOL = 32, // this glyph has a collision
COLL_KNOWN = 64, // we've figured out what's happening with this glyph
COLL_ISSPACE = 128, // treat this glyph as a space with regard to kerning
COLL_TEMPLOCK = 256, // Lock glyphs that have been given priority positioning
////COLL_JUMPABLE = 128, // moving glyphs may jump this stationary glyph in any direction - DELETE
////COLL_OVERLAP = 256, // use maxoverlap to restrict - DELETE
};
// Behavior for the collision.order attribute. To GDL this is an enum, to us it's a bitfield, with only 1 bit set
// Allows for easier inversion.
enum {
SEQ_ORDER_LEFTDOWN = 1,
SEQ_ORDER_RIGHTUP = 2,
SEQ_ORDER_NOABOVE = 4,
SEQ_ORDER_NOBELOW = 8,
SEQ_ORDER_NOLEFT = 16,
SEQ_ORDER_NORIGHT = 32
};
SlotCollision(Segment *seg, Slot *slot);
void initFromSlot(Segment *seg, Slot *slot);
const Rect &limit() const { return _limit; }
void setLimit(const Rect &r) { _limit = r; }
SLOTCOLSETPOSITIONPROP(shift, setShift)
SLOTCOLSETPOSITIONPROP(offset, setOffset)
SLOTCOLSETPOSITIONPROP(exclOffset, setExclOffset)
SLOTCOLSETUINTPROP(margin, setMargin)
SLOTCOLSETUINTPROP(marginWt, setMarginWt)
SLOTCOLSETUINTPROP(flags, setFlags)
SLOTCOLSETUINTPROP(exclGlyph, setExclGlyph)
SLOTCOLSETUINTPROP(seqClass, setSeqClass)
SLOTCOLSETUINTPROP(seqProxClass, setSeqProxClass)
SLOTCOLSETUINTPROP(seqOrder, setSeqOrder)
SLOTCOLSETINTPROP(seqAboveXoff, setSeqAboveXoff)
SLOTCOLSETUINTPROP(seqAboveWt, setSeqAboveWt)
SLOTCOLSETINTPROP(seqBelowXlim, setSeqBelowXlim)
SLOTCOLSETUINTPROP(seqBelowWt, setSeqBelowWt)
SLOTCOLSETUINTPROP(seqValignHt, setSeqValignHt)
SLOTCOLSETUINTPROP(seqValignWt, setSeqValignWt)
float getKern(int dir) const;
bool ignore() const;
private:
Rect _limit;
Position _shift; // adjustment within the given pass
Position _offset; // total adjustment for collisions
Position _exclOffset;
uint16 _margin;
uint16 _marginWt;
uint16 _flags;
uint16 _exclGlyph;
uint16 _seqClass;
uint16 _seqProxClass;
uint16 _seqOrder;
int16 _seqAboveXoff;
uint16 _seqAboveWt;
int16 _seqBelowXlim;
uint16 _seqBelowWt;
uint16 _seqValignHt;
uint16 _seqValignWt;
}; // end of class SlotColllision
struct BBox;
struct SlantBox;
class ShiftCollider
{
public:
typedef std::pair<float, float> fpair;
typedef Vector<fpair> vfpairs;
typedef vfpairs::iterator ivfpairs;
ShiftCollider(json *dbgout);
~ShiftCollider() throw() { };
bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint,
float margin, float marginMin, const Position &currShift,
const Position &currOffset, int dir, GR_MAYBE_UNUSED json * const dbgout);
bool mergeSlot(Segment *seg, Slot *slot, const SlotCollision *cinfo, const Position &currShift, bool isAfter,
bool sameCluster, bool &hasCol, bool isExclusion, GR_MAYBE_UNUSED json * const dbgout);
Position resolve(Segment *seg, bool &isCol, GR_MAYBE_UNUSED json * const dbgout);
void addBox_slope(bool isx, const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, float weight, float m, bool minright, int mode);
void removeBox(const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, int mode);
const Position &origin() const { return _origin; }
#if !defined GRAPHITE2_NTRACING
void outputJsonDbg(json * const dbgout, Segment *seg, int axis);
void outputJsonDbgStartSlot(json * const dbgout, Segment *seg);
void outputJsonDbgEndSlot(json * const dbgout, Position resultPos, int bestAxis, bool isCol);
void outputJsonDbgOneVector(json * const dbgout, Segment *seg, int axis, float tleft, float bestCost, float bestVal);
void outputJsonDbgRawRanges(json * const dbgout, int axis);
void outputJsonDbgRemovals(json * const dbgout, int axis, Segment *seg);
#endif
CLASS_NEW_DELETE;
protected:
Zones _ranges[4]; // possible movements in 4 directions (horizontally, vertically, diagonally);
Slot * _target; // the glyph to fix
Rect _limit;
Position _currShift;
Position _currOffset;
Position _origin; // Base for all relative calculations
float _margin;
float _marginWt;
float _len[4];
uint16 _seqClass;
uint16 _seqProxClass;
uint16 _seqOrder;
//bool _scraping[4];
}; // end of class ShiftCollider
inline
ShiftCollider::ShiftCollider(GR_MAYBE_UNUSED json *dbgout)
: _target(0),
_margin(0.0),
_marginWt(0.0),
_seqClass(0),
_seqProxClass(0),
_seqOrder(0)
{
#if !defined GRAPHITE2_NTRACING
for (int i = 0; i < 4; ++i)
_ranges[i].setdebug(dbgout);
#endif
}
class KernCollider
{
public:
KernCollider(json *dbg);
~KernCollider() throw() { };
bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint, float margin,
const Position &currShift, const Position &offsetPrev, int dir,
float ymin, float ymax, json * const dbgout);
bool mergeSlot(Segment *seg, Slot *slot, const Position &currShift, float currSpace, int dir, json * const dbgout);
Position resolve(Segment *seg, Slot *slot, int dir, json * const dbgout);
void shift(const Position &mv, int dir);
CLASS_NEW_DELETE;
private:
Slot * _target; // the glyph to fix
Rect _limit;
float _margin;
Position _offsetPrev; // kern from a previous pass
Position _currShift; // NOT USED??
float _miny; // y-coordinates offset by global slot position
float _maxy;
Vector<float> _edges; // edges of horizontal slices
float _sliceWidth; // width of each slice
float _mingap;
float _xbound; // max or min edge
bool _hit;
#if !defined GRAPHITE2_NTRACING
// Debugging
Segment * _seg;
Vector<float> _nearEdges; // closest potential collision in each slice
Vector<Slot*> _slotNear;
#endif
}; // end of class KernCollider
inline
float sqr(float x) {
return x * x;
}
inline
KernCollider::KernCollider(GR_MAYBE_UNUSED json *dbg)
: _target(0),
_margin(0.0f),
_miny(-1e38f),
_maxy(1e38f),
_sliceWidth(0.0f),
_mingap(0.0f),
_xbound(0.0),
_hit(false)
{
#if !defined GRAPHITE2_NTRACING
_seg = 0;
#endif
};
}; // end of namespace graphite2

View File

@@ -0,0 +1,81 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2015, SIL International, All rights reserved.
#pragma once
#include <cassert>
#include <cstddef>
#include <cstring>
namespace
{
#if defined(_MSC_VER)
typedef unsigned __int8 u8;
typedef unsigned __int16 u16;
typedef unsigned __int32 u32;
typedef unsigned __int64 u64;
#else
#include <stdint.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
#endif
ptrdiff_t const MINMATCH = 4,
LASTLITERALS = 5,
MINCODA = LASTLITERALS+1,
MINSRCSIZE = 13;
template<int S>
inline
void unaligned_copy(void * d, void const * s) {
::memcpy(d, s, S);
}
inline
size_t align(size_t p) {
return (p + sizeof(unsigned long)-1) & ~(sizeof(unsigned long)-1);
}
inline
u8 * safe_copy(u8 * d, u8 const * s, size_t n) {
while (n--) *d++ = *s++;
return d;
}
inline
u8 * overrun_copy(u8 * d, u8 const * s, size_t n) {
size_t const WS = sizeof(unsigned long);
u8 const * e = s + n;
do
{
unaligned_copy<WS>(d, s);
d += WS;
s += WS;
}
while (s < e);
d-=(s-e);
return d;
}
inline
u8 * fast_copy(u8 * d, u8 const * s, size_t n) {
size_t const WS = sizeof(unsigned long);
size_t wn = n/WS;
while (wn--)
{
unaligned_copy<WS>(d, s);
d += WS;
s += WS;
}
n &= WS-1;
return safe_copy(d, s, n);
}
} // end of anonymous namespace

View File

@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2015, SIL International, All rights reserved.
#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

86
thirdparty/graphite/src/inc/Endian.h vendored Normal file
View File

@@ -0,0 +1,86 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2011, SIL International, All rights reserved.
/*
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; }

111
thirdparty/graphite/src/inc/Error.h vendored Normal file
View File

@@ -0,0 +1,111 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2013, SIL International, All rights reserved.
#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 = pr ? err : 0); }
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 error {
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,
};
}

202
thirdparty/graphite/src/inc/Face.h vendored Normal file
View File

@@ -0,0 +1,202 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
#include <cstdio>
#include "graphite2/Font.h"
#include "inc/Main.h"
#include "inc/FeatureMap.h"
#include "inc/TtfUtil.h"
#include "inc/Silf.h"
#include "inc/Error.h"
namespace graphite2 {
class Cmap;
class FileFace;
class GlyphCache;
class NameTable;
class json;
class Font;
using TtfUtil::Tag;
// These are the actual tags, as distinct from the consecutive IDs in TtfUtil.h
class Face
{
// Prevent any kind of copying
Face(const Face&);
Face& operator=(const Face&);
public:
class Table;
static float default_glyph_advance(const void* face_ptr, gr_uint16 glyphid);
Face(const void* appFaceHandle/*non-NULL*/, const gr_face_ops & ops);
virtual ~Face();
virtual bool runGraphite(Segment *seg, const Silf *silf) const;
public:
bool readGlyphs(uint32 faceOptions);
bool readGraphite(const Table & silf);
bool readFeatures();
void takeFileFace(FileFace* pFileFace/*takes ownership*/);
const SillMap & theSill() const;
const GlyphCache & glyphs() const;
Cmap & cmap() const;
NameTable * nameTable() const;
void setLogger(FILE *log_file);
json * logger() const throw();
const Silf * chooseSilf(uint32 script) const;
uint16 languageForLocale(const char * locale) const;
// Features
uint16 numFeatures() const;
const FeatureRef * featureById(uint32 id) const;
const FeatureRef * feature(uint16 index) const;
// Glyph related
int32 getGlyphMetric(uint16 gid, uint8 metric) const;
uint16 findPseudo(uint32 uid) const;
// Errors
unsigned int error() const { return m_error; }
bool error(Error e) { m_error = e.error(); return false; }
unsigned int error_context() const { return m_error; }
void error_context(unsigned int errcntxt) { m_errcntxt = errcntxt; }
CLASS_NEW_DELETE;
private:
SillMap m_Sill;
gr_face_ops m_ops;
const void * m_appFaceHandle; // non-NULL
FileFace * m_pFileFace; //owned
mutable GlyphCache * m_pGlyphFaceCache; // owned - never NULL
mutable Cmap * m_cmap; // cmap cache if available
mutable NameTable * m_pNames;
mutable json * m_logger;
unsigned int m_error;
unsigned int m_errcntxt;
protected:
Silf * m_silfs; // silf subtables.
uint16 m_numSilf; // num silf subtables in the silf table
private:
uint16 m_ascent,
m_descent;
#ifdef GRAPHITE2_TELEMETRY
public:
mutable telemetry tele;
#endif
};
inline
const SillMap & Face::theSill() const
{
return m_Sill;
}
inline
uint16 Face::numFeatures() const
{
return m_Sill.theFeatureMap().numFeats();
}
inline
const FeatureRef * Face::featureById(uint32 id) const
{
return m_Sill.theFeatureMap().findFeatureRef(id);
}
inline
const FeatureRef *Face::feature(uint16 index) const
{
return m_Sill.theFeatureMap().feature(index);
}
inline
const GlyphCache & Face::glyphs() const
{
return *m_pGlyphFaceCache;
}
inline
Cmap & Face::cmap() const
{
return *m_cmap;
};
inline
json * Face::logger() const throw()
{
return m_logger;
}
class Face::Table
{
const Face * _f;
mutable const byte * _p;
size_t _sz;
bool _compressed;
Error decompress();
void release();
public:
Table() throw();
Table(const Face & face, const Tag n, uint32 version=0xffffffff) throw();
~Table() throw();
Table(const Table && rhs) throw();
operator const byte * () const throw();
size_t size() const throw();
Table & operator = (const Table && rhs) throw();
};
inline
Face::Table::Table() throw()
: _f(0), _p(0), _sz(0), _compressed(false)
{
}
inline
Face::Table::Table(const Table && rhs) throw()
: _f(rhs._f), _p(rhs._p), _sz(rhs._sz), _compressed(rhs._compressed)
{
rhs._p = 0;
}
inline
Face::Table::~Table() throw()
{
release();
}
inline
Face::Table::operator const byte * () const throw()
{
return _p;
}
inline
size_t Face::Table::size() const throw()
{
return _sz;
}
} // namespace graphite2
struct gr_face : public graphite2::Face {};

175
thirdparty/graphite/src/inc/FeatureMap.h vendored Normal file
View File

@@ -0,0 +1,175 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
#include "inc/Main.h"
#include "inc/FeatureVal.h"
namespace graphite2 {
// Forward declarations for implmentation types
class FeatureMap;
class Face;
class FeatureSetting
{
public:
FeatureSetting(int16 theValue, uint16 labelId) : m_label(labelId), m_value(theValue) {};
uint16 label() const { return m_label; }
int16 value() const { return m_value; }
CLASS_NEW_DELETE;
private:
FeatureSetting(const FeatureSetting & fs) : m_label(fs.m_label), m_value(fs.m_value) {};
uint16 m_label;
int16 m_value;
};
class FeatureRef
{
typedef uint32 chunk_t;
static const uint8 SIZEOF_CHUNK = sizeof(chunk_t)*8;
public:
enum flags_t : uint16 {
HIDDEN = 0x0800
};
FeatureRef() throw();
FeatureRef(const Face & face, unsigned short & bits_offset, uint32 max_val,
uint32 name, uint16 uiName, flags_t flags,
FeatureSetting *settings, uint16 num_set) throw();
~FeatureRef() throw();
bool applyValToFeature(uint32 val, Features& pDest) const; //defined in GrFaceImp.h
void maskFeature(Features & pDest) const {
if (m_index < pDest.size()) //defensive
pDest[m_index] |= m_mask;
}
uint32 getFeatureVal(const Features& feats) const; //defined in GrFaceImp.h
uint32 getId() const { return m_id; }
uint16 getNameId() const { return m_nameid; }
uint16 getNumSettings() const { return m_numSet; }
uint16 getSettingName(uint16 index) const { return m_nameValues[index].label(); }
int16 getSettingValue(uint16 index) const { return m_nameValues[index].value(); }
flags_t getFlags() const { return m_flags; }
uint32 maxVal() const { return m_max; }
const Face & getFace() const { assert(m_face); return *m_face;}
const FeatureMap* getFeatureMap() const;// { return m_pFace;}
CLASS_NEW_DELETE;
private:
FeatureRef(const FeatureRef & rhs);
const Face * m_face;
FeatureSetting * m_nameValues; // array of name table ids for feature values
chunk_t m_mask, // bit mask to get the value from the vector
m_max; // max value the value can take
uint32 m_id; // feature identifier/name
uint16 m_nameid, // Name table id for feature name
m_numSet; // number of values (number of entries in m_nameValues)
flags_t m_flags; // feature flags see FeatureRef::flags_t.
byte m_bits, // how many bits to shift the value into place
m_index; // index into the array to find the ulong to mask
private: //unimplemented
FeatureRef& operator=(const FeatureRef&);
};
inline
FeatureRef::FeatureRef() throw()
: m_face(0),
m_nameValues(0),
m_mask(0), m_max(0),
m_id(0), m_nameid(0), m_numSet(0),
m_flags(flags_t(0)),
m_bits(0), m_index(0)
{
}
class NameAndFeatureRef
{
public:
NameAndFeatureRef(uint32 name = 0) : m_name(name) , m_pFRef(NULL){}
NameAndFeatureRef(FeatureRef const & p) : m_name(p.getId()), m_pFRef(&p) {}
bool operator<(const NameAndFeatureRef& rhs) const //orders by m_name
{ return m_name<rhs.m_name; }
CLASS_NEW_DELETE
uint32 m_name;
const FeatureRef* m_pFRef;
};
class FeatureMap
{
public:
FeatureMap() : m_numFeats(0), m_feats(NULL), m_pNamedFeats(NULL) {}
~FeatureMap() { delete[] m_feats; delete[] m_pNamedFeats; }
bool readFeats(const Face & face);
const FeatureRef *findFeatureRef(uint32 name) const;
FeatureRef *feature(uint16 index) const { return m_feats + index; }
//GrFeatureRef *featureRef(byte index) { return index < m_numFeats ? m_feats + index : NULL; }
const FeatureRef *featureRef(byte index) const { return index < m_numFeats ? m_feats + index : NULL; }
FeatureVal* cloneFeatures(uint32 langname/*0 means default*/) const; //call destroy_Features when done.
uint16 numFeats() const { return m_numFeats; };
CLASS_NEW_DELETE
private:
friend class SillMap;
uint16 m_numFeats;
FeatureRef *m_feats;
NameAndFeatureRef* m_pNamedFeats; //owned
FeatureVal m_defaultFeatures; //owned
private: //defensive on m_feats, m_pNamedFeats, and m_defaultFeatures
FeatureMap(const FeatureMap&);
FeatureMap& operator=(const FeatureMap&);
};
class SillMap
{
private:
class LangFeaturePair
{
LangFeaturePair(const LangFeaturePair &);
LangFeaturePair & operator = (const LangFeaturePair &);
public:
LangFeaturePair() : m_lang(0), m_pFeatures(0) {}
~LangFeaturePair() { delete m_pFeatures; }
uint32 m_lang;
Features* m_pFeatures; //owns
CLASS_NEW_DELETE
};
public:
SillMap() : m_langFeats(NULL), m_numLanguages(0) {}
~SillMap() { delete[] m_langFeats; }
bool readFace(const Face & face);
bool readSill(const Face & face);
FeatureVal* cloneFeatures(uint32 langname/*0 means default*/) const; //call destroy_Features when done.
uint16 numLanguages() const { return m_numLanguages; };
uint32 getLangName(uint16 index) const { return (index < m_numLanguages)? m_langFeats[index].m_lang : 0; };
const FeatureMap & theFeatureMap() const { return m_FeatureMap; };
private:
FeatureMap m_FeatureMap; //of face
LangFeaturePair * m_langFeats;
uint16 m_numLanguages;
private: //defensive on m_langFeats
SillMap(const SillMap&);
SillMap& operator=(const SillMap&);
};
} // namespace graphite2
struct gr_feature_ref : public graphite2::FeatureRef {};

View File

@@ -0,0 +1,45 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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 {};

57
thirdparty/graphite/src/inc/FileFace.h vendored Normal file
View File

@@ -0,0 +1,57 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2012, SIL International, All rights reserved.
#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

67
thirdparty/graphite/src/inc/Font.h vendored Normal file
View File

@@ -0,0 +1,67 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
#include <cassert>
#include "graphite2/Font.h"
#include "inc/Main.h"
#include "inc/Face.h"
namespace graphite2 {
#define INVALID_ADVANCE -1e38f // can't be a static const because non-integral
class Font
{
public:
Font(float ppm, const Face & face, const void * appFontHandle=0, const gr_font_ops * ops=0);
virtual ~Font();
float advance(unsigned short glyphid) const;
float scale() const;
bool isHinted() const;
const Face & face() const;
operator bool () const throw() { return m_advances; }
CLASS_NEW_DELETE;
private:
gr_font_ops m_ops;
const void * const m_appFontHandle;
float * m_advances; // One advance per glyph in pixels. Nan if not defined
const Face & m_face;
float m_scale; // scales from design units to ppm
bool m_hinted;
Font(const Font&);
Font& operator=(const Font&);
};
inline
float Font::advance(unsigned short glyphid) const
{
if (m_advances[glyphid] == INVALID_ADVANCE)
m_advances[glyphid] = (*m_ops.glyph_advance_x)(m_appFontHandle, glyphid);
return m_advances[glyphid];
}
inline
float Font::scale() const
{
return m_scale;
}
inline
bool Font::isHinted() const
{
return m_hinted;
}
inline
const Face & Font::face() const
{
return m_face;
}
} // namespace graphite2
struct gr_font : public graphite2::Font {};

200
thirdparty/graphite/src/inc/GlyphCache.h vendored Normal file
View File

@@ -0,0 +1,200 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2012, SIL International, All rights reserved.
#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

60
thirdparty/graphite/src/inc/GlyphFace.h vendored Normal file
View File

@@ -0,0 +1,60 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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

211
thirdparty/graphite/src/inc/Intervals.h vendored Normal file
View File

@@ -0,0 +1,211 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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

145
thirdparty/graphite/src/inc/List.h vendored Normal file
View File

@@ -0,0 +1,145 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
// designed to have a limited subset of the std::vector api
#pragma once
#include <cstddef>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <new>
#include "Main.h"
namespace graphite2 {
template <typename T>
inline
ptrdiff_t distance(T* first, T* last) { return last-first; }
template <typename T>
class Vector
{
T * m_first, *m_last, *m_end;
public:
typedef T & reference;
typedef const T & const_reference;
typedef T * iterator;
typedef const T * const_iterator;
Vector() : m_first(0), m_last(0), m_end(0) {}
Vector(size_t n, const T& value = T()) : m_first(0), m_last(0), m_end(0) { insert(begin(), n, value); }
Vector(const Vector<T> &rhs) : m_first(0), m_last(0), m_end(0) { insert(begin(), rhs.begin(), rhs.end()); }
template <typename I>
Vector(I first, const I last) : m_first(0), m_last(0), m_end(0) { insert(begin(), first, last); }
~Vector() { clear(); free(m_first); }
iterator begin() { return m_first; }
const_iterator begin() const { return m_first; }
iterator end() { return m_last; }
const_iterator end() const { return m_last; }
bool empty() const { return m_first == m_last; }
size_t size() const { return m_last - m_first; }
size_t capacity() const{ return m_end - m_first; }
void reserve(size_t n);
void resize(size_t n, const T & v = T());
reference front() { assert(size() > 0); return *begin(); }
const_reference front() const { assert(size() > 0); return *begin(); }
reference back() { assert(size() > 0); return *(end()-1); }
const_reference back() const { assert(size() > 0); return *(end()-1); }
Vector<T> & operator = (const Vector<T> & rhs) { assign(rhs.begin(), rhs.end()); return *this; }
reference operator [] (size_t n) { assert(size() > n); return m_first[n]; }
const_reference operator [] (size_t n) const { assert(size() > n); return m_first[n]; }
void assign(size_t n, const T& u) { clear(); insert(begin(), n, u); }
void assign(const_iterator first, const_iterator last) { clear(); insert(begin(), first, last); }
iterator insert(iterator p, const T & x) { p = _insert_default(p, 1); new (p) T(x); return p; }
void insert(iterator p, size_t n, const T & x);
void insert(iterator p, const_iterator first, const_iterator last);
void pop_back() { assert(size() > 0); --m_last; }
void push_back(const T &v) { if (m_last == m_end) reserve(size()+1); new (m_last++) T(v); }
void clear() { erase(begin(), end()); }
iterator erase(iterator p) { return erase(p, p+1); }
iterator erase(iterator first, iterator last);
private:
iterator _insert_default(iterator p, size_t n);
};
template <typename T>
inline
void Vector<T>::reserve(size_t n)
{
if (n > capacity())
{
const ptrdiff_t sz = size();
size_t requested;
if (checked_mul(n,sizeof(T), requested)) std::abort();
m_first = static_cast<T*>(realloc(m_first, requested));
if (!m_first) std::abort();
m_last = m_first + sz;
m_end = m_first + n;
}
}
template <typename T>
inline
void Vector<T>::resize(size_t n, const T & v) {
const ptrdiff_t d = n-size();
if (d < 0) erase(end()+d, end());
else if (d > 0) insert(end(), d, v);
}
template<typename T>
inline
typename Vector<T>::iterator Vector<T>::_insert_default(iterator p, size_t n)
{
assert(begin() <= p && p <= end());
const ptrdiff_t i = p - begin();
reserve(((size() + n + 7) >> 3) << 3);
p = begin() + i;
// Move tail if there is one
if (p != end()) memmove(p + n, p, distance(p,end())*sizeof(T));
m_last += n;
return p;
}
template<typename T>
inline
void Vector<T>::insert(iterator p, size_t n, const T & x)
{
p = _insert_default(p, n);
// Copy in elements
for (; n; --n, ++p) { new (p) T(x); }
}
template<typename T>
inline
void Vector<T>::insert(iterator p, const_iterator first, const_iterator last)
{
p = _insert_default(p, distance(first, last));
// Copy in elements
for (;first != last; ++first, ++p) { new (p) T(*first); }
}
template<typename T>
inline
typename Vector<T>::iterator Vector<T>::erase(iterator first, iterator last)
{
for (iterator e = first; e != last; ++e) e->~T();
const size_t sz = distance(first, last);
if (m_last != last) memmove(first, last, distance(last,end())*sizeof(T));
m_last -= sz;
return first;
}
} // namespace graphite2

184
thirdparty/graphite/src/inc/Machine.h vendored Normal file
View File

@@ -0,0 +1,184 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
// This general interpreter interface.
// Author: Tim Eves
// Build one of direct_machine.cpp or call_machine.cpp to implement this
// interface.
#pragma once
#include <cstring>
#include <limits>
#include <graphite2/Types.h>
#include "inc/Main.h"
#if defined(__GNUC__)
#if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ * 10) < 430
#define HOT
#if defined(__x86_64)
#define REGPARM(n) __attribute__((regparm(n)))
#else
#define REGPARM(n)
#endif
#else
#define HOT __attribute__((hot))
#if defined(__x86_64)
#define REGPARM(n) __attribute__((hot, regparm(n)))
#else
#define REGPARM(n)
#endif
#endif
#else
#define HOT
#define REGPARM(n)
#endif
#if defined(__MINGW32__)
// MinGW's <limits> at some point includes winnt.h which #define's a
// DELETE macro, which conflicts with enum opcode below, so we undefine
// it here.
#undef DELETE
#endif
namespace graphite2 {
// Forward declarations
class Segment;
class Slot;
class SlotMap;
namespace vm
{
typedef void * instr;
typedef Slot * slotref;
enum {VARARGS = 0xff, MAX_NAME_LEN=32};
enum opcode {
NOP = 0,
PUSH_BYTE, PUSH_BYTEU, PUSH_SHORT, PUSH_SHORTU, PUSH_LONG,
ADD, SUB, MUL, DIV,
MIN_, MAX_,
NEG,
TRUNC8, TRUNC16,
COND,
AND, OR, NOT,
EQUAL, NOT_EQ,
LESS, GTR, LESS_EQ, GTR_EQ,
NEXT, NEXT_N, COPY_NEXT,
PUT_GLYPH_8BIT_OBS, PUT_SUBS_8BIT_OBS, PUT_COPY,
INSERT, DELETE,
ASSOC,
CNTXT_ITEM,
ATTR_SET, ATTR_ADD, ATTR_SUB,
ATTR_SET_SLOT,
IATTR_SET_SLOT,
PUSH_SLOT_ATTR, PUSH_GLYPH_ATTR_OBS,
PUSH_GLYPH_METRIC, PUSH_FEAT,
PUSH_ATT_TO_GATTR_OBS, PUSH_ATT_TO_GLYPH_METRIC,
PUSH_ISLOT_ATTR,
PUSH_IGLYPH_ATTR, // not implemented
POP_RET, RET_ZERO, RET_TRUE,
IATTR_SET, IATTR_ADD, IATTR_SUB,
PUSH_PROC_STATE, PUSH_VERSION,
PUT_SUBS, PUT_SUBS2, PUT_SUBS3,
PUT_GLYPH, PUSH_GLYPH_ATTR, PUSH_ATT_TO_GLYPH_ATTR,
BITOR, BITAND, BITNOT,
BITSET, SET_FEAT,
MAX_OPCODE,
// private opcodes for internal use only, comes after all other on disk opcodes
TEMP_COPY = MAX_OPCODE
};
struct opcode_t
{
instr impl[2];
uint8 param_sz;
char name[MAX_NAME_LEN];
};
class Machine
{
public:
typedef int32 stack_t;
static size_t const STACK_ORDER = 10,
STACK_MAX = 1 << STACK_ORDER,
STACK_GUARD = 2;
class Code;
enum status_t {
finished = 0,
stack_underflow,
stack_not_empty,
stack_overflow,
slot_offset_out_bounds,
died_early
};
Machine(SlotMap &) throw();
static const opcode_t * getOpcodeTable() throw();
CLASS_NEW_DELETE;
SlotMap & slotMap() const throw();
status_t status() const throw();
// operator bool () const throw();
private:
void check_final_stack(const stack_t * const sp);
stack_t run(const instr * program, const byte * data,
slotref * & map) HOT;
SlotMap & _map;
stack_t _stack[STACK_MAX + 2*STACK_GUARD];
status_t _status;
};
inline Machine::Machine(SlotMap & map) throw()
: _map(map), _status(finished)
{
// Initialise stack guard +1 entries as the stack pointer points to the
// current top of stack, hence the first push will never write entry 0.
// Initialising the guard space like this is unnecessary and is only
// done to keep valgrind happy during fuzz testing. Hopefully loop
// unrolling will flatten this.
for (size_t n = STACK_GUARD + 1; n; --n) _stack[n-1] = 0;
}
inline SlotMap& Machine::slotMap() const throw()
{
return _map;
}
inline Machine::status_t Machine::status() const throw()
{
return _status;
}
inline void Machine::check_final_stack(const stack_t * const sp)
{
if (_status != finished) return;
stack_t const * const base = _stack + STACK_GUARD,
* const limit = base + STACK_MAX;
if (sp < base) _status = stack_underflow; // This should be impossible now.
else if (sp >= limit) _status = stack_overflow; // So should this.
else if (sp != base) _status = stack_not_empty;
}
} // namespace vm
} // namespace graphite2

176
thirdparty/graphite/src/inc/Main.h vendored Normal file
View File

@@ -0,0 +1,176 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
#include <cstdlib>
#include "graphite2/Types.h"
#ifdef GRAPHITE2_CUSTOM_HEADER
#include GRAPHITE2_CUSTOM_HEADER
#endif
namespace graphite2 {
typedef gr_uint8 uint8;
typedef gr_uint8 byte;
typedef gr_uint16 uint16;
typedef gr_uint32 uint32;
typedef gr_int8 int8;
typedef gr_int16 int16;
typedef gr_int32 int32;
typedef size_t uintptr;
#ifdef GRAPHITE2_TELEMETRY
struct telemetry
{
class category;
static size_t * _category;
static void set_category(size_t & t) throw() { _category = &t; }
static void stop() throw() { _category = 0; }
static void count_bytes(size_t n) throw() { if (_category) *_category += n; }
size_t misc,
silf,
glyph,
code,
states,
starts,
transitions;
telemetry() : misc(0), silf(0), glyph(0), code(0), states(0), starts(0), transitions(0) {}
};
class telemetry::category
{
size_t * _prev;
public:
category(size_t & t) : _prev(_category) { _category = &t; }
~category() { _category = _prev; }
};
#else
struct telemetry {};
#endif
// Checked multiplaction to catch overflow or underflow when allocating memory
#if defined(__has_builtin)
#if __has_builtin(__builtin_mul_overflow)
#define HAVE_BUILTIN_OVERFLOW
#endif
#elif defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__INTEL_COMPILER)
#define HAVE_BUILTIN_OVERFLOW
#endif
#if defined(__has_include)
#if __has_include(<intsafe.h>) && !defined(__CYGWIN__)
#define HAVE_INTSAFE_H
#endif
#elif defined(_WIN32)
#define HAVE_INTSAFE_H
#endif
// Need to import intsafe into the top level namespace
#if defined(HAVE_INTSAFE_H)
} // namespace graphite2
#include <intsafe.h>
namespace graphite2 {
#endif
#if defined(HAVE_BUILTIN_OVERFLOW)
inline
bool checked_mul(const size_t a, const size_t b, size_t & t) {
return __builtin_mul_overflow(a, b, &t);
}
#elif defined(HAVE_INTSAFE_H)
inline
bool checked_mul(const size_t a, const size_t b, size_t & t) {
return SizeTMult(a, b, &t) == INTSAFE_E_ARITHMETIC_OVERFLOW;
}
#else
inline
bool checked_mul(const size_t a, const size_t b, size_t & t) {
t = a*b;
return (((a | b) & (~size_t(0) << (sizeof(size_t) << 2))) && (t / a != b));
}
#endif
// typesafe wrapper around malloc for simple types
// use free(pointer) to deallocate
template <typename T> T * gralloc(size_t n)
{
size_t total;
if (checked_mul(n, sizeof(T), total))
return 0;
#ifdef GRAPHITE2_TELEMETRY
telemetry::count_bytes(total);
#endif
return static_cast<T*>(malloc(total));
}
template <typename T> T * grzeroalloc(size_t n)
{
#ifdef GRAPHITE2_TELEMETRY
telemetry::count_bytes(sizeof(T) * n);
#endif
return static_cast<T*>(calloc(n, sizeof(T)));
}
template <typename T>
inline T min(const T a, const T b)
{
return a < b ? a : b;
}
template <typename T>
inline T max(const T a, const T b)
{
return a > b ? a : b;
}
} // namespace graphite2
#define CLASS_NEW_DELETE \
void * operator new (size_t size){ return gralloc<byte>(size);} \
void * operator new (size_t, void * p) throw() { return p; } \
void * operator new[] (size_t size) {return gralloc<byte>(size);} \
void * operator new[] (size_t, void * p) throw() { return p; } \
void operator delete (void * p) throw() { free(p);} \
void operator delete (void *, void *) throw() {} \
void operator delete[] (void * p)throw() { free(p); } \
void operator delete[] (void *, void *) throw() {}
#if defined(__GNUC__) || defined(__clang__)
#define GR_MAYBE_UNUSED __attribute__((unused))
#else
#define GR_MAYBE_UNUSED
#endif
#ifndef __has_cpp_attribute
# define __has_cpp_attribute(x) 0
#endif
#if __has_cpp_attribute(clang::fallthrough)
# define GR_FALLTHROUGH [[clang::fallthrough]]
#elif __has_cpp_attribute(gnu::fallthrough)
# define GR_FALLTHROUGH [[gnu::fallthrough]]
#elif defined(_MSC_VER)
/*
* MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
* https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
*/
#include <sal.h>
#define GR_FALLTHROUGH __fallthrough
#elif __GNUC__ >= 7
#define GR_FALLTHROUGH __attribute__ ((fallthrough))
#else
#define GR_FALLTHROUGH /* fallthrough */
#endif
#ifdef _MSC_VER
#pragma warning(disable: 4800)
#pragma warning(disable: 4355)
#endif

42
thirdparty/graphite/src/inc/NameTable.h vendored Normal file
View File

@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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

95
thirdparty/graphite/src/inc/Pass.h vendored Normal file
View File

@@ -0,0 +1,95 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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

45
thirdparty/graphite/src/inc/Position.h vendored Normal file
View File

@@ -0,0 +1,45 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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

282
thirdparty/graphite/src/inc/Rule.h vendored Normal file
View File

@@ -0,0 +1,282 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2011, SIL International, All rights reserved.
#pragma once
#include "inc/Code.h"
#include "inc/Slot.h"
namespace graphite2 {
struct Rule {
const vm::Machine::Code * constraint,
* action;
unsigned short sort;
byte preContext;
#ifndef NDEBUG
uint16 rule_idx;
#endif
Rule();
~Rule() {}
CLASS_NEW_DELETE;
private:
Rule(const Rule &);
Rule & operator = (const Rule &);
};
inline
Rule::Rule()
: constraint(0),
action(0),
sort(0),
preContext(0)
{
#ifndef NDEBUG
rule_idx = 0;
#endif
}
struct RuleEntry
{
const Rule * rule;
inline
bool operator < (const RuleEntry &r) const
{
const unsigned short lsort = rule->sort, rsort = r.rule->sort;
return lsort > rsort || (lsort == rsort && rule < r.rule);
}
inline
bool operator == (const RuleEntry &r) const
{
return rule == r.rule;
}
};
struct State
{
const RuleEntry * rules,
* rules_end;
bool empty() const;
};
inline
bool State::empty() const
{
return rules_end == rules;
}
class SlotMap
{
public:
enum {MAX_SLOTS=64};
SlotMap(Segment & seg, uint8 direction, size_t maxSize);
Slot * * begin();
Slot * * end();
size_t size() const;
unsigned short context() const;
void reset(Slot &, unsigned short);
Slot * const & operator[](int n) const;
Slot * & operator [] (int);
void pushSlot(Slot * const slot);
void collectGarbage(Slot *& aSlot);
Slot * highwater() { return m_highwater; }
void highwater(Slot *s) { m_highwater = s; m_highpassed = false; }
bool highpassed() const { return m_highpassed; }
void highpassed(bool v) { m_highpassed = v; }
uint8 dir() const { return m_dir; }
int decMax() { return --m_maxSize; }
Segment & segment;
private:
Slot * m_slot_map[MAX_SLOTS+1];
unsigned short m_size;
unsigned short m_precontext;
Slot * m_highwater;
int m_maxSize;
uint8 m_dir;
bool m_highpassed;
};
class FiniteStateMachine
{
public:
enum {MAX_RULES=128};
private:
class Rules
{
public:
Rules();
void clear();
const RuleEntry * begin() const;
const RuleEntry * end() const;
size_t size() const;
void accumulate_rules(const State &state);
private:
RuleEntry * m_begin,
* m_end,
m_rules[MAX_RULES*2];
};
public:
FiniteStateMachine(SlotMap & map, json * logger);
void reset(Slot * & slot, const short unsigned int max_pre_ctxt);
Rules rules;
SlotMap & slots;
json * const dbgout;
};
inline
FiniteStateMachine::FiniteStateMachine(SlotMap& map, json * logger)
: slots(map),
dbgout(logger)
{
}
inline
void FiniteStateMachine::reset(Slot * & slot, const short unsigned int max_pre_ctxt)
{
rules.clear();
int ctxt = 0;
for (; ctxt != max_pre_ctxt && slot->prev(); ++ctxt, slot = slot->prev());
slots.reset(*slot, ctxt);
}
inline
FiniteStateMachine::Rules::Rules()
: m_begin(m_rules), m_end(m_rules)
{
}
inline
void FiniteStateMachine::Rules::clear()
{
m_end = m_begin;
}
inline
const RuleEntry * FiniteStateMachine::Rules::begin() const
{
return m_begin;
}
inline
const RuleEntry * FiniteStateMachine::Rules::end() const
{
return m_end;
}
inline
size_t FiniteStateMachine::Rules::size() const
{
return m_end - m_begin;
}
inline
void FiniteStateMachine::Rules::accumulate_rules(const State &state)
{
// Only bother if there are rules in the State object.
if (state.empty()) return;
// Merge the new sorted rules list into the current sorted result set.
const RuleEntry * lre = begin(), * rre = state.rules;
RuleEntry * out = m_rules + (m_begin == m_rules)*MAX_RULES;
const RuleEntry * const lrend = out + MAX_RULES,
* const rrend = state.rules_end;
m_begin = out;
while (lre != end() && out != lrend)
{
if (*lre < *rre) *out++ = *lre++;
else if (*rre < *lre) { *out++ = *rre++; }
else { *out++ = *lre++; ++rre; }
if (rre == rrend)
{
while (lre != end() && out != lrend) { *out++ = *lre++; }
m_end = out;
return;
}
}
while (rre != rrend && out != lrend) { *out++ = *rre++; }
m_end = out;
}
inline
SlotMap::SlotMap(Segment & seg, uint8 direction, size_t maxSize)
: segment(seg), m_size(0), m_precontext(0), m_highwater(0),
m_maxSize(int(maxSize)), m_dir(direction), m_highpassed(false)
{
m_slot_map[0] = 0;
}
inline
Slot * * SlotMap::begin()
{
return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting
// at start of segment.
}
inline
Slot * * SlotMap::end()
{
return m_slot_map + m_size + 1;
}
inline
size_t SlotMap::size() const
{
return m_size;
}
inline
short unsigned int SlotMap::context() const
{
return m_precontext;
}
inline
void SlotMap::reset(Slot & slot, short unsigned int ctxt)
{
m_size = 0;
m_precontext = ctxt;
*m_slot_map = slot.prev();
}
inline
void SlotMap::pushSlot(Slot*const slot)
{
m_slot_map[++m_size] = slot;
}
inline
Slot * const & SlotMap::operator[](int n) const
{
return m_slot_map[n + 1];
}
inline
Slot * & SlotMap::operator[](int n)
{
return m_slot_map[n + 1];
}
} // namespace graphite2

213
thirdparty/graphite/src/inc/Segment.h vendored Normal file
View File

@@ -0,0 +1,213 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
#include "inc/Main.h"
#include <cassert>
#include "inc/CharInfo.h"
#include "inc/Face.h"
#include "inc/FeatureVal.h"
#include "inc/GlyphCache.h"
#include "inc/GlyphFace.h"
#include "inc/Slot.h"
#include "inc/Position.h"
#include "inc/List.h"
#include "inc/Collider.h"
#define MAX_SEG_GROWTH_FACTOR 64
namespace graphite2 {
typedef Vector<Features> FeatureList;
typedef Vector<Slot *> SlotRope;
typedef Vector<int16 *> AttributeRope;
typedef Vector<SlotJustify *> JustifyRope;
class Font;
class Segment;
class Silf;
enum SpliceParam {
/** sub-Segments longer than this are not cached
* (in Unicode code points) */
eMaxSpliceSize = 96
};
enum justFlags {
gr_justStartInline = 1,
gr_justEndInline = 2
};
class SegmentScopeState
{
private:
friend class Segment;
Slot * realFirstSlot;
Slot * slotBeforeScope;
Slot * slotAfterScope;
Slot * realLastSlot;
size_t numGlyphsOutsideScope;
};
class Segment
{
// Prevent copying of any kind.
Segment(const Segment&);
Segment& operator=(const Segment&);
public:
enum {
SEG_INITCOLLISIONS = 1,
SEG_HASCOLLISIONS = 2
};
size_t slotCount() const { return m_numGlyphs; } //one slot per glyph
void extendLength(ptrdiff_t num) { m_numGlyphs += num; }
Position advance() const { return m_advance; }
bool runGraphite() { if (m_silf) return m_face->runGraphite(this, m_silf); else return true;};
void chooseSilf(uint32 script) { m_silf = m_face->chooseSilf(script); }
const Silf *silf() const { return m_silf; }
size_t charInfoCount() const { return m_numCharinfo; }
const CharInfo *charinfo(unsigned int index) const { return index < m_numCharinfo ? m_charinfo + index : NULL; }
CharInfo *charinfo(unsigned int index) { return index < m_numCharinfo ? m_charinfo + index : NULL; }
Segment(size_t numchars, const Face* face, uint32 script, int dir);
~Segment();
uint8 flags() const { return m_flags; }
void flags(uint8 f) { m_flags = f; }
Slot *first() { return m_first; }
void first(Slot *p) { m_first = p; }
Slot *last() { return m_last; }
void last(Slot *p) { m_last = p; }
void appendSlot(int i, int cid, int gid, int fid, size_t coffset);
Slot *newSlot();
void freeSlot(Slot *);
SlotJustify *newJustify();
void freeJustify(SlotJustify *aJustify);
Position positionSlots(const Font *font=0, Slot *first=0, Slot *last=0, bool isRtl = false, bool isFinal = true);
void associateChars(int offset, size_t num);
void linkClusters(Slot *first, Slot *last);
uint16 getClassGlyph(uint16 cid, uint16 offset) const { return m_silf->getClassGlyph(cid, offset); }
uint16 findClassIndex(uint16 cid, uint16 gid) const { return m_silf->findClassIndex(cid, gid); }
int addFeatures(const Features& feats) { m_feats.push_back(feats); return int(m_feats.size()) - 1; }
uint32 getFeature(int index, uint8 findex) const { const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex); if (!pFR) return 0; else return pFR->getFeatureVal(m_feats[index]); }
void setFeature(int index, uint8 findex, uint32 val) {
const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex);
if (pFR)
{
if (val > pFR->maxVal()) val = pFR->maxVal();
pFR->applyValToFeature(val, m_feats[index]);
} }
int8 dir() const { return m_dir; }
void dir(int8 val) { m_dir = val; }
bool currdir() const { return ((m_dir >> 6) ^ m_dir) & 1; }
uint8 passBits() const { return m_passBits; }
void mergePassBits(const uint8 val) { m_passBits &= val; }
int16 glyphAttr(uint16 gid, uint16 gattr) const { const GlyphFace * p = m_face->glyphs().glyphSafe(gid); return p ? p->attrs()[gattr] : 0; }
int32 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel, bool rtl) const;
float glyphAdvance(uint16 gid) const { return m_face->glyphs().glyph(gid)->theAdvance().x; }
const Rect &theGlyphBBoxTemporary(uint16 gid) const { return m_face->glyphs().glyph(gid)->theBBox(); } //warning value may become invalid when another glyph is accessed
Slot *findRoot(Slot *is) const { return is->attachedTo() ? findRoot(is->attachedTo()) : is; }
int numAttrs() const { return m_silf->numUser(); }
int defaultOriginal() const { return m_defaultOriginal; }
const Face * getFace() const { return m_face; }
const Features & getFeatures(unsigned int /*charIndex*/) { assert(m_feats.size() == 1); return m_feats[0]; }
void bidiPass(int paradir, uint8 aMirror);
int8 getSlotBidiClass(Slot *s) const;
void doMirror(uint16 aMirror);
Slot *addLineEnd(Slot *nSlot);
void delLineEnd(Slot *s);
bool hasJustification() const { return m_justifies.size() != 0; }
void reverseSlots();
bool isWhitespace(const int cid) const;
bool hasCollisionInfo() const { return (m_flags & SEG_HASCOLLISIONS) && m_collisions; }
SlotCollision *collisionInfo(const Slot *s) const { return m_collisions ? m_collisions + s->index() : 0; }
CLASS_NEW_DELETE
public: //only used by: GrSegment* makeAndInitialize(const GrFont *font, const GrFace *face, uint32 script, const FeaturesHandle& pFeats/*must not be IsNull*/, encform enc, const void* pStart, size_t nChars, int dir);
bool read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void*pStart, size_t nChars);
void finalise(const Font *font, bool reverse=false);
float justify(Slot *pSlot, const Font *font, float width, enum justFlags flags, Slot *pFirst, Slot *pLast);
bool initCollisions();
private:
Position m_advance; // whole segment advance
SlotRope m_slots; // Vector of slot buffers
AttributeRope m_userAttrs; // Vector of userAttrs buffers
JustifyRope m_justifies; // Slot justification info buffers
FeatureList m_feats; // feature settings referenced by charinfos in this segment
Slot * m_freeSlots; // linked list of free slots
SlotJustify * m_freeJustifies; // Slot justification blocks free list
CharInfo * m_charinfo; // character info, one per input character
SlotCollision * m_collisions;
const Face * m_face; // GrFace
const Silf * m_silf;
Slot * m_first; // first slot in segment
Slot * m_last; // last slot in segment
size_t m_bufSize, // how big a buffer to create when need more slots
m_numGlyphs,
m_numCharinfo; // size of the array and number of input characters
int m_defaultOriginal; // number of whitespace chars in the string
int8 m_dir;
uint8 m_flags, // General purpose flags
m_passBits; // if bit set then skip pass
};
inline
int8 Segment::getSlotBidiClass(Slot *s) const
{
int8 res = s->getBidiClass();
if (res != -1) return res;
res = int8(glyphAttr(s->gid(), m_silf->aBidi()));
s->setBidiClass(res);
return res;
}
inline
void Segment::finalise(const Font *font, bool reverse)
{
if (!m_first || !m_last) return;
m_advance = positionSlots(font, m_first, m_last, m_silf->dir(), true);
//associateChars(0, m_numCharinfo);
if (reverse && currdir() != (m_dir & 1))
reverseSlots();
linkClusters(m_first, m_last);
}
inline
int32 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel, bool rtl) const {
if (attrLevel > 0)
{
Slot *is = findRoot(iSlot);
return is->clusterMetric(this, metric, attrLevel, rtl);
}
else
return m_face->getGlyphMetric(iSlot->gid(), metric);
}
inline
bool Segment::isWhitespace(const int cid) const
{
return ((cid >= 0x0009) * (cid <= 0x000D)
+ (cid == 0x0020)
+ (cid == 0x0085)
+ (cid == 0x00A0)
+ (cid == 0x1680)
+ (cid == 0x180E)
+ (cid >= 0x2000) * (cid <= 0x200A)
+ (cid == 0x2028)
+ (cid == 0x2029)
+ (cid == 0x202F)
+ (cid == 0x205F)
+ (cid == 0x3000)) != 0;
}
} // namespace graphite2
struct gr_segment : public graphite2::Segment {};

105
thirdparty/graphite/src/inc/Silf.h vendored Normal file
View File

@@ -0,0 +1,105 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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

147
thirdparty/graphite/src/inc/Slot.h vendored Normal file
View File

@@ -0,0 +1,147 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
#include "graphite2/Types.h"
#include "graphite2/Segment.h"
#include "inc/Main.h"
#include "inc/Font.h"
#include "inc/Position.h"
namespace graphite2 {
typedef gr_attrCode attrCode;
class GlyphFace;
class Segment;
struct SlotJustify
{
static const int NUMJUSTPARAMS = 5;
SlotJustify(const SlotJustify &);
SlotJustify & operator = (const SlotJustify &);
public:
static size_t size_of(size_t levels) { return sizeof(SlotJustify) + ((levels > 1 ? levels : 1)*NUMJUSTPARAMS - 1)*sizeof(int16); }
void LoadSlot(const Slot *s, const Segment *seg);
SlotJustify *next;
int16 values[1];
};
class Slot
{
enum Flag
{
DELETED = 1,
INSERTED = 2,
COPIED = 4,
POSITIONED = 8,
ATTACHED = 16
};
public:
struct iterator;
unsigned short gid() const { return m_glyphid; }
Position origin() const { return m_position; }
float advance() const { return m_advance.x; }
void advance(Position &val) { m_advance = val; }
Position advancePos() const { return m_advance; }
int before() const { return m_before; }
int after() const { return m_after; }
uint32 index() const { return m_index; }
void index(uint32 val) { m_index = val; }
Slot(int16 *m_userAttr = NULL);
void set(const Slot & slot, int charOffset, size_t numUserAttr, size_t justLevels, size_t numChars);
Slot *next() const { return m_next; }
void next(Slot *s) { m_next = s; }
Slot *prev() const { return m_prev; }
void prev(Slot *s) { m_prev = s; }
uint16 glyph() const { return m_realglyphid ? m_realglyphid : m_glyphid; }
void setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph = NULL);
void setRealGid(uint16 realGid) { m_realglyphid = realGid; }
void adjKern(const Position &pos) { m_shift = m_shift + pos; m_advance = m_advance + pos; }
void origin(const Position &pos) { m_position = pos + m_shift; }
void originate(int ind) { m_original = ind; }
int original() const { return m_original; }
void before(int ind) { m_before = ind; }
void after(int ind) { m_after = ind; }
bool isBase() const { return (!m_parent); }
void update(int numSlots, int numCharInfo, Position &relpos);
Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal, int depth = 0);
bool isDeleted() const { return (m_flags & DELETED) ? true : false; }
void markDeleted(bool state) { if (state) m_flags |= DELETED; else m_flags &= ~DELETED; }
bool isCopied() const { return (m_flags & COPIED) ? true : false; }
void markCopied(bool state) { if (state) m_flags |= COPIED; else m_flags &= ~COPIED; }
bool isPositioned() const { return (m_flags & POSITIONED) ? true : false; }
void markPositioned(bool state) { if (state) m_flags |= POSITIONED; else m_flags &= ~POSITIONED; }
bool isInsertBefore() const { return !(m_flags & INSERTED); }
uint8 getBidiLevel() const { return m_bidiLevel; }
void setBidiLevel(uint8 level) { m_bidiLevel = level; }
int8 getBidiClass(const Segment *seg);
int8 getBidiClass() const { return m_bidiCls; }
void setBidiClass(int8 cls) { m_bidiCls = cls; }
int16 *userAttrs() const { return m_userAttr; }
void userAttrs(int16 *p) { m_userAttr = p; }
void markInsertBefore(bool state) { if (!state) m_flags |= INSERTED; else m_flags &= ~INSERTED; }
void setAttr(Segment* seg, attrCode ind, uint8 subindex, int16 val, const SlotMap & map);
int getAttr(const Segment *seg, attrCode ind, uint8 subindex) const;
int getJustify(const Segment *seg, uint8 level, uint8 subindex) const;
void setJustify(Segment *seg, uint8 level, uint8 subindex, int16 value);
bool isLocalJustify() const { return m_justs != NULL; };
void attachTo(Slot *ap) { m_parent = ap; }
Slot *attachedTo() const { return m_parent; }
Position attachOffset() const { return m_attach - m_with; }
Slot* firstChild() const { return m_child; }
void firstChild(Slot *ap) { m_child = ap; }
bool child(Slot *ap);
Slot* nextSibling() const { return m_sibling; }
void nextSibling(Slot *ap) { m_sibling = ap; }
bool sibling(Slot *ap);
bool removeChild(Slot *ap);
int32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel, bool rtl);
void positionShift(Position a) { m_position += a; }
void floodShift(Position adj, int depth = 0);
float just() const { return m_just; }
void just(float j) { m_just = j; }
Slot *nextInCluster(const Slot *s) const;
bool isChildOf(const Slot *base) const;
CLASS_NEW_DELETE
private:
Slot *m_next; // linked list of slots
Slot *m_prev;
unsigned short m_glyphid; // glyph id
uint16 m_realglyphid;
uint32 m_original; // charinfo that originated this slot (e.g. for feature values)
uint32 m_before; // charinfo index of before association
uint32 m_after; // charinfo index of after association
uint32 m_index; // slot index given to this slot during finalising
Slot *m_parent; // index to parent we are attached to
Slot *m_child; // index to first child slot that attaches to us
Slot *m_sibling; // index to next child that attaches to our parent
Position m_position; // absolute position of glyph
Position m_shift; // .shift slot attribute
Position m_advance; // .advance slot attribute
Position m_attach; // attachment point on us
Position m_with; // attachment point position on parent
float m_just; // Justification inserted space
uint8 m_flags; // holds bit flags
byte m_attLevel; // attachment level
int8 m_bidiCls; // bidirectional class
byte m_bidiLevel; // bidirectional level
int16 *m_userAttr; // pointer to user attributes
SlotJustify *m_justs; // pointer to justification parameters
friend class Segment;
};
} // namespace graphite2
struct gr_slot : public graphite2::Slot {};

145
thirdparty/graphite/src/inc/Sparse.h vendored Normal file
View File

@@ -0,0 +1,145 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2011, SIL International, All rights reserved.
#pragma once
#include <iterator>
#include <utility>
#include "inc/Main.h"
namespace graphite2 {
// A read-only packed fast sparse array of uint16 with uint16 keys.
// Like most container classes this has capacity and size properties and these
// refer to the number of stored entries and the number of addressable entries
// as normal. However due the sparse nature the capacity is always <= than the
// size.
class sparse
{
public:
typedef uint16 key_type;
typedef uint16 mapped_type;
typedef std::pair<const key_type, mapped_type> value_type;
private:
typedef unsigned long mask_t;
static const unsigned char SIZEOF_CHUNK = (sizeof(mask_t) - sizeof(key_type))*8;
struct chunk
{
mask_t mask:SIZEOF_CHUNK;
key_type offset;
};
static const chunk empty_chunk;
sparse(const sparse &);
sparse & operator = (const sparse &);
public:
template<typename I>
sparse(I first, const I last);
sparse() throw();
~sparse() throw();
operator bool () const throw();
mapped_type operator [] (const key_type k) const throw();
size_t capacity() const throw();
size_t size() const throw();
size_t _sizeof() const throw();
CLASS_NEW_DELETE;
private:
union {
chunk * map;
mapped_type * values;
} m_array;
key_type m_nchunks;
};
inline
sparse::sparse() throw() : m_nchunks(0)
{
m_array.map = const_cast<graphite2::sparse::chunk *>(&empty_chunk);
}
template <typename I>
sparse::sparse(I attr, const I last)
: m_nchunks(0)
{
m_array.map = 0;
// Find the maximum extent of the key space.
size_t n_values=0;
long lastkey = -1;
for (I i = attr; i != last; ++i, ++n_values)
{
const typename std::iterator_traits<I>::value_type v = *i;
if (v.second == 0) { --n_values; continue; }
if (v.first <= lastkey) { m_nchunks = 0; return; }
lastkey = v.first;
const key_type k = v.first / SIZEOF_CHUNK;
if (k >= m_nchunks) m_nchunks = k+1;
}
if (m_nchunks == 0)
{
m_array.map=const_cast<graphite2::sparse::chunk *>(&empty_chunk);
return;
}
m_array.values = grzeroalloc<mapped_type>((m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)
/ sizeof(mapped_type)
+ n_values);
if (m_array.values == 0)
return;
// coverity[forward_null : FALSE] Since m_array is union and m_array.values is not NULL
chunk * ci = m_array.map;
ci->offset = (m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)/sizeof(mapped_type);
mapped_type * vi = m_array.values + ci->offset;
for (; attr != last; ++attr, ++vi)
{
const typename std::iterator_traits<I>::value_type v = *attr;
if (v.second == 0) { --vi; continue; }
chunk * const ci_ = m_array.map + v.first/SIZEOF_CHUNK;
if (ci != ci_)
{
ci = ci_;
ci->offset = key_type(vi - m_array.values);
}
ci->mask |= 1UL << (SIZEOF_CHUNK - 1 - (v.first % SIZEOF_CHUNK));
*vi = v.second;
}
}
inline
sparse::operator bool () const throw()
{
return m_array.map != 0;
}
inline
size_t sparse::size() const throw()
{
return m_nchunks*SIZEOF_CHUNK;
}
inline
size_t sparse::_sizeof() const throw()
{
return sizeof(sparse) + capacity()*sizeof(mapped_type) + m_nchunks*sizeof(chunk);
}
} // namespace graphite2

394
thirdparty/graphite/src/inc/TtfTypes.h vendored Normal file
View File

@@ -0,0 +1,394 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
/*
Responsibility: Tim Eves
Last reviewed: Not yet.
Description:
Provides types required to represent the TTF basic types.
*/
//**********************************************************************************************
// Include files
//**********************************************************************************************
namespace graphite2
{
namespace TtfUtil
{
//**********************************************************************************************
// Forward declarations
//**********************************************************************************************
//**********************************************************************************************
// Type declarations
//**********************************************************************************************
typedef unsigned char uint8;
typedef uint8 byte;
typedef signed char int8;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned int uint32;
typedef int int32;
typedef int16 short_frac;
typedef int32 fixed;
typedef int16 fword;
typedef uint16 ufword;
typedef int16 f2dot14;
typedef uint32 long_date_time[2];
//**********************************************************************************************
// Constants and enum types
//**********************************************************************************************/
enum
{
OneFix = 1<<16
};
//**********************************************************************************************
// Table declarations
//**********************************************************************************************
namespace Sfnt
{
#pragma pack(push,1) // We need this or the structure members aren't aligned
// correctly. Fortunately this form of pragma is supposed
// to be recognised by VS C++ too (at least according to
// MSDN).
struct OffsetSubTable
{
uint32 scaler_type;
uint16 num_tables,
search_range,
entry_selector,
range_shift;
struct Entry
{
uint32 tag,
checksum,
offset,
length;
} table_directory[1];
enum ScalerType
{
TrueTypeMac = 0x74727565U,
TrueTypeWin = 0x00010000U,
Type1 = 0x74797031U
};
};
struct CharacterCodeMap
{
uint16 version,
num_subtables;
struct
{
uint16 platform_id,
platform_specific_id;
uint32 offset;
} encoding[1];
};
struct CmapSubTable
{
uint16 format,
length,
language;
};
struct CmapSubTableFormat4 : CmapSubTable
{
uint16 seg_count_x2,
search_range,
entry_selector,
range_shift,
end_code[1];
// There are arrarys after this which need their
// start positions calculated since end_code is
// seg_count uint16s long.
};
struct CmapSubTableFormat12
{
fixed format;
uint32 length,
language,
num_groups;
struct
{
uint32 start_char_code,
end_char_code,
start_glyph_id;
} group[1];
};
struct FontHeader
{
fixed version,
font_revision;
uint32 check_sum_adjustment,
magic_number;
uint16 flags,
units_per_em;
long_date_time created,
modified;
fword x_min,
y_min,
x_max,
y_max;
uint16 mac_style,
lowest_rec_ppem;
int16 font_direction_hint,
index_to_loc_format,
glyph_data_format;
enum
{
MagicNumber = 0x5F0F3CF5,
GlypDataFormat = 0
};
enum {ShortIndexLocFormat, LongIndexLocFormat};
};
struct PostScriptGlyphName
{
fixed format,
italic_angle;
fword underline_position,
underline_thickness;
uint32 is_fixed_pitch,
min_mem_type42,
max_mem_type42,
min_mem_type1,
max_mem_type1;
enum
{
Format1 = 0x10000,
Format2 = 0x20000,
Format25 = 0x28000,
Format3 = 0x30000,
Format4 = 0x40000
};
};
struct PostScriptGlyphName2 : PostScriptGlyphName
{
uint16 number_of_glyphs,
glyph_name_index[1];
};
struct PostScriptGlyphName25 : PostScriptGlyphName
{
uint16 number_of_glyphs;
int8 offset[1];
};
struct PostScriptGlyphName3 : PostScriptGlyphName {};
struct PostScriptGlyphName4 : PostScriptGlyphName
{
uint16 glyph_to_char_map[1];
};
struct HorizontalHeader
{
fixed version;
fword ascent,
descent,
line_gap;
ufword advance_width_max;
fword min_left_side_bearing,
max_left_side_bearing,
x_max_element;
int16 caret_slope_rise,
caret_slope_run;
fword caret_offset;
int16 reserved[4],
metric_data_format;
uint16 num_long_hor_metrics;
};
struct MaximumProfile
{
fixed version;
uint16 num_glyphs,
max_points,
max_contours,
max_component_points,
max_component_contours,
max_zones,
max_twilight_points,
max_storage,
max_function_defs,
max_instruction_defs,
max_stack_elements,
max_size_of_instructions,
max_component_elements,
max_component_depth;
};
typedef byte Panose[10];
struct Compatibility0
{
uint16 version;
int16 x_avg_char_width;
uint16 weight_class,
width_class;
int16 fs_type,
y_subscript_x_size,
y_subscript_y_size,
y_subscript_x_offset,
y_subscript_y_offset,
y_superscript_x_size,
y_superscript_y_size,
y_superscript_x_offset,
y_superscript_y_offset,
y_strikeout_size,
y_strikeout_position,
family_class;
Panose panose;
uint32 unicode_range[4];
int8 ach_vend_id[4];
uint16 fs_selection,
fs_first_char_index,
fs_last_char_index, // Acording to Apple's spec this is where v0 should end
typo_ascender,
typo_descender,
type_linegap,
win_ascent,
win_descent;
enum
{
Italic =0x01,
Underscore=0x02,
Negative =0x04,
Outlined =0x08,
StrikeOut =0x10,
Bold =0x20
};
};
struct Compatibility1 : Compatibility0
{
uint32 codepage_range[2];
};
struct Compatibility2 : Compatibility1
{
int16 x_height,
cap_height;
uint16 default_char,
break_char,
max_context;
};
struct Compatibility3 : Compatibility2 {};
typedef Compatibility3 Compatibility;
struct NameRecord
{
uint16 platform_id,
platform_specific_id,
language_id,
name_id,
length,
offset;
enum {Unicode, Mactintosh, Reserved, Microsoft};
enum
{
Copyright, Family, Subfamily, UniqueSubfamily,
Fullname, Version, PostScript
};
};
struct LangTagRecord
{
uint16 length,
offset;
};
struct FontNames
{
uint16 format,
count,
string_offset;
NameRecord name_record[1];
};
struct HorizontalMetric
{
uint16 advance_width;
int16 left_side_bearing;
};
struct Glyph
{
int16 number_of_contours;
fword x_min,
y_min,
x_max,
y_max;
};
struct SimpleGlyph : Glyph
{
uint16 end_pts_of_contours[1];
enum
{
OnCurve = 0x01,
XShort = 0x02,
YShort = 0x04,
Repeat = 0x08,
XIsSame = 0x10,
XIsPos = 0x10,
YIsSame = 0x20,
YIsPos = 0x20
};
};
struct CompoundGlyph : Glyph
{
uint16 flags,
glyph_index;
enum
{
Arg1Arg2Words = 0x01,
ArgsAreXYValues = 0x02,
RoundXYToGrid = 0x04,
HaveScale = 0x08,
MoreComponents = 0x20,
HaveXAndYScale = 0x40,
HaveTwoByTwo = 0x80,
HaveInstructions = 0x100,
UseMyMetrics = 0x200,
OverlapCompund = 0x400,
ScaledOffset = 0x800,
UnscaledOffset = 0x1000
};
};
#pragma pack(pop)
} // end of namespace Sfnt
} // end of namespace TtfUtil
} // end of namespace graphite2

182
thirdparty/graphite/src/inc/TtfUtil.h vendored Normal file
View File

@@ -0,0 +1,182 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
/*
Responsibility: Alan Ward
Last reviewed: Not yet.
Description:
Utility class for handling TrueType font files.
*/
#pragma once
#include <cstddef>
namespace graphite2
{
namespace TtfUtil
{
#define OVERFLOW_OFFSET_CHECK(p, o) (o + reinterpret_cast<size_t>(p) < reinterpret_cast<size_t>(p))
typedef long fontTableId32;
typedef unsigned short gid16;
#define TTF_TAG(a,b,c,d) ((a << 24UL) + (b << 16UL) + (c << 8UL) + (d))
// Enumeration used to specify a table in a TTF file
class Tag
{
unsigned int _v;
public:
Tag(const char n[5]) throw() : _v(TTF_TAG(n[0],n[1],n[2],n[3])) {}
Tag(const unsigned int tag) throw() : _v(tag) {}
operator unsigned int () const throw () { return _v; }
enum
{
Feat = TTF_TAG('F','e','a','t'),
Glat = TTF_TAG('G','l','a','t'),
Gloc = TTF_TAG('G','l','o','c'),
Sile = TTF_TAG('S','i','l','e'),
Silf = TTF_TAG('S','i','l','f'),
Sill = TTF_TAG('S','i','l','l'),
cmap = TTF_TAG('c','m','a','p'),
cvt = TTF_TAG('c','v','t',' '),
cryp = TTF_TAG('c','r','y','p'),
head = TTF_TAG('h','e','a','d'),
fpgm = TTF_TAG('f','p','g','m'),
gdir = TTF_TAG('g','d','i','r'),
glyf = TTF_TAG('g','l','y','f'),
hdmx = TTF_TAG('h','d','m','x'),
hhea = TTF_TAG('h','h','e','a'),
hmtx = TTF_TAG('h','m','t','x'),
loca = TTF_TAG('l','o','c','a'),
kern = TTF_TAG('k','e','r','n'),
LTSH = TTF_TAG('L','T','S','H'),
maxp = TTF_TAG('m','a','x','p'),
name = TTF_TAG('n','a','m','e'),
OS_2 = TTF_TAG('O','S','/','2'),
post = TTF_TAG('p','o','s','t'),
prep = TTF_TAG('p','r','e','p')
};
};
/*----------------------------------------------------------------------------------------------
Class providing utility methods to parse a TrueType font file (TTF).
Callling application handles all file input and memory allocation.
Assumes minimal knowledge of TTF file format.
----------------------------------------------------------------------------------------------*/
////////////////////////////////// tools to find & check TTF tables
bool GetHeaderInfo(size_t & lOffset, size_t & lSize);
bool CheckHeader(const void * pHdr);
bool GetTableDirInfo(const void * pHdr, size_t & lOffset, size_t & lSize);
bool GetTableInfo(const Tag TableTag, const void * pHdr, const void * pTableDir,
size_t & lOffset, size_t & lSize);
bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize);
////////////////////////////////// simple font wide info
size_t GlyphCount(const void * pMaxp);
#ifdef ALL_TTFUTILS
size_t MaxCompositeComponentCount(const void * pMaxp);
size_t MaxCompositeLevelCount(const void * pMaxp);
size_t LocaGlyphCount(size_t lLocaSize, const void * pHead); // throw (std::domain_error);
#endif
int DesignUnits(const void * pHead);
#ifdef ALL_TTFUTILS
int HeadTableCheckSum(const void * pHead);
void HeadTableCreateTime(const void * pHead, unsigned int * pnDateBC, unsigned int * pnDateAD);
void HeadTableModifyTime(const void * pHead, unsigned int * pnDateBC, unsigned int * pnDateAD);
bool IsItalic(const void * pHead);
int FontAscent(const void * pOs2);
int FontDescent(const void * pOs2);
bool FontOs2Style(const void *pOs2, bool & fBold, bool & fItalic);
bool Get31EngFamilyInfo(const void * pName, size_t & lOffset, size_t & lSize);
bool Get31EngFullFontInfo(const void * pName, size_t & lOffset, size_t & lSize);
bool Get30EngFamilyInfo(const void * pName, size_t & lOffset, size_t & lSize);
bool Get30EngFullFontInfo(const void * pName, size_t & lOffset, size_t & lSize);
int PostLookup(const void * pPost, size_t lPostSize, const void * pMaxp,
const char * pPostName);
#endif
////////////////////////////////// utility methods helpful for name table
bool GetNameInfo(const void * pName, int nPlatformId, int nEncodingId,
int nLangId, int nNameId, size_t & lOffset, size_t & lSize);
//size_t NameTableLength(const byte * pTable);
#ifdef ALL_TTFUTILS
int GetLangsForNames(const void * pName, int nPlatformId, int nEncodingId,
int *nameIdList, int cNameIds, short *langIdList);
void SwapWString(void * pWStr, size_t nSize = 0); // throw (std::invalid_argument);
#endif
////////////////////////////////// cmap lookup tools
const void * FindCmapSubtable(const void * pCmap, int nPlatformId = 3,
int nEncodingId = 1, size_t length = 0);
bool CheckCmapSubtable4(const void * pCmap31, const void * pCmapEnd /*, unsigned int maxgid*/);
gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, int rangeKey = 0);
unsigned int CmapSubtable4NextCodepoint(const void *pCmap31, unsigned int nUnicodeId,
int * pRangeKey = 0);
bool CheckCmapSubtable12(const void *pCmap310, const void * pCmapEnd /*, unsigned int maxgid*/);
gid16 CmapSubtable12Lookup(const void * pCmap310, unsigned int uUnicodeId, int rangeKey = 0);
unsigned int CmapSubtable12NextCodepoint(const void *pCmap310, unsigned int nUnicodeId,
int * pRangeKey = 0);
///////////////////////////////// horizontal metric data for a glyph
bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize,
const void * pHhea, int & nLsb, unsigned int & nAdvWid);
////////////////////////////////// primitives for loca and glyf lookup
size_t LocaLookup(gid16 nGlyphId, const void * pLoca, size_t lLocaSize,
const void * pHead); // throw (std::out_of_range);
void * GlyfLookup(const void * pGlyf, size_t lGlyfOffset, size_t lTableLen);
////////////////////////////////// primitves for simple glyph data
bool GlyfBox(const void * pSimpleGlyf, int & xMin, int & yMin,
int & xMax, int & yMax);
#ifdef ALL_TTFUTILS
int GlyfContourCount(const void * pSimpleGlyf);
bool GlyfContourEndPoints(const void * pSimpleGlyf, int * prgnContourEndPoint,
int cnPointsTotal, size_t & cnPoints);
bool GlyfPoints(const void * pSimpleGlyf, int * prgnX, int * prgnY,
char * prgbFlag, int cnPointsTotal, int & cnPoints);
// primitive to find the glyph ids in a composite glyph
bool GetComponentGlyphIds(const void * pSimpleGlyf, int * prgnCompId,
size_t cnCompIdTotal, size_t & cnCompId);
// primitive to find the placement data for a component in a composite glyph
bool GetComponentPlacement(const void * pSimpleGlyf, int nCompId,
bool fOffset, int & a, int & b);
// primitive to find the transform data for a component in a composite glyph
bool GetComponentTransform(const void * pSimpleGlyf, int nCompId,
float & flt11, float & flt12, float & flt21, float & flt22, bool & fTransOffset);
#endif
////////////////////////////////// operate on composite or simple glyph (auto glyf lookup)
void * GlyfLookup(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
size_t lGlyfSize, size_t lLocaSize, const void * pHead); // primitive used by below methods
#ifdef ALL_TTFUTILS
// below are primary user methods for handling glyf data
bool IsSpace(gid16 nGlyphId, const void * pLoca, size_t lLocaSize, const void * pHead);
bool IsDeepComposite(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
size_t lGlyfSize, size_t lLocaSize, const void * pHead);
bool GlyfBox(gid16 nGlyphId, const void * pGlyf, const void * pLoca, size_t lGlyfSize, size_t lLocaSize,
const void * pHead, int & xMin, int & yMin, int & xMax, int & yMax);
bool GlyfContourCount(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
size_t lGlyfSize, size_t lLocaSize, const void *pHead, size_t & cnContours);
bool GlyfContourEndPoints(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
size_t lGlyfSize, size_t lLocaSize, const void * pHead, int * prgnContourEndPoint, size_t cnPoints);
bool GlyfPoints(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
size_t lGlyfSize, size_t lLocaSize, const void * pHead, const int * prgnContourEndPoint, size_t cnEndPoints,
int * prgnX, int * prgnY, bool * prgfOnCurve, size_t cnPoints);
// utitily method used by high-level GlyfPoints
bool SimplifyFlags(char * prgbFlags, int cnPoints);
bool CalcAbsolutePoints(int * prgnX, int * prgnY, int cnPoints);
#endif
} // end of namespace TtfUtil
} // end of namespace graphite2

228
thirdparty/graphite/src/inc/UtfCodec.h vendored Normal file
View File

@@ -0,0 +1,228 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2011, SIL International, All rights reserved.
#pragma once
#include <cstdlib>
#include "inc/Main.h"
namespace graphite2 {
typedef uint32 uchar_t;
template <int N>
struct _utf_codec
{
typedef uchar_t codeunit_t;
static void put(codeunit_t * cp, const uchar_t , int8 & len) throw();
static uchar_t get(const codeunit_t * cp, int8 & len) throw();
static bool validate(const codeunit_t * s, const codeunit_t * const e) throw();
};
template <>
struct _utf_codec<32>
{
private:
static const uchar_t limit = 0x110000;
public:
typedef uint32 codeunit_t;
inline
static void put(codeunit_t * cp, const uchar_t usv, int8 & l) throw()
{
*cp = usv; l = 1;
}
inline
static uchar_t get(const codeunit_t * cp, int8 & l) throw()
{
if (cp[0] < limit) { l = 1; return cp[0]; }
else { l = -1; return 0xFFFD; }
}
inline
static bool validate(const codeunit_t * s, const codeunit_t * const e) throw()
{
return s <= e;
}
};
template <>
struct _utf_codec<16>
{
private:
static const int32 lead_offset = 0xD800 - (0x10000 >> 10);
static const int32 surrogate_offset = 0x10000 - (0xD800 << 10) - 0xDC00;
public:
typedef uint16 codeunit_t;
inline
static void put(codeunit_t * cp, const uchar_t usv, int8 & l) throw()
{
if (usv < 0x10000) { l = 1; cp[0] = codeunit_t(usv); }
else
{
cp[0] = codeunit_t(lead_offset + (usv >> 10));
cp[1] = codeunit_t(0xDC00 + (usv & 0x3FF));
l = 2;
}
}
inline
static uchar_t get(const codeunit_t * cp, int8 & l) throw()
{
const uint32 uh = cp[0];
l = 1;
if (uh < 0xD800|| uh > 0xDFFF) { return uh; }
if (uh > 0xDBFF) { l = -1; return 0xFFFD; }
const uint32 ul = cp[1];
if (ul < 0xDC00 || ul > 0xDFFF) { l = -1; return 0xFFFD; }
++l;
return (uh<<10) + ul + surrogate_offset;
}
inline
static bool validate(const codeunit_t * s, const codeunit_t * const e) throw()
{
const ptrdiff_t n = e-s;
if (n <= 0) return n == 0;
const uint32 u = *(e-1); // Get the last codepoint
return (u < 0xD800 || u > 0xDBFF);
}
};
template <>
struct _utf_codec<8>
{
private:
static const int8 sz_lut[16];
static const byte mask_lut[5];
static const uchar_t limit = 0x110000;
public:
typedef uint8 codeunit_t;
inline
static void put(codeunit_t * cp, const uchar_t usv, int8 & l) throw()
{
if (usv < 0x80) {l = 1; cp[0] = usv; return; }
if (usv < 0x0800) {l = 2; cp[0] = 0xC0 + (usv >> 6); cp[1] = 0x80 + (usv & 0x3F); return; }
if (usv < 0x10000) {l = 3; cp[0] = 0xE0 + (usv >> 12); cp[1] = 0x80 + ((usv >> 6) & 0x3F); cp[2] = 0x80 + (usv & 0x3F); return; }
else {l = 4; cp[0] = 0xF0 + (usv >> 18); cp[1] = 0x80 + ((usv >> 12) & 0x3F); cp[2] = 0x80 + ((usv >> 6) & 0x3F); cp[3] = 0x80 + (usv & 0x3F); return; }
}
inline
static uchar_t get(const codeunit_t * cp, int8 & l) throw()
{
const int8 seq_sz = sz_lut[*cp >> 4];
uchar_t u = *cp & mask_lut[seq_sz];
l = 1;
bool toolong = false;
switch(seq_sz) {
case 4: u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong = (u < 0x10); GR_FALLTHROUGH;
// no break
case 3: u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x20); GR_FALLTHROUGH;
// no break
case 2: u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x80); GR_FALLTHROUGH;
// no break
case 1: break;
case 0: l = -1; return 0xFFFD;
}
if (l != seq_sz || toolong || u >= limit)
{
l = -l;
return 0xFFFD;
}
return u;
}
inline
static bool validate(const codeunit_t * s, const codeunit_t * const e) throw()
{
const ptrdiff_t n = e-s;
if (n <= 0) return n == 0;
s += (n-1);
if (*s < 0x80) return true;
if (*s >= 0xC0) return false;
if (n == 1) return true;
if (*--s < 0x80) return true;
if (*s >= 0xE0) return false;
if (n == 2 || *s >= 0xC0) return true;
if (*--s < 0x80) return true;
if (*s >= 0xF0) return false;
return true;
}
};
template <typename C>
class _utf_iterator
{
typedef _utf_codec<sizeof(C)*8> codec;
C * cp;
mutable int8 sl;
public:
typedef C codeunit_type;
typedef uchar_t value_type;
typedef uchar_t * pointer;
class reference
{
const _utf_iterator & _i;
reference(const _utf_iterator & i): _i(i) {}
public:
operator value_type () const throw () { return codec::get(_i.cp, _i.sl); }
reference & operator = (const value_type usv) throw() { codec::put(_i.cp, usv, _i.sl); return *this; }
friend class _utf_iterator;
};
_utf_iterator(const void * us=0) : cp(reinterpret_cast<C *>(const_cast<void *>(us))), sl(1) { }
_utf_iterator & operator ++ () { cp += abs(sl); return *this; }
_utf_iterator operator ++ (int) { _utf_iterator tmp(*this); operator++(); return tmp; }
bool operator == (const _utf_iterator & rhs) const throw() { return cp >= rhs.cp; }
bool operator != (const _utf_iterator & rhs) const throw() { return !operator==(rhs); }
reference operator * () const throw() { return *this; }
pointer operator ->() const throw() { return &operator *(); }
operator codeunit_type * () const throw() { return cp; }
bool error() const throw() { return sl < 1; }
bool validate(const _utf_iterator & e) { return codec::validate(cp, e.cp); }
};
template <typename C>
struct utf
{
typedef typename _utf_codec<sizeof(C)*8>::codeunit_t codeunit_t;
typedef _utf_iterator<C> iterator;
typedef _utf_iterator<const C> const_iterator;
inline
static bool validate(codeunit_t * s, codeunit_t * e) throw() {
return _utf_codec<sizeof(C)*8>::validate(s,e);
}
};
typedef utf<uint32> utf32;
typedef utf<uint16> utf16;
typedef utf<uint8> utf8;
} // namespace graphite2

127
thirdparty/graphite/src/inc/bits.h vendored Normal file
View File

@@ -0,0 +1,127 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2012, SIL International, All rights reserved.
#pragma once
namespace graphite2
{
#if defined GRAPHITE2_BUILTINS && (defined __GNUC__ || defined __clang__)
template<typename T>
inline unsigned int bit_set_count(T v)
{
return __builtin_popcount(v);
}
template<>
inline unsigned int bit_set_count(int16 v)
{
return __builtin_popcount(static_cast<uint16>(v));
}
template<>
inline unsigned int bit_set_count(int8 v)
{
return __builtin_popcount(static_cast<uint8>(v));
}
template<>
inline unsigned int bit_set_count(unsigned long v)
{
return __builtin_popcountl(v);
}
template<>
inline unsigned int bit_set_count(signed long v)
{
return __builtin_popcountl(v);
}
template<>
inline unsigned int bit_set_count(unsigned long long v)
{
return __builtin_popcountll(v);
}
template<>
inline unsigned int bit_set_count(signed long long v)
{
return __builtin_popcountll(v);
}
#else
template<typename T>
inline unsigned int bit_set_count(T v)
{
static size_t const ONES = ~0;
v = v - ((v >> 1) & T(ONES/3)); // temp
v = (v & T(ONES/15*3)) + ((v >> 2) & T(ONES/15*3)); // temp
v = (v + (v >> 4)) & T(ONES/255*15); // temp
return (T)(v * T(ONES/255)) >> (sizeof(T)-1)*8; // count
}
#endif
//TODO: Changed these to uintmax_t when we go to C++11
template<int S>
inline size_t _mask_over_val(size_t v)
{
v = _mask_over_val<S/2>(v);
v |= v >> S*4;
return v;
}
//TODO: Changed these to uintmax_t when we go to C++11
template<>
inline size_t _mask_over_val<1>(size_t v)
{
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
return v;
}
template<typename T>
inline T mask_over_val(T v)
{
return T(_mask_over_val<sizeof(T)>(v));
}
template<typename T>
inline unsigned long next_highest_power2(T v)
{
return _mask_over_val<sizeof(T)>(v-1)+1;
}
template<typename T>
inline unsigned int log_binary(T v)
{
return bit_set_count(mask_over_val(v))-1;
}
template<typename T>
inline T has_zero(const T x)
{
return (x - T(~T(0)/255)) & ~x & T(~T(0)/255*128);
}
template<typename T>
inline T zero_bytes(const T x, unsigned char n)
{
const T t = T(~T(0)/255*n);
return T((has_zero(x^t) >> 7)*n);
}
#if 0
inline float float_round(float x, uint32 m)
{
*reinterpret_cast<unsigned int *>(&x) &= m;
return *reinterpret_cast<float *>(&x);
}
#endif
}

66
thirdparty/graphite/src/inc/debug.h vendored Normal file
View File

@@ -0,0 +1,66 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2011, SIL International, All rights reserved.
// 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

155
thirdparty/graphite/src/inc/json.h vendored Normal file
View File

@@ -0,0 +1,155 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2011, SIL International, All rights reserved.
// JSON pretty printer for graphite font debug output logging.
// Created on: 15 Dec 2011
// Author: Tim Eves
#pragma once
#include "inc/Main.h"
#include <cassert>
#include <cstdio>
#include <cstdint>
#include "inc/List.h"
namespace graphite2 {
class json
{
// Prevent copying
json(const json &);
json & operator = (const json &);
typedef void (*_context_t)(json &);
FILE * const _stream;
char _contexts[128], // context stack
* _context, // current context (top of stack)
* _flatten; // if !0 points to context above which
// pretty printed output should occur.
Vector<void *> _env;
void context(const char current) throw();
void indent(const int d=0) throw();
void push_context(const char, const char) throw();
void pop_context() throw();
public:
class closer;
using string = const char *;
using number = double;
enum class integer : std::intmax_t {};
enum class integer_u : std::uintmax_t {};
using boolean = bool;
static const std::nullptr_t null;
void setenv(unsigned int index, void *val) { _env.reserve(index + 1); if (index >= _env.size()) _env.insert(_env.end(), _env.size() - index + 1, 0); _env[index] = val; }
void *getenv(unsigned int index) const { return _env[index]; }
const Vector<void *> &getenvs() const { return _env; }
static void flat(json &) throw();
static void close(json &) throw();
static void object(json &) throw();
static void array(json &) throw();
static void item(json &) throw();
json(FILE * stream) throw();
~json() throw ();
FILE * stream() const throw();
json & operator << (string) throw();
json & operator << (number) throw();
json & operator << (integer) throw();
json & operator << (integer_u) throw();
json & operator << (boolean) throw();
json & operator << (std::nullptr_t) throw();
json & operator << (_context_t) throw();
operator bool() const throw();
bool good() const throw();
bool eof() const throw();
CLASS_NEW_DELETE;
};
class json::closer
{
// Prevent copying.
closer(const closer &);
closer & operator = (const closer &);
json * const _j;
public:
closer(json * const j) : _j(j) {}
~closer() throw() { if (_j) *_j << close; }
};
inline
json::json(FILE * s) throw()
: _stream(s), _context(_contexts), _flatten(0)
{
if (good())
fflush(s);
}
inline
json::~json() throw ()
{
while (_context > _contexts) pop_context();
}
inline
FILE * json::stream() const throw() { return _stream; }
inline
json & json::operator << (json::_context_t ctxt) throw()
{
ctxt(*this);
return *this;
}
inline
json & operator << (json & j, signed char d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, unsigned char d) throw() { return j << json::integer_u(d); }
inline
json & operator << (json & j, short int d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, unsigned short int d) throw() { return j << json::integer_u(d); }
inline
json & operator << (json & j, int d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, unsigned int d) throw() { return j << json::integer_u(d); }
inline
json & operator << (json & j, long int d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, unsigned long int d) throw() { return j << json::integer_u(d); }
inline
json & operator << (json & j, long long int d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, unsigned long long int d) throw() { return j << json::integer_u(d); }
inline
json::operator bool() const throw() { return good(); }
inline
bool json::good() const throw() { return _stream && ferror(_stream) == 0; }
inline
bool json::eof() const throw() { return feof(_stream) != 0; }
} // namespace graphite2

View File

@@ -0,0 +1,427 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#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

View File

@@ -0,0 +1,101 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
// This file will be pulled into and integrated into a machine implmentation
// DO NOT build directly
#pragma once
#define do2(n) do_(n) ,do_(n)
#define NILOP 0U
// types or parameters are: (.. is inclusive)
// number - any byte
// output_class - 0 .. silf.m_nClass
// input_class - 0 .. silf.m_nClass
// sattrnum - 0 .. 29 (gr_slatJWidth) , 55 (gr_slatUserDefn)
// attrid - 0 .. silf.numUser() where sattrnum == 55; 0..silf.m_iMaxComp where sattrnum == 15 otherwise 0
// gattrnum - 0 .. face->getGlyphFaceCache->numAttrs()
// gmetric - 0 .. 11 (kgmetDescent)
// featidx - 0 .. face.numFeatures()
// level - any byte
static const opcode_t opcode_table[] =
{
{{do2(nop)}, 0, "NOP"},
{{do2(push_byte)}, 1, "PUSH_BYTE"}, // number
{{do2(push_byte_u)}, 1, "PUSH_BYTE_U"}, // number
{{do2(push_short)}, 2, "PUSH_SHORT"}, // number number
{{do2(push_short_u)}, 2, "PUSH_SHORT_U"}, // number number
{{do2(push_long)}, 4, "PUSH_LONG"}, // number number number number
{{do2(add)}, 0, "ADD"},
{{do2(sub)}, 0, "SUB"},
{{do2(mul)}, 0, "MUL"},
{{do2(div_)}, 0, "DIV"},
{{do2(min_)}, 0, "MIN"},
{{do2(max_)}, 0, "MAX"},
{{do2(neg)}, 0, "NEG"},
{{do2(trunc8)}, 0, "TRUNC8"},
{{do2(trunc16)}, 0, "TRUNC16"},
{{do2(cond)}, 0, "COND"},
{{do2(and_)}, 0, "AND"}, // 0x10
{{do2(or_)}, 0, "OR"},
{{do2(not_)}, 0, "NOT"},
{{do2(equal)}, 0, "EQUAL"},
{{do2(not_eq_)}, 0, "NOT_EQ"},
{{do2(less)}, 0, "LESS"},
{{do2(gtr)}, 0, "GTR"},
{{do2(less_eq)}, 0, "LESS_EQ"},
{{do2(gtr_eq)}, 0, "GTR_EQ"}, // 0x18
{{do_(next), NILOP}, 0, "NEXT"},
{{NILOP, NILOP}, 1, "NEXT_N"}, // number <= smap.end - map
{{do_(next), NILOP}, 0, "COPY_NEXT"},
{{do_(put_glyph_8bit_obs), NILOP}, 1, "PUT_GLYPH_8BIT_OBS"}, // output_class
{{do_(put_subs_8bit_obs), NILOP}, 3, "PUT_SUBS_8BIT_OBS"}, // slot input_class output_class
{{do_(put_copy), NILOP}, 1, "PUT_COPY"}, // slot
{{do_(insert), NILOP}, 0, "INSERT"},
{{do_(delete_), NILOP}, 0, "DELETE"}, // 0x20
{{do_(assoc), NILOP}, VARARGS, "ASSOC"},
{{NILOP ,do_(cntxt_item)}, 2, "CNTXT_ITEM"}, // slot offset
{{do_(attr_set), NILOP}, 1, "ATTR_SET"}, // sattrnum
{{do_(attr_add), NILOP}, 1, "ATTR_ADD"}, // sattrnum
{{do_(attr_sub), NILOP}, 1, "ATTR_SUB"}, // sattrnum
{{do_(attr_set_slot), NILOP}, 1, "ATTR_SET_SLOT"}, // sattrnum
{{do_(iattr_set_slot), NILOP}, 2, "IATTR_SET_SLOT"}, // sattrnum attrid
{{do2(push_slot_attr)}, 2, "PUSH_SLOT_ATTR"}, // sattrnum slot
{{do2(push_glyph_attr_obs)}, 2, "PUSH_GLYPH_ATTR_OBS"}, // gattrnum slot
{{do2(push_glyph_metric)}, 3, "PUSH_GLYPH_METRIC"}, // gmetric slot level
{{do2(push_feat)}, 2, "PUSH_FEAT"}, // featidx slot
{{do2(push_att_to_gattr_obs)}, 2, "PUSH_ATT_TO_GATTR_OBS"}, // gattrnum slot
{{do2(push_att_to_glyph_metric)}, 3, "PUSH_ATT_TO_GLYPH_METRIC"}, // gmetric slot level
{{do2(push_islot_attr)}, 3, "PUSH_ISLOT_ATTR"}, // sattrnum slot attrid
{{NILOP,NILOP}, 3, "PUSH_IGLYPH_ATTR"},
{{do2(pop_ret)}, 0, "POP_RET"}, // 0x30
{{do2(ret_zero)}, 0, "RET_ZERO"},
{{do2(ret_true)}, 0, "RET_TRUE"},
{{do_(iattr_set), NILOP}, 2, "IATTR_SET"}, // sattrnum attrid
{{do_(iattr_add), NILOP}, 2, "IATTR_ADD"}, // sattrnum attrid
{{do_(iattr_sub), NILOP}, 2, "IATTR_SUB"}, // sattrnum attrid
{{do2(push_proc_state)}, 1, "PUSH_PROC_STATE"}, // dummy
{{do2(push_version)}, 0, "PUSH_VERSION"},
{{do_(put_subs), NILOP}, 5, "PUT_SUBS"}, // slot input_class input_class output_class output_class
{{NILOP,NILOP}, 0, "PUT_SUBS2"},
{{NILOP,NILOP}, 0, "PUT_SUBS3"},
{{do_(put_glyph), NILOP}, 2, "PUT_GLYPH"}, // output_class output_class
{{do2(push_glyph_attr)}, 3, "PUSH_GLYPH_ATTR"}, // gattrnum gattrnum slot
{{do2(push_att_to_glyph_attr)}, 3, "PUSH_ATT_TO_GLYPH_ATTR"}, // gattrnum gattrnum slot
{{do2(bor)}, 0, "BITOR"},
{{do2(band)}, 0, "BITAND"},
{{do2(bnot)}, 0, "BITNOT"}, // 0x40
{{do2(setbits)}, 4, "BITSET"},
{{do_(set_feat), NILOP}, 2, "SET_FEAT"}, // featidx slot
// private opcodes for internal use only, comes after all other on disk opcodes.
{{do_(temp_copy), NILOP}, 0, "TEMP_COPY"}
};

668
thirdparty/graphite/src/inc/opcodes.h vendored Normal file
View File

@@ -0,0 +1,668 @@
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
// This file will be pulled into and integrated into a machine implmentation
// DO NOT build directly and under no circumstances ever #include headers in
// here or you will break the direct_machine.
//
// Implementers' notes
// ==================
// You have access to a few primitives and the full C++ code:
// declare_params(n) Tells the interpreter how many bytes of parameter
// space to claim for this instruction uses and
// initialises the param pointer. You *must* before the
// first use of param.
// use_params(n) Claim n extra bytes of param space beyond what was
// claimed using delcare_param.
// param A const byte pointer for the parameter space claimed by
// this instruction.
// binop(op) Implement a binary operation on the stack using the
// specified C++ operator.
// NOT_IMPLEMENTED Any instruction body containing this will exit the
// program with an assertion error. Instructions that are
// not implemented should also be marked NILOP in the
// opcodes tables this will cause the code class to spot
// them in a live code stream and throw a runtime_error
// instead.
// push(n) Push the value n onto the stack.
// pop() Pop the top most value and return it.
//
// You have access to the following named fast 'registers':
// sp = The pointer to the current top of stack, the last value
// pushed.
// seg = A reference to the Segment this code is running over.
// is = The current slot index
// isb = The original base slot index at the start of this rule
// isf = The first positioned slot
// isl = The last positioned slot
// ip = The current instruction pointer
// endPos = Position of advance of last cluster
// dir = writing system directionality of the font
// #define NOT_IMPLEMENTED assert(false)
// #define NOT_IMPLEMENTED
#define binop(op) const uint32 a = pop(); *sp = uint32(*sp) op a
#define sbinop(op) const int32 a = pop(); *sp = int32(*sp) op a
#define use_params(n) dp += n
#define declare_params(n) const byte * param = dp; \
use_params(n);
#define push(n) { *++sp = n; }
#define pop() (*sp--)
#define slotat(x) (map[(x)])
#define DIE { is=seg.last(); status = Machine::died_early; EXIT(1); }
#define POSITIONED 1
STARTOP(nop)
do {} while (0);
ENDOP
STARTOP(push_byte)
declare_params(1);
push(int8(*param));
ENDOP
STARTOP(push_byte_u)
declare_params(1);
push(uint8(*param));
ENDOP
STARTOP(push_short)
declare_params(2);
const int16 r = int16(param[0]) << 8
| uint8(param[1]);
push(r);
ENDOP
STARTOP(push_short_u)
declare_params(2);
const uint16 r = uint16(param[0]) << 8
| uint8(param[1]);
push(r);
ENDOP
STARTOP(push_long)
declare_params(4);
const int32 r = int32(param[0]) << 24
| uint32(param[1]) << 16
| uint32(param[2]) << 8
| uint8(param[3]);
push(r);
ENDOP
STARTOP(add)
binop(+);
ENDOP
STARTOP(sub)
binop(-);
ENDOP
STARTOP(mul)
binop(*);
ENDOP
STARTOP(div_)
const int32 b = pop();
const int32 a = int32(*sp);
if (b == 0 || (a == std::numeric_limits<int32>::min() && b == -1)) DIE;
*sp = int32(*sp) / b;
ENDOP
STARTOP(min_)
const int32 a = pop(), b = *sp;
if (a < b) *sp = a;
ENDOP
STARTOP(max_)
const int32 a = pop(), b = *sp;
if (a > b) *sp = a;
ENDOP
STARTOP(neg)
*sp = uint32(-int32(*sp));
ENDOP
STARTOP(trunc8)
*sp = uint8(*sp);
ENDOP
STARTOP(trunc16)
*sp = uint16(*sp);
ENDOP
STARTOP(cond)
const uint32 f = pop(), t = pop(), c = pop();
push(c ? t : f);
ENDOP
STARTOP(and_)
binop(&&);
ENDOP
STARTOP(or_)
binop(||);
ENDOP
STARTOP(not_)
*sp = !*sp;
ENDOP
STARTOP(equal)
binop(==);
ENDOP
STARTOP(not_eq_)
binop(!=);
ENDOP
STARTOP(less)
sbinop(<);
ENDOP
STARTOP(gtr)
sbinop(>);
ENDOP
STARTOP(less_eq)
sbinop(<=);
ENDOP
STARTOP(gtr_eq)
sbinop(>=);
ENDOP
STARTOP(next)
if (map - &smap[0] >= int(smap.size())) DIE
if (is)
{
if (is == smap.highwater())
smap.highpassed(true);
is = is->next();
}
++map;
ENDOP
//STARTOP(next_n)
// use_params(1);
// NOT_IMPLEMENTED;
//declare_params(1);
//const size_t num = uint8(*param);
//ENDOP
//STARTOP(copy_next)
// if (is) is = is->next();
// ++map;
// ENDOP
STARTOP(put_glyph_8bit_obs)
declare_params(1);
const unsigned int output_class = uint8(*param);
is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
ENDOP
STARTOP(put_subs_8bit_obs)
declare_params(3);
const int slot_ref = int8(param[0]);
const unsigned int input_class = uint8(param[1]),
output_class = uint8(param[2]);
uint16 index;
slotref slot = slotat(slot_ref);
if (slot)
{
index = seg.findClassIndex(input_class, slot->gid());
is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
}
ENDOP
STARTOP(put_copy)
declare_params(1);
const int slot_ref = int8(*param);
if (is && !is->isDeleted())
{
slotref ref = slotat(slot_ref);
if (ref && ref != is)
{
int16 *tempUserAttrs = is->userAttrs();
if (is->attachedTo() || is->firstChild()) DIE
Slot *prev = is->prev();
Slot *next = is->next();
memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16));
memcpy(is, ref, sizeof(Slot));
is->firstChild(NULL);
is->nextSibling(NULL);
is->userAttrs(tempUserAttrs);
is->next(next);
is->prev(prev);
if (is->attachedTo())
is->attachedTo()->child(is);
}
is->markCopied(false);
is->markDeleted(false);
}
ENDOP
STARTOP(insert)
if (smap.decMax() <= 0) DIE;
Slot *newSlot = seg.newSlot();
if (!newSlot) DIE;
Slot *iss = is;
while (iss && iss->isDeleted()) iss = iss->next();
if (!iss)
{
if (seg.last())
{
seg.last()->next(newSlot);
newSlot->prev(seg.last());
newSlot->before(seg.last()->before());
seg.last(newSlot);
}
else
{
seg.first(newSlot);
seg.last(newSlot);
}
}
else if (iss->prev())
{
iss->prev()->next(newSlot);
newSlot->prev(iss->prev());
newSlot->before(iss->prev()->after());
}
else
{
newSlot->prev(NULL);
newSlot->before(iss->before());
seg.first(newSlot);
}
newSlot->next(iss);
if (iss)
{
iss->prev(newSlot);
newSlot->originate(iss->original());
newSlot->after(iss->before());
}
else if (newSlot->prev())
{
newSlot->originate(newSlot->prev()->original());
newSlot->after(newSlot->prev()->after());
}
else
{
newSlot->originate(seg.defaultOriginal());
}
if (is == smap.highwater())
smap.highpassed(false);
is = newSlot;
seg.extendLength(1);
if (map != &smap[-1])
--map;
ENDOP
STARTOP(delete_)
if (!is || is->isDeleted()) DIE
is->markDeleted(true);
if (is->prev())
is->prev()->next(is->next());
else
seg.first(is->next());
if (is->next())
is->next()->prev(is->prev());
else
seg.last(is->prev());
if (is == smap.highwater())
smap.highwater(is->next());
if (is->prev())
is = is->prev();
seg.extendLength(-1);
ENDOP
STARTOP(assoc)
declare_params(1);
unsigned int num = uint8(*param);
const int8 * assocs = reinterpret_cast<const int8 *>(param+1);
use_params(num);
int max = -1;
int min = -1;
while (num-- > 0)
{
int sr = *assocs++;
slotref ts = slotat(sr);
if (ts && (min == -1 || ts->before() < min)) min = ts->before();
if (ts && ts->after() > max) max = ts->after();
}
if (min > -1) // implies max > -1
{
is->before(min);
is->after(max);
}
ENDOP
STARTOP(cntxt_item)
// It turns out this is a cunningly disguised condition forward jump.
declare_params(3);
const int is_arg = int8(param[0]);
const size_t iskip = uint8(param[1]),
dskip = uint8(param[2]);
if (mapb + is_arg != map)
{
ip += iskip;
dp += dskip;
push(true);
}
ENDOP
STARTOP(attr_set)
declare_params(1);
const attrCode slat = attrCode(uint8(*param));
const int val = pop();
is->setAttr(&seg, slat, 0, val, smap);
ENDOP
STARTOP(attr_add)
declare_params(1);
const attrCode slat = attrCode(uint8(*param));
const uint32_t val = pop();
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
is->setAttr(&seg, slat, 0, int32_t(val + res), smap);
ENDOP
STARTOP(attr_sub)
declare_params(1);
const attrCode slat = attrCode(uint8(*param));
const uint32_t val = pop();
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
is->setAttr(&seg, slat, 0, int32_t(res - val), smap);
ENDOP
STARTOP(attr_set_slot)
declare_params(1);
const attrCode slat = attrCode(uint8(*param));
const int offset = int(map - smap.begin())*int(slat == gr_slatAttTo);
const int val = pop() + offset;
is->setAttr(&seg, slat, offset, val, smap);
ENDOP
STARTOP(iattr_set_slot)
declare_params(2);
const attrCode slat = attrCode(uint8(param[0]));
const uint8 idx = uint8(param[1]);
const int val = int(pop() + (map - smap.begin())*int(slat == gr_slatAttTo));
is->setAttr(&seg, slat, idx, val, smap);
ENDOP
STARTOP(push_slot_attr)
declare_params(2);
const attrCode slat = attrCode(uint8(param[0]));
const int slot_ref = int8(param[1]);
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
slotref slot = slotat(slot_ref);
if (slot)
{
int res = slot->getAttr(&seg, slat, 0);
push(res);
}
ENDOP
STARTOP(push_glyph_attr_obs)
declare_params(2);
const unsigned int glyph_attr = uint8(param[0]);
const int slot_ref = int8(param[1]);
slotref slot = slotat(slot_ref);
if (slot)
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
ENDOP
STARTOP(push_glyph_metric)
declare_params(3);
const unsigned int glyph_attr = uint8(param[0]);
const int slot_ref = int8(param[1]);
const signed int attr_level = uint8(param[2]);
slotref slot = slotat(slot_ref);
if (slot)
push(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir));
ENDOP
STARTOP(push_feat)
declare_params(2);
const unsigned int feat = uint8(param[0]);
const int slot_ref = int8(param[1]);
slotref slot = slotat(slot_ref);
if (slot)
{
uint8 fid = seg.charinfo(slot->original())->fid();
push(seg.getFeature(fid, feat));
}
ENDOP
STARTOP(push_att_to_gattr_obs)
declare_params(2);
const unsigned int glyph_attr = uint8(param[0]);
const int slot_ref = int8(param[1]);
slotref slot = slotat(slot_ref);
if (slot)
{
slotref att = slot->attachedTo();
if (att) slot = att;
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
}
ENDOP
STARTOP(push_att_to_glyph_metric)
declare_params(3);
const unsigned int glyph_attr = uint8(param[0]);
const int slot_ref = int8(param[1]);
const signed int attr_level = uint8(param[2]);
slotref slot = slotat(slot_ref);
if (slot)
{
slotref att = slot->attachedTo();
if (att) slot = att;
push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir)));
}
ENDOP
STARTOP(push_islot_attr)
declare_params(3);
const attrCode slat = attrCode(uint8(param[0]));
const int slot_ref = int8(param[1]),
idx = uint8(param[2]);
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
slotref slot = slotat(slot_ref);
if (slot)
{
int res = slot->getAttr(&seg, slat, idx);
push(res);
}
ENDOP
#if 0
STARTOP(push_iglyph_attr) // not implemented
NOT_IMPLEMENTED;
ENDOP
#endif
STARTOP(pop_ret)
const uint32 ret = pop();
EXIT(ret);
ENDOP
STARTOP(ret_zero)
EXIT(0);
ENDOP
STARTOP(ret_true)
EXIT(1);
ENDOP
STARTOP(iattr_set)
declare_params(2);
const attrCode slat = attrCode(uint8(param[0]));
const uint8 idx = uint8(param[1]);
const int val = pop();
is->setAttr(&seg, slat, idx, val, smap);
ENDOP
STARTOP(iattr_add)
declare_params(2);
const attrCode slat = attrCode(uint8(param[0]));
const uint8 idx = uint8(param[1]);
const uint32_t val = pop();
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
is->setAttr(&seg, slat, idx, int32_t(val + res), smap);
ENDOP
STARTOP(iattr_sub)
declare_params(2);
const attrCode slat = attrCode(uint8(param[0]));
const uint8 idx = uint8(param[1]);
const uint32_t val = pop();
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
is->setAttr(&seg, slat, idx, int32_t(res - val), smap);
ENDOP
STARTOP(push_proc_state)
use_params(1);
push(1);
ENDOP
STARTOP(push_version)
push(0x00030000);
ENDOP
STARTOP(put_subs)
declare_params(5);
const int slot_ref = int8(param[0]);
const unsigned int input_class = uint8(param[1]) << 8
| uint8(param[2]);
const unsigned int output_class = uint8(param[3]) << 8
| uint8(param[4]);
slotref slot = slotat(slot_ref);
if (slot)
{
int index = seg.findClassIndex(input_class, slot->gid());
is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
}
ENDOP
#if 0
STARTOP(put_subs2) // not implemented
NOT_IMPLEMENTED;
ENDOP
STARTOP(put_subs3) // not implemented
NOT_IMPLEMENTED;
ENDOP
#endif
STARTOP(put_glyph)
declare_params(2);
const unsigned int output_class = uint8(param[0]) << 8
| uint8(param[1]);
is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
ENDOP
STARTOP(push_glyph_attr)
declare_params(3);
const unsigned int glyph_attr = uint8(param[0]) << 8
| uint8(param[1]);
const int slot_ref = int8(param[2]);
slotref slot = slotat(slot_ref);
if (slot)
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
ENDOP
STARTOP(push_att_to_glyph_attr)
declare_params(3);
const unsigned int glyph_attr = uint8(param[0]) << 8
| uint8(param[1]);
const int slot_ref = int8(param[2]);
slotref slot = slotat(slot_ref);
if (slot)
{
slotref att = slot->attachedTo();
if (att) slot = att;
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
}
ENDOP
STARTOP(temp_copy)
slotref newSlot = seg.newSlot();
if (!newSlot || !is) DIE;
int16 *tempUserAttrs = newSlot->userAttrs();
memcpy(newSlot, is, sizeof(Slot));
memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16));
newSlot->userAttrs(tempUserAttrs);
newSlot->markCopied(true);
*map = newSlot;
ENDOP
STARTOP(band)
binop(&);
ENDOP
STARTOP(bor)
binop(|);
ENDOP
STARTOP(bnot)
*sp = ~*sp;
ENDOP
STARTOP(setbits)
declare_params(4);
const uint16 m = uint16(param[0]) << 8
| uint8(param[1]);
const uint16 v = uint16(param[2]) << 8
| uint8(param[3]);
*sp = ((*sp) & ~m) | v;
ENDOP
STARTOP(set_feat)
declare_params(2);
const unsigned int feat = uint8(param[0]);
const int slot_ref = int8(param[1]);
slotref slot = slotat(slot_ref);
if (slot)
{
uint8 fid = seg.charinfo(slot->original())->fid();
seg.setFeature(fid, feat, pop());
}
ENDOP