зеркало из https://github.com/mozilla/gecko-dev.git
bug 876069 - update graphite2 library to release 1.2.2. r=jdaggett
This commit is contained in:
Родитель
3a7fe9a2b2
Коммит
7d0ec4d98e
|
@ -1,6 +1,6 @@
|
|||
This directory contains the Graphite2 library from http://hg.palaso.org/graphitedev
|
||||
|
||||
Current version derived from upstream changeset 51e72e74b9a6
|
||||
Current version derived from upstream changeset 09707dd22634
|
||||
|
||||
See gfx/graphite2/moz-gr-update.sh for update procedure.
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#define GR2_VERSION_MAJOR 1
|
||||
#define GR2_VERSION_MINOR 2
|
||||
#define GR2_VERSION_BUGFIX 0
|
||||
#define GR2_VERSION_BUGFIX 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
|
|
@ -37,10 +37,10 @@ enum DirCode { // Hungarian: dirc
|
|||
R = 2, // right-to-left, strong - R
|
||||
AL = 3, // Arabic letter, right-to-left, strong, AR
|
||||
EN = 4, // European number, left-to-right, weak - EN
|
||||
ES = 5, // European separator, left-to-right, weak - ES
|
||||
EUS = 5, // European separator, left-to-right, weak - ES
|
||||
ET = 6, // European number terminator, left-to-right, weak - ET
|
||||
AN = 7, // Arabic number, left-to-right, weak - AN
|
||||
CS = 8, // Common number separator, left-to-right, weak - CS
|
||||
CUS = 8, // Common number separator, left-to-right, weak - CS
|
||||
WS = 9, // white space, neutral - WS
|
||||
BN = 10, // boundary neutral - BN
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ if (GRAPHITE2_NTRACING)
|
|||
set(TRACING)
|
||||
endif (GRAPHITE2_NTRACING)
|
||||
|
||||
if (GRAPHITE2_TELEMETRY)
|
||||
add_definitions(-DGRAPHITE2_TELEMETRY)
|
||||
endif (GRAPHITE2_TELEMETRY)
|
||||
|
||||
set(GRAPHITE_HEADERS
|
||||
../include/graphite2/Font.h
|
||||
|
|
|
@ -37,6 +37,7 @@ using namespace graphite2;
|
|||
const void * bmp_subtable(const Face::Table & cmap)
|
||||
{
|
||||
const void * stbl;
|
||||
if (!cmap.size()) return 0;
|
||||
if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()))
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()))
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()))
|
||||
|
@ -49,6 +50,7 @@ const void * bmp_subtable(const Face::Table & cmap)
|
|||
const void * smp_subtable(const Face::Table & cmap)
|
||||
{
|
||||
const void * stbl;
|
||||
if (!cmap.size()) return 0;
|
||||
if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()))
|
||||
|| TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size())))
|
||||
return stbl;
|
||||
|
@ -109,6 +111,7 @@ CachedCmap::CachedCmap(const Face & face)
|
|||
|
||||
CachedCmap::~CachedCmap() throw()
|
||||
{
|
||||
if (!m_blocks) return;
|
||||
unsigned int numBlocks = (m_isBmpOnly)? 0x100 : 0x1100;
|
||||
for (unsigned int i = 0; i < numBlocks; i++)
|
||||
free(m_blocks[i]);
|
||||
|
|
|
@ -144,6 +144,9 @@ Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte
|
|||
: _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0), _status(loaded),
|
||||
_constraint(is_constraint), _modify(false), _delete(false), _own(true)
|
||||
{
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::category _code_cat(face.tele.code);
|
||||
#endif
|
||||
assert(bytecode_begin != 0);
|
||||
if (bytecode_begin == bytecode_end)
|
||||
{
|
||||
|
@ -211,11 +214,15 @@ Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte
|
|||
_code = static_cast<instr *>(realloc(_code, (_instr_count+1)*sizeof(instr)));
|
||||
_data = static_cast<byte *>(realloc(_data, _data_size*sizeof(byte)));
|
||||
|
||||
if (!_code)
|
||||
failure(alloc_failed);
|
||||
|
||||
// Make this RET_ZERO, we should never reach this but just in case ...
|
||||
_code[_instr_count] = op_to_fn[RET_ZERO].impl[_constraint];
|
||||
|
||||
if (!_code)
|
||||
failure(alloc_failed);
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::count_bytes(_data_size + (_instr_count+1)*sizeof(instr));
|
||||
#endif
|
||||
}
|
||||
|
||||
Machine::Code::~Code() throw ()
|
||||
|
|
|
@ -78,6 +78,9 @@ float Face::default_glyph_advance(const void* font_ptr, gr_uint16 glyphid)
|
|||
|
||||
bool Face::readGlyphs(uint32 faceOptions)
|
||||
{
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::category _glyph_cat(tele.glyph);
|
||||
#endif
|
||||
if (faceOptions & gr_face_cacheCmap)
|
||||
m_cmap = new CachedCmap(*this);
|
||||
else
|
||||
|
@ -98,6 +101,9 @@ bool Face::readGlyphs(uint32 faceOptions)
|
|||
|
||||
bool Face::readGraphite(const Table & silf)
|
||||
{
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::category _silf_cat(tele.silf);
|
||||
#endif
|
||||
const byte * p = silf;
|
||||
if (!p) return false;
|
||||
|
||||
|
@ -145,7 +151,8 @@ bool Face::runGraphite(Segment *seg, const Silf *aSilf) const
|
|||
#endif
|
||||
|
||||
bool res = aSilf->runGraphite(seg, 0, aSilf->justificationPass());
|
||||
res &= aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses());
|
||||
if (res)
|
||||
res = aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses());
|
||||
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
if (dbgout)
|
||||
|
|
|
@ -78,7 +78,7 @@ const void *FileFace::get_table_fn(const void* appFaceHandle, unsigned int name,
|
|||
if (appFaceHandle == 0) return 0;
|
||||
const FileFace & file_face = *static_cast<const FileFace *>(appFaceHandle);
|
||||
|
||||
char *tbl;
|
||||
void *tbl;
|
||||
size_t tbl_offset, tbl_len;
|
||||
if (!TtfUtil::GetTableInfo(name, file_face._header_tbl, file_face._table_dir, tbl_offset, tbl_len))
|
||||
return 0;
|
||||
|
@ -87,7 +87,7 @@ const void *FileFace::get_table_fn(const void* appFaceHandle, unsigned int name,
|
|||
|| fseek(file_face._file, tbl_offset, SEEK_SET) != 0)
|
||||
return 0;
|
||||
|
||||
tbl = gralloc<char>(tbl_len);
|
||||
tbl = malloc(tbl_len);
|
||||
if (fread(tbl, 1, tbl_len, file_face._file) != tbl_len)
|
||||
{
|
||||
free(tbl);
|
||||
|
|
|
@ -37,7 +37,7 @@ NameTable::NameTable(const void* data, size_t length, uint16 platformId, uint16
|
|||
m_platformOffset(0), m_platformLastRecord(0), m_nameDataLength(0),
|
||||
m_table(0), m_nameData(NULL)
|
||||
{
|
||||
void *pdata = malloc(length);
|
||||
void *pdata = gralloc<byte>(length);
|
||||
if (!pdata) return;
|
||||
memcpy(pdata, data, length);
|
||||
m_table = reinterpret_cast<const TtfUtil::Sfnt::FontNames*>(pdata);
|
||||
|
|
|
@ -46,16 +46,16 @@ Pass::Pass()
|
|||
m_rules(0),
|
||||
m_ruleMap(0),
|
||||
m_startStates(0),
|
||||
m_sTable(0),
|
||||
m_transitions(0),
|
||||
m_states(0),
|
||||
m_flags(0),
|
||||
m_iMaxLoop(0),
|
||||
m_numGlyphs(0),
|
||||
m_numRules(0),
|
||||
m_sRows(0),
|
||||
m_sTransition(0),
|
||||
m_sSuccess(0),
|
||||
m_sColumns(0),
|
||||
m_numStates(0),
|
||||
m_numTransition(0),
|
||||
m_numSuccess(0),
|
||||
m_numColumns(0),
|
||||
m_minPreCtxt(0),
|
||||
m_maxPreCtxt(0)
|
||||
{
|
||||
|
@ -65,14 +65,14 @@ Pass::~Pass()
|
|||
{
|
||||
free(m_cols);
|
||||
free(m_startStates);
|
||||
free(m_sTable);
|
||||
free(m_transitions);
|
||||
free(m_states);
|
||||
free(m_ruleMap);
|
||||
|
||||
delete [] m_rules;
|
||||
}
|
||||
|
||||
bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t subtable_base, const Face & face)
|
||||
bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t subtable_base, GR_MAYBE_UNUSED const Face & face)
|
||||
{
|
||||
const byte * p = pass_start,
|
||||
* const pass_end = p + pass_length;
|
||||
|
@ -89,33 +89,34 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su
|
|||
* const rcCode = pass_start + be::read<uint32>(p) - subtable_base,
|
||||
* const aCode = pass_start + be::read<uint32>(p) - subtable_base;
|
||||
be::skip<uint32>(p);
|
||||
m_sRows = be::read<uint16>(p);
|
||||
m_sTransition = be::read<uint16>(p);
|
||||
m_sSuccess = be::read<uint16>(p);
|
||||
m_sColumns = be::read<uint16>(p);
|
||||
m_numStates = be::read<uint16>(p);
|
||||
m_numTransition = be::read<uint16>(p);
|
||||
m_numSuccess = be::read<uint16>(p);
|
||||
m_numColumns = be::read<uint16>(p);
|
||||
numRanges = be::read<uint16>(p);
|
||||
be::skip<uint16>(p, 3); // skip searchRange, entrySelector & rangeShift.
|
||||
assert(p - pass_start == 40);
|
||||
// Perform some sanity checks.
|
||||
if ( m_sTransition > m_sRows
|
||||
|| m_sSuccess > m_sRows
|
||||
|| m_sSuccess + m_sTransition < m_sRows
|
||||
if ( m_numTransition > m_numStates
|
||||
|| m_numSuccess > m_numStates
|
||||
|| m_numSuccess + m_numTransition < m_numStates
|
||||
|| numRanges == 0)
|
||||
return false;
|
||||
|
||||
m_successStart = m_numStates - m_numSuccess;
|
||||
if (p + numRanges * 6 - 4 > pass_end) return false;
|
||||
m_numGlyphs = be::peek<uint16>(p + numRanges * 6 - 4) + 1;
|
||||
// Calculate the start of various arrays.
|
||||
const byte * const ranges = p;
|
||||
be::skip<uint16>(p, numRanges*3);
|
||||
const byte * const o_rule_map = p;
|
||||
be::skip<uint16>(p, m_sSuccess + 1);
|
||||
be::skip<uint16>(p, m_numSuccess + 1);
|
||||
|
||||
// More sanity checks
|
||||
if (reinterpret_cast<const byte *>(o_rule_map + m_sSuccess*sizeof(uint16)) > pass_end
|
||||
if (reinterpret_cast<const byte *>(o_rule_map + m_numSuccess*sizeof(uint16)) > pass_end
|
||||
|| p > pass_end)
|
||||
return false;
|
||||
const size_t numEntries = be::peek<uint16>(o_rule_map + m_sSuccess*sizeof(uint16));
|
||||
const size_t numEntries = be::peek<uint16>(o_rule_map + m_numSuccess*sizeof(uint16));
|
||||
const byte * const rule_map = p;
|
||||
be::skip<uint16>(p, numEntries);
|
||||
|
||||
|
@ -138,7 +139,7 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su
|
|||
const uint16 * const o_actions = reinterpret_cast<const uint16 *>(p);
|
||||
be::skip<uint16>(p, m_numRules + 1);
|
||||
const byte * const states = p;
|
||||
be::skip<int16>(p, m_sTransition*m_sColumns);
|
||||
be::skip<int16>(p, m_numTransition*m_numColumns);
|
||||
be::skip<byte>(p); // skip reserved byte
|
||||
if (p != pcCode || p >= pass_end) return false;
|
||||
be::skip<byte>(p, pass_constraint_len);
|
||||
|
@ -161,7 +162,10 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su
|
|||
if (!readRanges(ranges, numRanges)) return false;
|
||||
if (!readRules(rule_map, numEntries, precontext, sort_keys,
|
||||
o_constraint, rcCode, o_actions, aCode, face)) return false;
|
||||
return readStates(start_states, states, o_rule_map);
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::category _states_cat(face.tele.states);
|
||||
#endif
|
||||
return readStates(start_states, states, o_rule_map, face);
|
||||
}
|
||||
|
||||
|
||||
|
@ -225,36 +229,43 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries,
|
|||
static int cmpRuleEntry(const void *a, const void *b) { return (*(RuleEntry *)a < *(RuleEntry *)b ? -1 :
|
||||
(*(RuleEntry *)b < *(RuleEntry *)a ? 1 : 0)); }
|
||||
|
||||
bool Pass::readStates(const byte * starts, const byte *states, const byte * o_rule_map)
|
||||
bool Pass::readStates(const byte * starts, const byte *states, const byte * o_rule_map, GR_MAYBE_UNUSED const Face & face)
|
||||
{
|
||||
m_startStates = gralloc<State *>(m_maxPreCtxt - m_minPreCtxt + 1);
|
||||
m_states = gralloc<State>(m_sRows);
|
||||
m_sTable = gralloc<State *>(m_sTransition * m_sColumns);
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::category _states_cat(face.tele.starts);
|
||||
#endif
|
||||
m_startStates = gralloc<uint16>(m_maxPreCtxt - m_minPreCtxt + 1);
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::set_category(face.tele.states);
|
||||
#endif
|
||||
m_states = gralloc<State>(m_numStates);
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::set_category(face.tele.transitions);
|
||||
#endif
|
||||
m_transitions = gralloc<uint16>(m_numTransition * m_numColumns);
|
||||
|
||||
if (!m_startStates || !m_states || !m_sTable) return false;
|
||||
if (!m_startStates || !m_states || !m_transitions) return false;
|
||||
// load start states
|
||||
for (State * * s = m_startStates,
|
||||
* * const s_end = s + m_maxPreCtxt - m_minPreCtxt + 1; s != s_end; ++s)
|
||||
for (uint16 * s = m_startStates,
|
||||
* const s_end = s + m_maxPreCtxt - m_minPreCtxt + 1; s != s_end; ++s)
|
||||
{
|
||||
*s = m_states + be::read<uint16>(starts);
|
||||
if (*s < m_states || *s >= m_states + m_sRows) return false; // true;
|
||||
*s = be::read<uint16>(starts);
|
||||
if (*s >= m_numStates) return false; // true;
|
||||
}
|
||||
|
||||
// load state transition table.
|
||||
for (State * * t = m_sTable,
|
||||
* * const t_end = t + m_sTransition*m_sColumns; t != t_end; ++t)
|
||||
for (uint16 * t = m_transitions,
|
||||
* const t_end = t + m_numTransition*m_numColumns; t != t_end; ++t)
|
||||
{
|
||||
*t = m_states + be::read<uint16>(states);
|
||||
if (*t < m_states || *t >= m_states + m_sRows) return false;
|
||||
*t = be::read<uint16>(states);
|
||||
if (*t >= m_numStates) return false;
|
||||
}
|
||||
|
||||
State * s = m_states,
|
||||
* const transitions_end = m_states + m_sTransition,
|
||||
* const success_begin = m_states + m_sRows - m_sSuccess;
|
||||
const RuleEntry * rule_map_end = m_ruleMap + be::peek<uint16>(o_rule_map + m_sSuccess*sizeof(uint16));
|
||||
for (size_t n = m_sRows; n; --n, ++s)
|
||||
* const success_begin = m_states + m_numStates - m_numSuccess;
|
||||
const RuleEntry * rule_map_end = m_ruleMap + be::peek<uint16>(o_rule_map + m_numSuccess*sizeof(uint16));
|
||||
for (size_t n = m_numStates; n; --n, ++s)
|
||||
{
|
||||
s->transitions = s < transitions_end ? m_sTable + (s-m_states)*m_sColumns : 0;
|
||||
RuleEntry * const begin = s < success_begin ? 0 : m_ruleMap + be::read<uint16>(o_rule_map),
|
||||
* const end = s < success_begin ? 0 : m_ruleMap + be::peek<uint16>(o_rule_map);
|
||||
|
||||
|
@ -279,7 +290,7 @@ bool Pass::readRanges(const byte * ranges, size_t num_ranges)
|
|||
* ci_end = m_cols + be::read<uint16>(ranges) + 1,
|
||||
col = be::read<uint16>(ranges);
|
||||
|
||||
if (ci >= ci_end || ci_end > m_cols+m_numGlyphs || col >= m_sColumns)
|
||||
if (ci >= ci_end || ci_end > m_cols+m_numGlyphs || col >= m_numColumns)
|
||||
return false;
|
||||
|
||||
// A glyph must only belong to one column at a time
|
||||
|
@ -322,31 +333,30 @@ void Pass::runGraphite(Machine & m, FiniteStateMachine & fsm) const
|
|||
} while (s);
|
||||
}
|
||||
|
||||
inline uint16 Pass::glyphToCol(const uint16 gid) const
|
||||
{
|
||||
return gid < m_numGlyphs ? m_cols[gid] : 0xffffU;
|
||||
}
|
||||
|
||||
bool Pass::runFSM(FiniteStateMachine& fsm, Slot * slot) const
|
||||
{
|
||||
fsm.reset(slot, m_maxPreCtxt);
|
||||
if (fsm.slots.context() < m_minPreCtxt)
|
||||
return false;
|
||||
|
||||
const State * state = m_startStates[m_maxPreCtxt - fsm.slots.context()];
|
||||
uint16 state = m_startStates[m_maxPreCtxt - fsm.slots.context()];
|
||||
uint8 free_slots = SlotMap::MAX_SLOTS;
|
||||
do
|
||||
{
|
||||
fsm.slots.pushSlot(slot);
|
||||
if (fsm.slots.size() >= SlotMap::MAX_SLOTS) return false;
|
||||
const uint16 col = glyphToCol(slot->gid());
|
||||
if (col == 0xffffU || !state->is_transition()) return true;
|
||||
if (--free_slots == 0
|
||||
|| slot->gid() >= m_numGlyphs
|
||||
|| m_cols[slot->gid()] == 0xffffU
|
||||
|| state >= m_numTransition)
|
||||
return free_slots != 0;
|
||||
|
||||
state = state->transitions[col];
|
||||
if (state->is_success())
|
||||
fsm.rules.accumulate_rules(*state);
|
||||
const uint16 * transitions = m_transitions + state*m_numColumns;
|
||||
state = transitions[m_cols[slot->gid()]];
|
||||
if (state >= m_successStart)
|
||||
fsm.rules.accumulate_rules(m_states[state]);
|
||||
|
||||
slot = slot->next();
|
||||
} while (state != m_states && slot);
|
||||
} while (state != 0 && slot);
|
||||
|
||||
fsm.slots.pushSlot(slot);
|
||||
return true;
|
||||
|
|
|
@ -52,6 +52,7 @@ Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int tex
|
|||
m_bufSize(numchars + 10),
|
||||
m_numGlyphs(numchars),
|
||||
m_numCharinfo(numchars),
|
||||
m_passBits(m_silf->aPassBits() ? -1 : 0),
|
||||
m_defaultOriginal(0),
|
||||
m_dir(textDir)
|
||||
{
|
||||
|
@ -128,6 +129,7 @@ void Segment::append(const Segment &other)
|
|||
m_numGlyphs += other.m_numGlyphs;
|
||||
m_advance = m_advance + other.m_advance;
|
||||
m_bbox = m_bbox.widen(bbox);
|
||||
m_passBits &= other.passBits();
|
||||
}
|
||||
#endif // GRAPHITE2_NSEGCACHE
|
||||
|
||||
|
@ -150,6 +152,9 @@ void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset)
|
|||
aSlot->prev(m_last);
|
||||
m_last = aSlot;
|
||||
if (!m_first) m_first = aSlot;
|
||||
if (theGlyph && m_silf->aPassBits())
|
||||
m_passBits &= theGlyph->attrs()[m_silf->aPassBits()]
|
||||
| (m_silf->numPasses() > 16 ? (theGlyph->attrs()[m_silf->aPassBits() + 1] << 16) : 0);
|
||||
}
|
||||
|
||||
Slot *Segment::newSlot()
|
||||
|
@ -185,6 +190,13 @@ void Segment::freeSlot(Slot *aSlot)
|
|||
{
|
||||
if (m_last == aSlot) m_last = aSlot->prev();
|
||||
if (m_first == aSlot) m_first = aSlot->next();
|
||||
if (aSlot->attachedTo())
|
||||
aSlot->attachedTo()->removeChild(aSlot);
|
||||
while (aSlot->firstChild())
|
||||
{
|
||||
aSlot->firstChild()->attachTo(NULL);
|
||||
aSlot->removeChild(aSlot->firstChild());
|
||||
}
|
||||
// reset the slot incase it is reused
|
||||
::new (aSlot) Slot;
|
||||
memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
|
||||
|
|
|
@ -55,6 +55,7 @@ Silf::Silf() throw()
|
|||
m_aUser(0),
|
||||
m_aBidi(0),
|
||||
m_aMirror(0),
|
||||
m_aPassBits(0),
|
||||
m_iMaxComp(0),
|
||||
m_aLig(0),
|
||||
m_numPseudo(0),
|
||||
|
@ -111,7 +112,7 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, const Face&
|
|||
m_aBreak = be::read<uint8>(p);
|
||||
m_aBidi = be::read<uint8>(p);
|
||||
m_aMirror = be::read<uint8>(p);
|
||||
be::skip<byte>(p); // skip reserved stuff
|
||||
m_aPassBits = be::read<uint8>(p);
|
||||
|
||||
// Read Justification levels.
|
||||
m_numJusts = be::read<uint8>(p);
|
||||
|
@ -374,6 +375,7 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass) const
|
|||
#endif
|
||||
|
||||
// test whether to reorder, prepare for positioning
|
||||
if (i >= 32 || (seg->passBits() & (1 << i)) == 0)
|
||||
m_passes[i].runGraphite(m, fsm);
|
||||
// only subsitution passes can change segment length, cached subsegments are short for their text
|
||||
if (m.status() != vm::Machine::finished
|
||||
|
|
|
@ -87,7 +87,7 @@ Position Slot::finalise(const Segment *seg, const Font *font, Position & base, R
|
|||
{
|
||||
if (attrLevel && m_attLevel > attrLevel) return Position(0, 0);
|
||||
float scale = 1.0;
|
||||
Position shift = m_shift + Position(m_just, 0);
|
||||
Position shift(m_shift.x * ((seg->dir() & 1) * -2 + 1) + m_just, m_shift.y);
|
||||
float tAdvance = m_advance.x + m_just;
|
||||
const GlyphFace * glyphFace = seg->getFace()->glyphs().glyphSafe(glyph());
|
||||
if (font)
|
||||
|
@ -144,7 +144,7 @@ Position Slot::finalise(const Segment *seg, const Font *font, Position & base, R
|
|||
return res;
|
||||
}
|
||||
|
||||
uint32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel)
|
||||
int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel)
|
||||
{
|
||||
Position base;
|
||||
Rect bbox = seg->theGlyphBBoxTemporary(gid());
|
||||
|
@ -247,7 +247,9 @@ void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, cons
|
|||
if (idx < map.size() && map[idx])
|
||||
{
|
||||
Slot *other = map[idx];
|
||||
if (other != this && other->child(this))
|
||||
if (other == this) break;
|
||||
if (m_parent) m_parent->removeChild(this);
|
||||
if (other->child(this))
|
||||
{
|
||||
attachTo(other);
|
||||
if (((seg->dir() & 1) != 0) ^ (idx > subindex))
|
||||
|
@ -313,7 +315,7 @@ int Slot::getJustify(const Segment *seg, uint8 level, uint8 subindex) const
|
|||
|
||||
void Slot::setJustify(Segment *seg, uint8 level, uint8 subindex, int16 value)
|
||||
{
|
||||
if (level >= seg->silf()->numJustLevels()) return;
|
||||
if (level && level >= seg->silf()->numJustLevels()) return;
|
||||
if (!m_justs)
|
||||
{
|
||||
SlotJustify *j = seg->newJustify();
|
||||
|
@ -345,6 +347,34 @@ bool Slot::sibling(Slot *ap)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Slot::removeChild(Slot *ap)
|
||||
{
|
||||
if (this == ap || !m_child) return false;
|
||||
else if (ap == m_child)
|
||||
{
|
||||
Slot *nSibling = m_child->nextSibling();
|
||||
m_child->sibling(NULL);
|
||||
m_child = nSibling;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return m_child->removeSibling(ap);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Slot::removeSibling(Slot *ap)
|
||||
{
|
||||
if (this == ap || !m_sibling) return false;
|
||||
else if (ap == m_sibling)
|
||||
{
|
||||
m_sibling = m_sibling->nextSibling();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return m_sibling->removeSibling(ap);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
|
||||
{
|
||||
m_glyphid = glyphid;
|
||||
|
@ -365,6 +395,8 @@ void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
|
|||
if (aGlyph) theGlyph = aGlyph;
|
||||
}
|
||||
m_advance = Position(theGlyph->theAdvance().x, 0.);
|
||||
if (seg->silf()->aPassBits())
|
||||
seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()]);
|
||||
}
|
||||
|
||||
void Slot::floodShift(Position adj)
|
||||
|
|
|
@ -38,6 +38,9 @@ namespace
|
|||
{
|
||||
bool load_face(Face & face, unsigned int options)
|
||||
{
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::category _misc_cat(face.tele.misc);
|
||||
#endif
|
||||
Face::Table silf(face, Tag::Silf);
|
||||
if (silf) options &= ~gr_face_dumbRendering;
|
||||
else if (!(options & gr_face_dumbRendering))
|
||||
|
|
|
@ -38,7 +38,6 @@ of the License or (at your option) any later version.
|
|||
|
||||
using namespace graphite2;
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
||||
|
@ -58,19 +57,23 @@ bool gr_start_logging(gr_face * face, const char *log_path)
|
|||
log = _wfopen(wlog_path, L"wt");
|
||||
|
||||
free(wlog_path);
|
||||
#else
|
||||
#else // _WIN32
|
||||
FILE *log = fopen(log_path, "wt");
|
||||
#endif
|
||||
#endif // _WIN32
|
||||
if (!log) return false;
|
||||
|
||||
face->setLogger(log);
|
||||
if (!face->logger()) return false;
|
||||
|
||||
*face->logger() << json::array;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
*face->logger() << face->tele;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
#else // GRAPHITE2_NTRACING
|
||||
return false;
|
||||
#endif // GRAPHITE2_NTRACING
|
||||
}
|
||||
|
||||
bool graphite_start_logging(FILE * /* log */, GrLogMask /* mask */)
|
||||
|
@ -112,8 +115,37 @@ void graphite_stop_logging()
|
|||
|
||||
} // extern "C"
|
||||
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
size_t * graphite2::telemetry::_category = 0UL;
|
||||
#endif
|
||||
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
|
||||
json & graphite2::operator << (json & j, const telemetry & t) throw()
|
||||
{
|
||||
j << json::object
|
||||
<< "type" << "telemetry"
|
||||
<< "silf" << t.silf
|
||||
<< "states" << t.states
|
||||
<< "starts" << t.starts
|
||||
<< "transitions" << t.transitions
|
||||
<< "glyphs" << t.glyph
|
||||
<< "code" << t.code
|
||||
<< "misc" << t.misc
|
||||
<< "total" << (t.silf + t.states + t.starts + t.transitions + t.glyph + t.code + t.misc)
|
||||
<< json::close;
|
||||
return j;
|
||||
}
|
||||
#else
|
||||
json & graphite2::operator << (json & j, const telemetry &) throw()
|
||||
{
|
||||
return j;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
json & graphite2::operator << (json & j, const CharInfo & ci) throw()
|
||||
{
|
||||
return j << json::object
|
||||
|
|
|
@ -43,6 +43,7 @@ class GlyphCache;
|
|||
class NameTable;
|
||||
class json;
|
||||
|
||||
|
||||
using TtfUtil::Tag;
|
||||
|
||||
// These are the actual tags, as distinct from the consecutive IDs in TtfUtil.h
|
||||
|
@ -103,6 +104,10 @@ protected:
|
|||
private:
|
||||
uint16 m_ascent,
|
||||
m_descent;
|
||||
#ifdef GRAPHITE2_TELEMETRY
|
||||
public:
|
||||
mutable telemetry tele;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ of the License or (at your option) any later version.
|
|||
#include "inc/Main.h"
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__clang__)
|
||||
#if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ * 10) < 430
|
||||
#define HOT
|
||||
#if defined(__x86_64)
|
||||
#define REGPARM(n) __attribute__((regparm(n)))
|
||||
|
|
|
@ -44,15 +44,55 @@ typedef gr_int16 int16;
|
|||
typedef gr_int32 int32;
|
||||
typedef size_t uintptr;
|
||||
|
||||
#if GRAPHITE2_TELEMETRY
|
||||
struct telemetry
|
||||
{
|
||||
class category;
|
||||
|
||||
static size_t * _category;
|
||||
static void set_category(size_t & t) throw() { _category = &t; }
|
||||
static void stop() throw() { _category = 0; }
|
||||
static void count_bytes(size_t n) throw() { if (_category) *_category += n; }
|
||||
|
||||
size_t misc,
|
||||
silf,
|
||||
glyph,
|
||||
code,
|
||||
states,
|
||||
starts,
|
||||
transitions;
|
||||
|
||||
telemetry() : misc(0), silf(0), glyph(0), code(0), states(0), starts(0), transitions(0) {}
|
||||
};
|
||||
|
||||
class telemetry::category
|
||||
{
|
||||
size_t * _prev;
|
||||
public:
|
||||
category(size_t & t) : _prev(_category) { _category = &t; }
|
||||
~category() { _category = _prev; }
|
||||
};
|
||||
|
||||
#else
|
||||
struct telemetry {};
|
||||
#endif
|
||||
|
||||
// typesafe wrapper around malloc for simple types
|
||||
// use free(pointer) to deallocate
|
||||
|
||||
template <typename T> T * gralloc(size_t n)
|
||||
{
|
||||
#if GRAPHITE2_TELEMETRY
|
||||
telemetry::count_bytes(sizeof(T) * n);
|
||||
#endif
|
||||
return reinterpret_cast<T*>(malloc(sizeof(T) * n));
|
||||
}
|
||||
|
||||
template <typename T> T * grzeroalloc(size_t n)
|
||||
{
|
||||
#if GRAPHITE2_TELEMETRY
|
||||
telemetry::count_bytes(sizeof(T) * n);
|
||||
#endif
|
||||
return reinterpret_cast<T*>(calloc(n, sizeof(T)));
|
||||
}
|
||||
|
||||
|
@ -71,9 +111,9 @@ inline T max(const T a, const T b)
|
|||
} // namespace graphite2
|
||||
|
||||
#define CLASS_NEW_DELETE \
|
||||
void * operator new (size_t size){ return malloc(size);} \
|
||||
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 malloc(size);} \
|
||||
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() {} \
|
||||
|
|
|
@ -61,7 +61,7 @@ private:
|
|||
const uint16 * o_constraint, const byte *constraint_data,
|
||||
const uint16 * o_action, const byte * action_data,
|
||||
const Face &);
|
||||
bool readStates(const byte * starts, const byte * states, const byte * o_rule_map);
|
||||
bool readStates(const byte * starts, const byte * states, const byte * o_rule_map, const Face &);
|
||||
bool readRanges(const byte * ranges, size_t num_ranges);
|
||||
uint16 glyphToCol(const uint16 gid) const;
|
||||
bool runFSM(FiniteStateMachine & fsm, Slot * slot) const;
|
||||
|
@ -72,18 +72,19 @@ private:
|
|||
uint16 * m_cols;
|
||||
Rule * m_rules; // rules
|
||||
RuleEntry * m_ruleMap;
|
||||
State * * m_startStates; // prectxt length
|
||||
State * * m_sTable;
|
||||
uint16 * m_startStates; // prectxt length
|
||||
uint16 * m_transitions;
|
||||
State * m_states;
|
||||
|
||||
byte m_flags;
|
||||
byte m_iMaxLoop;
|
||||
uint16 m_numGlyphs;
|
||||
uint16 m_numRules;
|
||||
uint16 m_sRows;
|
||||
uint16 m_sTransition;
|
||||
uint16 m_sSuccess;
|
||||
uint16 m_sColumns;
|
||||
uint16 m_numStates;
|
||||
uint16 m_numTransition;
|
||||
uint16 m_numSuccess;
|
||||
uint16 m_successStart;
|
||||
uint16 m_numColumns;
|
||||
byte m_minPreCtxt;
|
||||
byte m_maxPreCtxt;
|
||||
vm::Machine::Code m_cPConstraint;
|
||||
|
|
|
@ -81,29 +81,14 @@ struct State
|
|||
{
|
||||
const RuleEntry * rules,
|
||||
* rules_end;
|
||||
const State * const * transitions;
|
||||
|
||||
size_t size() const;
|
||||
bool is_success() const;
|
||||
bool is_transition() const;
|
||||
bool empty() const;
|
||||
};
|
||||
|
||||
inline
|
||||
size_t State::size() const
|
||||
bool State::empty() const
|
||||
{
|
||||
return rules_end - rules;
|
||||
}
|
||||
|
||||
inline
|
||||
bool State::is_success() const
|
||||
{
|
||||
return (rules != NULL);
|
||||
}
|
||||
|
||||
inline
|
||||
bool State::is_transition() const
|
||||
{
|
||||
return (transitions != NULL);
|
||||
return rules_end == rules;
|
||||
}
|
||||
|
||||
|
||||
|
@ -222,12 +207,13 @@ inline
|
|||
void FiniteStateMachine::Rules::accumulate_rules(const State &state)
|
||||
{
|
||||
// Only bother if there are rules in the State object.
|
||||
if (state.size() == 0) return;
|
||||
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 * lrend = out + MAX_RULES;
|
||||
const RuleEntry * const lrend = out + MAX_RULES,
|
||||
* const rrend = state.rules_end;
|
||||
m_begin = out;
|
||||
while (lre != end() && out != lrend)
|
||||
{
|
||||
|
@ -235,14 +221,14 @@ void FiniteStateMachine::Rules::accumulate_rules(const State &state)
|
|||
else if (*rre < *lre) { *out++ = *rre++; }
|
||||
else { *out++ = *lre++; ++rre; }
|
||||
|
||||
if (rre == state.rules_end)
|
||||
if (rre == rrend)
|
||||
{
|
||||
while (lre != end() && out != lrend) { *out++ = *lre++; }
|
||||
m_end = out;
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (rre != state.rules_end && out != lrend) { *out++ = *rre++; }
|
||||
while (rre != rrend && out != lrend) { *out++ = *rre++; }
|
||||
m_end = out;
|
||||
}
|
||||
|
||||
|
@ -289,7 +275,7 @@ void SlotMap::reset(Slot & slot, short unsigned int ctxt)
|
|||
inline
|
||||
void SlotMap::pushSlot(Slot*const slot)
|
||||
{
|
||||
m_slot_map[m_size++ + 1] = slot;
|
||||
m_slot_map[++m_size] = slot;
|
||||
}
|
||||
|
||||
inline
|
||||
|
|
|
@ -123,8 +123,10 @@ public:
|
|||
int addFeatures(const Features& feats) { m_feats.push_back(feats); return m_feats.size() - 1; }
|
||||
uint32 getFeature(int index, uint8 findex) const { const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex); if (!pFR) return 0; else return pFR->getFeatureVal(m_feats[index]); }
|
||||
void dir(int8 val) { m_dir = val; }
|
||||
uint16 glyphAttr(uint16 gid, uint16 gattr) const { const GlyphFace * p = m_face->glyphs().glyphSafe(gid); return p ? p->attrs()[gattr] : 0; }
|
||||
uint16 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const;
|
||||
unsigned int passBits() const { return m_passBits; }
|
||||
void mergePassBits(const unsigned int val) { m_passBits &= val; }
|
||||
int16 glyphAttr(uint16 gid, uint16 gattr) const { const GlyphFace * p = m_face->glyphs().glyphSafe(gid); return p ? p->attrs()[gattr] : 0; }
|
||||
int32 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) 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; }
|
||||
|
@ -163,7 +165,8 @@ private:
|
|||
Slot * m_last; // last slot in segment
|
||||
unsigned int m_bufSize, // how big a buffer to create when need more slots
|
||||
m_numGlyphs,
|
||||
m_numCharinfo; // size of the array and number of input characters
|
||||
m_numCharinfo, // size of the array and number of input characters
|
||||
m_passBits; // if bit set then skip pass
|
||||
int m_defaultOriginal; // number of whitespace chars in the string
|
||||
int8 m_dir;
|
||||
};
|
||||
|
@ -181,7 +184,7 @@ void Segment::finalise(const Font *font)
|
|||
}
|
||||
|
||||
inline
|
||||
uint16 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const {
|
||||
int32 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const {
|
||||
if (attrLevel > 0)
|
||||
{
|
||||
Slot *is = findRoot(iSlot);
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
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 substitutionPass() const { return m_sPass; }
|
||||
uint8 positionPass() const { return m_pPass; }
|
||||
uint8 justificationPass() const { return m_jPass; }
|
||||
|
@ -111,7 +112,7 @@ private:
|
|||
uint8 m_sPass, m_pPass, m_jPass, m_bPass,
|
||||
m_flags;
|
||||
|
||||
uint8 m_aPseudo, m_aBreak, m_aUser, m_aBidi, m_aMirror,
|
||||
uint8 m_aPseudo, m_aBreak, m_aUser, m_aBidi, m_aMirror, m_aPassBits,
|
||||
m_iMaxComp;
|
||||
uint16 m_aLig,
|
||||
m_numPseudo,
|
||||
|
|
|
@ -125,7 +125,9 @@ public:
|
|||
bool child(Slot *ap);
|
||||
Slot* nextSibling() const { return m_sibling; }
|
||||
bool sibling(Slot *ap);
|
||||
uint32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel);
|
||||
bool removeChild(Slot *ap);
|
||||
bool removeSibling(Slot *ap);
|
||||
int32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel);
|
||||
void positionShift(Position a) { m_position += a; }
|
||||
void floodShift(Position adj);
|
||||
float just() const { return m_just; }
|
||||
|
|
|
@ -52,10 +52,13 @@ struct objectid
|
|||
objectid(const Segment * const p) throw();
|
||||
};
|
||||
|
||||
|
||||
json & operator << (json & j, const Position &) 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
|
||||
|
|
|
@ -443,7 +443,7 @@ STARTOP(push_glyph_attr_obs)
|
|||
const int slot_ref = int8(param[1]);
|
||||
slotref slot = slotat(slot_ref);
|
||||
if (slot)
|
||||
push(seg.glyphAttr(slot->gid(), glyph_attr));
|
||||
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
|
||||
ENDOP
|
||||
|
||||
STARTOP(push_glyph_metric)
|
||||
|
@ -477,7 +477,7 @@ STARTOP(push_att_to_gattr_obs)
|
|||
{
|
||||
slotref att = slot->attachedTo();
|
||||
if (att) slot = att;
|
||||
push(seg.glyphAttr(slot->gid(), glyph_attr));
|
||||
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
|
||||
}
|
||||
ENDOP
|
||||
|
||||
|
@ -491,7 +491,7 @@ STARTOP(push_att_to_glyph_metric)
|
|||
{
|
||||
slotref att = slot->attachedTo();
|
||||
if (att) slot = att;
|
||||
push(seg.getGlyphMetric(slot, glyph_attr, attr_level));
|
||||
push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level)));
|
||||
}
|
||||
ENDOP
|
||||
|
||||
|
@ -616,7 +616,7 @@ STARTOP(push_glyph_attr)
|
|||
const int slot_ref = int8(param[2]);
|
||||
slotref slot = slotat(slot_ref);
|
||||
if (slot)
|
||||
push(seg.glyphAttr(slot->gid(), glyph_attr));
|
||||
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
|
||||
ENDOP
|
||||
|
||||
STARTOP(push_att_to_glyph_attr)
|
||||
|
@ -629,7 +629,7 @@ STARTOP(push_att_to_glyph_attr)
|
|||
{
|
||||
slotref att = slot->attachedTo();
|
||||
if (att) slot = att;
|
||||
push(seg.glyphAttr(slot->gid(), glyph_attr));
|
||||
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
|
||||
}
|
||||
ENDOP
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче