bug 876069 - update graphite2 library to release 1.2.2. r=jdaggett

This commit is contained in:
Jonathan Kew 2013-05-28 14:49:25 +01:00
Родитель 3a7fe9a2b2
Коммит 7d0ec4d98e
25 изменённых файлов: 273 добавлений и 121 удалений

Просмотреть файл

@ -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)
{
@ -210,12 +213,16 @@ Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte
assert((bytecode_end - bytecode_begin) >= std::ptrdiff_t(_data_size));
_code = static_cast<instr *>(realloc(_code, (_instr_count+1)*sizeof(instr)));
_data = static_cast<byte *>(realloc(_data, _data_size*sizeof(byte)));
// 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);
// Make this RET_ZERO, we should never reach this but just in case ...
_code[_instr_count] = op_to_fn[RET_ZERO].impl[_constraint];
#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,7 +375,8 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass) const
#endif
// test whether to reorder, prepare for positioning
m_passes[i].runGraphite(m, fsm);
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
|| (i < m_pPass && (seg->slotCount() > initSize * MAX_SEG_GROWTH_FACTOR

Просмотреть файл

@ -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;

Просмотреть файл

@ -64,11 +64,11 @@ struct RuleEntry
inline
bool operator < (const RuleEntry &r) const
{
const unsigned short lsort = rule->sort, rsort = r.rule->sort;
{
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
{
@ -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