зеркало из https://github.com/mozilla/pjs.git
bug 746975 - update graphite2 library to 1.1.2 release from upstream. r=jdaggett a=akeybl
This commit is contained in:
Родитель
37a22d76d2
Коммит
4111d5a1ea
|
@ -28,9 +28,9 @@
|
|||
|
||||
#include "graphite2/Types.h"
|
||||
|
||||
#define GR2_VERSION_MAJOR 2
|
||||
#define GR2_VERSION_MINOR 0
|
||||
#define GR2_VERSION_BUGFIX 1
|
||||
#define GR2_VERSION_MAJOR 1
|
||||
#define GR2_VERSION_MINOR 1
|
||||
#define GR2_VERSION_BUGFIX 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
|
|
@ -94,7 +94,7 @@ enum gr_attrCode {
|
|||
/// bidi directionality of this glyph (not implemented)
|
||||
gr_slatDir,
|
||||
/// Whether insertion is allowed before this glyph
|
||||
gr_slatInsert,
|
||||
gr_slatInsert,
|
||||
/// Final positioned position of this glyph relative to its parent in x-direction in pixels
|
||||
gr_slatPosX,
|
||||
/// Final positioned position of this glyph relative to its parent in y-direction in pixels
|
||||
|
@ -119,8 +119,10 @@ enum gr_attrCode {
|
|||
gr_slatJWeight,
|
||||
/// Amount this slot mush shrink or stretch in design units
|
||||
gr_slatJWidth,
|
||||
/// SubSegment split point
|
||||
gr_slatSegSplit = gr_slatJStretch + 29,
|
||||
/// User defined attribute, see subattr for user attr number
|
||||
gr_slatUserDefn = gr_slatJStretch + 30,
|
||||
gr_slatUserDefn,
|
||||
|
||||
/// not implemented
|
||||
gr_slatMax,
|
||||
|
|
|
@ -300,8 +300,8 @@ const bidi_action actionWeak[][10] =
|
|||
inline uint8 GetDeferredType(bidi_action a) { return (a >> 4) & 0xF; }
|
||||
inline uint8 GetResolvedType(bidi_action a) { return a & 0xF; }
|
||||
inline DirCode EmbeddingDirection(int l) { return l & 1 ? R : L; }
|
||||
inline bool IsDeferredState(bidi_state a) { return (1 << a) & (rtmask | ltmask | acmask | rcmask | rsmask | lcmask | lsmask); }
|
||||
inline bool IsModifiedClass(DirCode a) { return (1 << a) & (ALmask | NSMmask | ESmask | CSmask | ETmask | ENmask); }
|
||||
inline bool IsDeferredState(bidi_state a) { return 0 != ((1 << a) & (rtmask | ltmask | acmask | rcmask | rsmask | lcmask | lsmask)); }
|
||||
inline bool IsModifiedClass(DirCode a) { return 0 != ((1 << a) & (ALmask | NSMmask | ESmask | CSmask | ETmask | ENmask)); }
|
||||
|
||||
void SetDeferredRunClass(Slot *s, Slot *sRun, int nval)
|
||||
{
|
||||
|
|
|
@ -54,6 +54,7 @@ set(GRAPHITE_HEADERS
|
|||
../include/graphite2/Font.h
|
||||
../include/graphite2/Segment.h
|
||||
../include/graphite2/Types.h
|
||||
../include/graphite2/Log.h
|
||||
)
|
||||
|
||||
file(GLOB PRIVATE_HEADERS inc/*.h)
|
||||
|
|
|
@ -56,83 +56,64 @@ bool CachedFace::runGraphite(Segment *seg, const Silf *pSilf) const
|
|||
assert(pSilf);
|
||||
pSilf->runGraphite(seg, 0, pSilf->substitutionPass());
|
||||
|
||||
SegCache * segCache = NULL;
|
||||
unsigned int silfIndex = 0;
|
||||
for (; silfIndex < m_numSilf && &(m_silfs[silfIndex]) != pSilf; ++silfIndex);
|
||||
if (silfIndex == m_numSilf) return false;
|
||||
SegCache * const segCache = m_cacheStore->getOrCreate(silfIndex, seg->getFeatures(0));
|
||||
if (!segCache)
|
||||
return false;
|
||||
|
||||
for (unsigned int i = 0; i < m_numSilf; i++)
|
||||
{
|
||||
if (&(m_silfs[i]) == pSilf)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(silfIndex < m_numSilf);
|
||||
assert(m_cacheStore);
|
||||
segCache = m_cacheStore->getOrCreate(silfIndex, seg->getFeatures(0));
|
||||
// find where the segment can be broken
|
||||
Slot * subSegStartSlot = seg->first();
|
||||
Slot * subSegEndSlot = subSegStartSlot;
|
||||
uint16 cmapGlyphs[eMaxSpliceSize];
|
||||
int subSegStart = 0;
|
||||
bool spaceOnly = true;
|
||||
for (unsigned int i = 0; i < seg->charInfoCount(); i++)
|
||||
for (unsigned int i = 0; i < seg->charInfoCount(); ++i)
|
||||
{
|
||||
if (i - subSegStart < eMaxSpliceSize)
|
||||
{
|
||||
cmapGlyphs[i-subSegStart] = subSegEndSlot->gid();
|
||||
}
|
||||
if (!m_cacheStore->isSpaceGlyph(subSegEndSlot->gid()))
|
||||
{
|
||||
spaceOnly = false;
|
||||
}
|
||||
const unsigned int length = i - subSegStart + 1;
|
||||
if (length < eMaxSpliceSize)
|
||||
cmapGlyphs[length-1] = subSegEndSlot->gid();
|
||||
else return false;
|
||||
const bool spaceOnly = m_cacheStore->isSpaceGlyph(subSegEndSlot->gid());
|
||||
// at this stage the character to slot mapping is still 1 to 1
|
||||
int breakWeight = seg->charinfo(i)->breakWeight();
|
||||
int nextBreakWeight = (i + 1 < seg->charInfoCount())?
|
||||
seg->charinfo(i+1)->breakWeight() : 0;
|
||||
if (((breakWeight > 0) &&
|
||||
(breakWeight <= gr_breakWord)) ||
|
||||
(i + 1 == seg->charInfoCount()) ||
|
||||
m_cacheStore->isSpaceGlyph(subSegEndSlot->gid()) ||
|
||||
((i + 1 < seg->charInfoCount()) &&
|
||||
(((nextBreakWeight < 0) &&
|
||||
(nextBreakWeight >= gr_breakBeforeWord)) ||
|
||||
(subSegEndSlot->next() && m_cacheStore->isSpaceGlyph(subSegEndSlot->next()->gid())))))
|
||||
const int breakWeight = seg->charinfo(i)->breakWeight(),
|
||||
nextBreakWeight = (i + 1 < seg->charInfoCount())?
|
||||
seg->charinfo(i+1)->breakWeight() : 0;
|
||||
const uint8 f = seg->charinfo(i)->flags();
|
||||
if (((spaceOnly
|
||||
|| (breakWeight > 0 && breakWeight <= gr_breakWord)
|
||||
|| i + 1 == seg->charInfoCount()
|
||||
|| ((nextBreakWeight < 0 && nextBreakWeight >= gr_breakBeforeWord)
|
||||
|| (subSegEndSlot->next() && m_cacheStore->isSpaceGlyph(subSegEndSlot->next()->gid()))))
|
||||
&& f != 1)
|
||||
|| f == 2)
|
||||
{
|
||||
// record the next slot before any splicing
|
||||
Slot * nextSlot = subSegEndSlot->next();
|
||||
if (spaceOnly)
|
||||
{
|
||||
// spaces should be left untouched by graphite rules in any sane font
|
||||
}
|
||||
else
|
||||
// spaces should be left untouched by graphite rules in any sane font
|
||||
if (!spaceOnly)
|
||||
{
|
||||
// found a break position, check for a cache of the sub sequence
|
||||
const SegCacheEntry * entry = (segCache)?
|
||||
segCache->find(cmapGlyphs, i - subSegStart + 1) : NULL;
|
||||
const SegCacheEntry * entry = segCache->find(cmapGlyphs, length);
|
||||
// TODO disable cache for words at start/end of line with contextuals
|
||||
if (!entry)
|
||||
{
|
||||
unsigned int length = i - subSegStart + 1;
|
||||
SegmentScopeState scopeState = seg->setScope(subSegStartSlot, subSegEndSlot, length);
|
||||
pSilf->runGraphite(seg, pSilf->substitutionPass(), pSilf->numPasses());
|
||||
//entry =runGraphiteOnSubSeg(segCache, seg, cmapGlyphs,
|
||||
// subSegStartSlot, subSegEndSlot,
|
||||
// subSegStart, i - subSegStart + 1);
|
||||
if ((length < eMaxSpliceSize) && segCache)
|
||||
if (length < eMaxSpliceSize)
|
||||
{
|
||||
seg->associateChars();
|
||||
entry = segCache->cache(m_cacheStore, cmapGlyphs, length, seg, subSegStart);
|
||||
}
|
||||
seg->removeScope(scopeState);
|
||||
}
|
||||
else
|
||||
{
|
||||
//seg->splice(subSegStart, i - subSegStart + 1, subSegStartSlot, subSegEndSlot, entry);
|
||||
seg->splice(subSegStart, i - subSegStart + 1, subSegStartSlot, subSegEndSlot,
|
||||
seg->splice(subSegStart, length, subSegStartSlot, subSegEndSlot,
|
||||
entry->first(), entry->glyphLength());
|
||||
}
|
||||
}
|
||||
subSegEndSlot = nextSlot;
|
||||
subSegStartSlot = nextSlot;
|
||||
subSegStartSlot = subSegEndSlot = nextSlot;
|
||||
subSegStart = i + 1;
|
||||
spaceOnly = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -112,7 +112,7 @@ uint16 CmapCache::operator [] (const uint32 usv) const throw()
|
|||
|
||||
CmapCache::operator bool() const throw()
|
||||
{
|
||||
return m_blocks;
|
||||
return m_blocks != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,6 +136,6 @@ uint16 DirectCmap::operator [] (const uint32 usv) const throw()
|
|||
|
||||
DirectCmap::operator bool () const throw()
|
||||
{
|
||||
return _ctable;
|
||||
return _ctable != 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -592,7 +592,7 @@ int32 Machine::Code::run(Machine & m, slotref * & map) const
|
|||
assert(_own);
|
||||
assert(*this); // Check we are actually runnable
|
||||
|
||||
if (m.slotMap().size() <= _max_ref + m.slotMap().context())
|
||||
if (m.slotMap().size() <= size_t(_max_ref + m.slotMap().context()))
|
||||
{
|
||||
m._status = Machine::slot_offset_out_bounds;
|
||||
// return (m.slotMap().end() - map);
|
||||
|
|
|
@ -85,7 +85,7 @@ bool Face::readGraphite()
|
|||
{
|
||||
size_t lSilf;
|
||||
const byte * const pSilf = getTable(Tag::Silf, &lSilf),
|
||||
* p = pSilf;
|
||||
* p = pSilf;
|
||||
if (!p) return false;
|
||||
|
||||
const uint32 version = be::read<uint32>(p);
|
||||
|
|
|
@ -42,7 +42,9 @@ using namespace graphite2;
|
|||
const void* pMaxp = face.getTable(Tag::maxp);
|
||||
if (pMaxp == NULL) return false;
|
||||
m_nGlyphs = m_nGlyphsWithGraphics = (unsigned short)TtfUtil::GlyphCount(pMaxp);
|
||||
|
||||
if (TtfUtil::LocaLookup(m_nGlyphs-1, m_pLoca, m_lLoca, m_pHead) == size_t(-1))
|
||||
return false; // This will fail if m_nGlyphs is wildly out of range.
|
||||
|
||||
if (!dumb_font)
|
||||
{
|
||||
if ((m_pGlat = face.getTable(Tag::Glat, &m_lGlat)) == NULL) return false;
|
||||
|
|
|
@ -63,33 +63,29 @@ Pass::~Pass()
|
|||
delete [] m_rules;
|
||||
}
|
||||
|
||||
bool Pass::readPass(void *pass, 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, const Face & face)
|
||||
{
|
||||
const byte * p = reinterpret_cast<const byte *>(pass),
|
||||
* const pass_start = p,
|
||||
const byte * p = pass_start,
|
||||
* const pass_end = p + pass_length;
|
||||
size_t numRanges;
|
||||
|
||||
if (pass_length < 40) return false;
|
||||
// Read in basic values
|
||||
m_immutable = (*p++) & 0x1U;
|
||||
m_iMaxLoop = *p++;
|
||||
p++; // skip maxContext
|
||||
p += sizeof(byte); // skip maxBackup
|
||||
m_immutable = be::read<byte>(p) & 0x1U;
|
||||
m_iMaxLoop = be::read<byte>(p);
|
||||
be::skip<byte>(p,2); // skip maxContext & maxBackup
|
||||
m_numRules = be::read<uint16>(p);
|
||||
p += sizeof(uint16); // not sure why we would want this
|
||||
be::skip<uint16>(p); // fsmOffset - not sure why we would want this
|
||||
const byte * const pcCode = pass_start + be::read<uint32>(p) - subtable_base,
|
||||
* const rcCode = pass_start + be::read<uint32>(p) - subtable_base,
|
||||
* const aCode = pass_start + be::read<uint32>(p) - subtable_base;
|
||||
p += sizeof(uint32);
|
||||
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);
|
||||
numRanges = be::read<uint16>(p);
|
||||
p += sizeof(uint16) // skip searchRange
|
||||
+ sizeof(uint16) // skip entrySelector
|
||||
+ sizeof(uint16); // skip rangeShift
|
||||
be::skip<uint16>(p, 3); // skip searchRange, entrySelector & rangeShift.
|
||||
assert(p - pass_start == 40);
|
||||
// Perform some sanity checks.
|
||||
if ( m_sTransition > m_sRows
|
||||
|
@ -101,9 +97,9 @@ bool Pass::readPass(void *pass, size_t pass_length, size_t subtable_base, const
|
|||
m_numGlyphs = be::peek<uint16>(p + numRanges * 6 - 4) + 1;
|
||||
// Caculate the start of vairous arrays.
|
||||
const byte * const ranges = p;
|
||||
p += numRanges*sizeof(uint16)*3;
|
||||
be::skip<uint16>(p, numRanges*3);
|
||||
const byte * const o_rule_map = p;
|
||||
p += (m_sSuccess + 1)*sizeof(uint16);
|
||||
be::skip<uint16>(p, m_sSuccess + 1);
|
||||
|
||||
// More sanity checks
|
||||
if ( reinterpret_cast<const byte *>(o_rule_map) > pass_end
|
||||
|
@ -111,34 +107,38 @@ bool Pass::readPass(void *pass, size_t pass_length, size_t subtable_base, const
|
|||
return false;
|
||||
const size_t numEntries = be::peek<uint16>(o_rule_map + m_sSuccess*sizeof(uint16));
|
||||
const byte * const rule_map = p;
|
||||
p += numEntries*sizeof(uint16);
|
||||
be::skip<uint16>(p, numEntries);
|
||||
|
||||
if (p > pass_end) return false;
|
||||
m_minPreCtxt = *p++;
|
||||
m_maxPreCtxt = *p++;
|
||||
m_minPreCtxt = be::read<uint8>(p);
|
||||
m_maxPreCtxt = be::read<uint8>(p);
|
||||
const byte * const start_states = p;
|
||||
p += (m_maxPreCtxt - m_minPreCtxt + 1)*sizeof(int16);
|
||||
be::skip<int16>(p, m_maxPreCtxt - m_minPreCtxt + 1);
|
||||
const uint16 * const sort_keys = reinterpret_cast<const uint16 *>(p);
|
||||
p += m_numRules*sizeof(uint16);
|
||||
be::skip<uint16>(p, m_numRules);
|
||||
const byte * const precontext = p;
|
||||
p += m_numRules;
|
||||
p += sizeof(byte); // skip reserved byte
|
||||
be::skip<byte>(p, m_numRules);
|
||||
be::skip<byte>(p); // skip reserved byte
|
||||
|
||||
if (p > pass_end) return false;
|
||||
const size_t pass_constraint_len = be::read<uint16>(p);
|
||||
const uint16 * const o_constraint = reinterpret_cast<const uint16 *>(p);
|
||||
p += (m_numRules + 1)*sizeof(uint16);
|
||||
be::skip<uint16>(p, m_numRules + 1);
|
||||
const uint16 * const o_actions = reinterpret_cast<const uint16 *>(p);
|
||||
p += (m_numRules + 1)*sizeof(uint16);
|
||||
be::skip<uint16>(p, m_numRules + 1);
|
||||
const byte * const states = p;
|
||||
p += m_sTransition*m_sColumns*sizeof(int16);
|
||||
p += sizeof(byte); // skip reserved byte
|
||||
be::skip<int16>(p, m_sTransition*m_sColumns);
|
||||
be::skip<byte>(p); // skip reserved byte
|
||||
if (p != pcCode || p >= pass_end) return false;
|
||||
p += pass_constraint_len;
|
||||
if (p != rcCode || p >= pass_end) return false;
|
||||
p += be::peek<uint16>(o_constraint + m_numRules);
|
||||
be::skip<byte>(p, pass_constraint_len);
|
||||
if (p != rcCode || p >= pass_end
|
||||
|| size_t(rcCode - pcCode) != pass_constraint_len) return false;
|
||||
be::skip<byte>(p, be::peek<uint16>(o_constraint + m_numRules));
|
||||
if (p != aCode || p >= pass_end) return false;
|
||||
if (size_t(rcCode - pcCode) != pass_constraint_len) return false;
|
||||
be::skip<byte>(p, be::peek<uint16>(o_actions + m_numRules));
|
||||
|
||||
// We should be at the end or within the pass
|
||||
if (p > pass_end) return false;
|
||||
|
||||
// Load the pass constraint if there is one.
|
||||
if (pass_constraint_len)
|
||||
|
@ -475,14 +475,15 @@ bool Pass::testPassConstraint(Machine & m) const
|
|||
}
|
||||
|
||||
|
||||
bool Pass::testConstraint(const Rule &r, Machine & m) const
|
||||
bool Pass::testConstraint(const Rule & r, Machine & m) const
|
||||
{
|
||||
if ((r.sort - r.preContext) > (m.slotMap().size() - m.slotMap().context())) return false;
|
||||
if (m.slotMap().context() - r.preContext < 0) return false;
|
||||
if (!*r.constraint) return true;
|
||||
const uint16 curr_context = m.slotMap().context();
|
||||
if (unsigned(r.sort - r.preContext) > m.slotMap().size() - curr_context
|
||||
|| curr_context - r.preContext < 0) return false;
|
||||
if (!*r.constraint) return true;
|
||||
assert(r.constraint->constraint());
|
||||
|
||||
vm::slotref * map = m.slotMap().begin() + m.slotMap().context() - r.preContext;
|
||||
vm::slotref * map = m.slotMap().begin() + curr_context - r.preContext;
|
||||
for (int n = r.sort; n && map; --n, ++map)
|
||||
{
|
||||
if (!*map) continue;
|
||||
|
|
|
@ -144,7 +144,7 @@ SegCacheEntry* SegCache::cache(SegCacheStore * store, const uint16* cmapGlyphs,
|
|||
|
||||
void SegCache::purge(SegCacheStore * store)
|
||||
{
|
||||
unsigned long long minAccessCount = m_totalAccessCount * m_purgeFactor + 1;
|
||||
unsigned long long minAccessCount = static_cast<unsigned long long>(m_totalAccessCount * m_purgeFactor + 1);
|
||||
if (minAccessCount < 2) minAccessCount = 2;
|
||||
unsigned long long oldAccessTime = m_totalAccessCount - store->maxSegmentCount() / eAgeFactor;
|
||||
purgeLevel(store, m_prefixes, 0, minAccessCount, oldAccessTime);
|
||||
|
|
|
@ -52,31 +52,19 @@ SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment *
|
|||
m_glyphLength = glyphCount;
|
||||
Slot * slotCopy = m_glyph;
|
||||
m_glyph->prev(NULL);
|
||||
struct Index2Slot {
|
||||
Index2Slot(uint16 i, const Slot * s) : m_i(i), m_slot(s) {};
|
||||
Index2Slot() : m_i(0), m_slot(NULL) {};
|
||||
uint16 m_i;
|
||||
const Slot * m_slot;
|
||||
};
|
||||
struct Index2Slot parentGlyphs[eMaxSpliceSize];
|
||||
struct Index2Slot childGlyphs[eMaxSpliceSize];
|
||||
uint16 numParents = 0;
|
||||
uint16 numChildren = 0;
|
||||
|
||||
uint16 pos = 0;
|
||||
while (slot)
|
||||
{
|
||||
slotCopy->userAttrs(m_attr + pos * seg->numAttrs());
|
||||
slotCopy->set(*slot, -static_cast<int32>(charOffset), seg->numAttrs());
|
||||
slotCopy->index(pos);
|
||||
if (slot->firstChild())
|
||||
{
|
||||
new(parentGlyphs + numParents) Index2Slot( pos, slot );
|
||||
++numParents;
|
||||
}
|
||||
slotCopy->m_child = m_glyph + slot->firstChild()->index();
|
||||
if (slot->attachedTo())
|
||||
{
|
||||
new(childGlyphs + numChildren) Index2Slot( pos, slot );
|
||||
++numChildren;
|
||||
}
|
||||
slotCopy->attachTo(m_glyph + slot->attachedTo()->index());
|
||||
if (slot->nextSibling())
|
||||
slotCopy->m_sibling = m_glyph + slot->nextSibling()->index();
|
||||
slot = slot->next();
|
||||
++slotCopy;
|
||||
++pos;
|
||||
|
@ -86,45 +74,6 @@ SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment *
|
|||
(slotCopy-1)->next(slotCopy);
|
||||
}
|
||||
}
|
||||
// loop over the attached children finding their siblings and parents
|
||||
for (int16 i = 0; i < numChildren; i++)
|
||||
{
|
||||
if (childGlyphs[i].m_slot->nextSibling())
|
||||
{
|
||||
for (int16 j = i; j < numChildren; j++)
|
||||
{
|
||||
if (childGlyphs[i].m_slot->nextSibling() == childGlyphs[j].m_slot)
|
||||
{
|
||||
m_glyph[childGlyphs[i].m_i].sibling(m_glyph + childGlyphs[j].m_i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!m_glyph[childGlyphs[i].m_i].nextSibling())
|
||||
{
|
||||
// search backwards
|
||||
for (int16 j = i-1; j >= 0; j--)
|
||||
{
|
||||
if (childGlyphs[i].m_slot->nextSibling() == childGlyphs[j].m_slot)
|
||||
{
|
||||
m_glyph[childGlyphs[i].m_i].sibling(m_glyph + childGlyphs[j].m_i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// now find the parent glyph
|
||||
for (int16 j = 0; j < numParents; j++)
|
||||
{
|
||||
if (childGlyphs[i].m_slot->attachedTo() == parentGlyphs[j].m_slot)
|
||||
{
|
||||
m_glyph[childGlyphs[i].m_i].attachTo(m_glyph + parentGlyphs[j].m_i);
|
||||
if (parentGlyphs[j].m_slot->firstChild() == childGlyphs[i].m_slot)
|
||||
{
|
||||
m_glyph[parentGlyphs[j].m_i].child(m_glyph + childGlyphs[i].m_i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -204,86 +204,57 @@ void Segment::freeSlot(Slot *aSlot)
|
|||
}
|
||||
|
||||
#ifndef GRAPHITE2_NSEGCACHE
|
||||
void Segment::splice(size_t offset, size_t length, Slot * startSlot,
|
||||
Slot * endSlot, const Slot * firstSpliceSlot,
|
||||
size_t numGlyphs)
|
||||
void Segment::splice(size_t offset, size_t length, Slot * const startSlot,
|
||||
Slot * endSlot, const Slot * srcSlot,
|
||||
const size_t numGlyphs)
|
||||
{
|
||||
const Slot * replacement = firstSpliceSlot;
|
||||
Slot * slot = startSlot;
|
||||
extendLength(numGlyphs - length);
|
||||
// insert extra slots if needed
|
||||
while (numGlyphs > length)
|
||||
{
|
||||
Slot * extra = newSlot();
|
||||
extra->prev(endSlot);
|
||||
extra->next(endSlot->next());
|
||||
endSlot->next(extra);
|
||||
if (extra->next())
|
||||
extra->next()->prev(extra);
|
||||
if (m_last == endSlot)
|
||||
m_last = extra;
|
||||
endSlot = extra;
|
||||
++length;
|
||||
}
|
||||
// remove any extra
|
||||
if (numGlyphs < length)
|
||||
{
|
||||
Slot * afterSplice = endSlot->next();
|
||||
Slot * end = endSlot->next();
|
||||
do
|
||||
{
|
||||
endSlot = endSlot->prev();
|
||||
freeSlot(endSlot->next());
|
||||
--length;
|
||||
} while (numGlyphs < length);
|
||||
endSlot->next(afterSplice);
|
||||
if (afterSplice)
|
||||
afterSplice->prev(endSlot);
|
||||
} while (numGlyphs < --length);
|
||||
endSlot->next(end);
|
||||
if (end)
|
||||
end->prev(endSlot);
|
||||
}
|
||||
assert(numGlyphs == length);
|
||||
// keep a record of consecutive slots wrt start of splice to minimize
|
||||
// iterative next/prev calls
|
||||
Slot * slotArray[eMaxSpliceSize];
|
||||
uint16 slotPosition = 0;
|
||||
for (uint16 i = 0; i < numGlyphs; i++)
|
||||
else
|
||||
{
|
||||
if (slotPosition <= i)
|
||||
// insert extra slots if needed
|
||||
while (numGlyphs > length)
|
||||
{
|
||||
slotArray[i] = slot;
|
||||
slotPosition = i;
|
||||
Slot * extra = newSlot();
|
||||
extra->prev(endSlot);
|
||||
extra->next(endSlot->next());
|
||||
endSlot->next(extra);
|
||||
if (extra->next())
|
||||
extra->next()->prev(extra);
|
||||
if (m_last == endSlot)
|
||||
m_last = extra;
|
||||
endSlot = extra;
|
||||
++length;
|
||||
}
|
||||
slot->set(*replacement, offset, m_silf->numUser());
|
||||
if (replacement->attachedTo())
|
||||
{
|
||||
uint16 parentPos = replacement->attachedTo() - firstSpliceSlot;
|
||||
while (slotPosition < parentPos)
|
||||
{
|
||||
slotArray[slotPosition+1] = slotArray[slotPosition]->next();
|
||||
++slotPosition;
|
||||
}
|
||||
slot->attachTo(slotArray[parentPos]);
|
||||
}
|
||||
if (replacement->nextSibling())
|
||||
{
|
||||
uint16 pos = replacement->nextSibling() - firstSpliceSlot;
|
||||
while (slotPosition < pos)
|
||||
{
|
||||
slotArray[slotPosition+1] = slotArray[slotPosition]->next();
|
||||
++slotPosition;
|
||||
}
|
||||
slot->sibling(slotArray[pos]);
|
||||
}
|
||||
if (replacement->firstChild())
|
||||
{
|
||||
uint16 pos = replacement->firstChild() - firstSpliceSlot;
|
||||
while (slotPosition < pos)
|
||||
{
|
||||
slotArray[slotPosition+1] = slotArray[slotPosition]->next();
|
||||
++slotPosition;
|
||||
}
|
||||
slot->child(slotArray[pos]);
|
||||
}
|
||||
slot = slot->next();
|
||||
replacement = replacement->next();
|
||||
}
|
||||
|
||||
endSlot = endSlot->next();
|
||||
assert(numGlyphs == length);
|
||||
Slot * indexmap[eMaxSpliceSize*3];
|
||||
assert(numGlyphs < sizeof indexmap/sizeof *indexmap);
|
||||
Slot * slot = startSlot;
|
||||
for (uint16 i=0; i < numGlyphs; slot = slot->next(), ++i)
|
||||
indexmap[i] = slot;
|
||||
|
||||
slot = startSlot;
|
||||
for (slot=startSlot; slot != endSlot; slot = slot->next(), srcSlot = srcSlot->next())
|
||||
{
|
||||
slot->set(*srcSlot, offset, m_silf->numUser());
|
||||
if (srcSlot->attachedTo()) slot->attachTo(indexmap[srcSlot->attachedTo()->index()]);
|
||||
if (srcSlot->nextSibling()) slot->m_sibling = indexmap[srcSlot->nextSibling()->index()];
|
||||
if (srcSlot->firstChild()) slot->m_child = indexmap[srcSlot->firstChild()->index()];
|
||||
}
|
||||
}
|
||||
#endif // GRAPHITE2_NSEGCACHE
|
||||
|
@ -347,6 +318,24 @@ Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd)
|
|||
}
|
||||
|
||||
|
||||
void Segment::associateChars()
|
||||
{
|
||||
int i = 0;
|
||||
for (Slot * s = m_first; s; s->index(i++), s = s->next())
|
||||
{
|
||||
int j = s->before();
|
||||
if (j < 0) continue;
|
||||
|
||||
for (const int after = s->after(); j <= after; ++j)
|
||||
{
|
||||
CharInfo & c = *charinfo(j);
|
||||
if (c.before() == -1 || i < c.before()) c.before(i);
|
||||
if (c.after() < i) c.after(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename utf_iter>
|
||||
inline void process_utf_data(Segment & seg, const Face & face, const int fid, utf_iter c, size_t n_chars)
|
||||
{
|
||||
|
@ -382,38 +371,16 @@ void Segment::prepare_pos(const Font * /*font*/)
|
|||
// copy key changeable metrics into slot (if any);
|
||||
}
|
||||
|
||||
void Segment::finalise(const Font *font)
|
||||
{
|
||||
if (!m_first) return;
|
||||
|
||||
m_advance = positionSlots(font);
|
||||
int i = 0;
|
||||
for (Slot * s = m_first; s; s->index(i++), s = s->next())
|
||||
{
|
||||
int j = s->before();
|
||||
if (j < 0) continue;
|
||||
|
||||
for (const int after = s->after(); j <= after; ++j)
|
||||
{
|
||||
CharInfo & c = *charinfo(j);
|
||||
if (c.before() == -1 || i < c.before()) c.before(i);
|
||||
if (c.after() < i) c.after(i);
|
||||
}
|
||||
}
|
||||
linkClusters(m_first, m_last);
|
||||
}
|
||||
|
||||
void Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUSED justFlags flags, Slot *pFirst, Slot *pLast)
|
||||
{
|
||||
Slot *pEnd = pSlot;
|
||||
Slot *s, *end;
|
||||
int numBase = 0;
|
||||
float currWidth = 0.;
|
||||
float scale = font ? font->scale() : 1.0;
|
||||
float base;
|
||||
float currWidth = 0.0;
|
||||
const float scale = font ? font->scale() : 1.0f;
|
||||
|
||||
if (!pFirst) pFirst = pSlot;
|
||||
base = pFirst->origin().x / scale;
|
||||
const float base = pFirst->origin().x / scale;
|
||||
width = width / scale;
|
||||
end = pLast ? pLast->next() : NULL;
|
||||
|
||||
|
@ -471,7 +438,7 @@ void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror)
|
|||
unsigned int bmask = 0;
|
||||
for (s = first(); s; s = s->next())
|
||||
{
|
||||
unsigned int bAttr = glyphAttr(s->gid(), aBidi);
|
||||
unsigned int bAttr = glyphAttr(s->gid(), aBidi);
|
||||
s->setBidiClass((bAttr <= 16) * bAttr);
|
||||
bmask |= (1 << s->getBidiClass());
|
||||
s->setBidiLevel(baseLevel);
|
||||
|
@ -486,7 +453,7 @@ void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror)
|
|||
resolveNeutrals(baseLevel, first());
|
||||
resolveImplicit(first(), this, aMirror);
|
||||
resolveWhitespace(baseLevel, this, aBidi, last());
|
||||
s = resolveOrder(s = first(), baseLevel);
|
||||
s = resolveOrder(s = first(), baseLevel != 0);
|
||||
first(s); last(s->prev());
|
||||
s->prev()->next(0); s->prev(0);
|
||||
}
|
||||
|
|
|
@ -64,86 +64,69 @@ void Silf::releaseBuffers() throw()
|
|||
}
|
||||
|
||||
|
||||
bool Silf::readGraphite(const void* pSilf, size_t lSilf, const Face& face, uint32 version)
|
||||
bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, const Face& face, uint32 version)
|
||||
{
|
||||
const byte * p = (byte *)pSilf,
|
||||
* const eSilf = p + lSilf;
|
||||
const byte * p = silf_start,
|
||||
* const silf_end = p + lSilf;
|
||||
|
||||
if (version >= 0x00030000)
|
||||
{
|
||||
if (lSilf < 27) { releaseBuffers(); return false; }
|
||||
p += 8;
|
||||
if (lSilf < 28) { releaseBuffers(); return false; }
|
||||
be::skip<int32>(p); // ruleVersion
|
||||
be::skip<uint16>(p,2); // passOffset & pseudosOffset
|
||||
}
|
||||
else if (lSilf < 19) { releaseBuffers(); return false; }
|
||||
p += 2; // maxGlyphID
|
||||
p += 4; // extra ascent/descent
|
||||
m_numPasses = uint8(*p++);
|
||||
if (m_numPasses > 128)
|
||||
return false;
|
||||
m_passes = new Pass[m_numPasses];
|
||||
m_sPass = uint8(*p++);
|
||||
m_pPass = uint8(*p++);
|
||||
if (m_pPass < m_sPass) {
|
||||
releaseBuffers();
|
||||
return false;
|
||||
}
|
||||
m_jPass = uint8(*p++);
|
||||
if (m_jPass < m_pPass) {
|
||||
releaseBuffers();
|
||||
return false;
|
||||
}
|
||||
m_bPass = uint8(*p++); // when do we reorder?
|
||||
if (m_bPass != 0xFF && (m_bPass < m_jPass || m_bPass > m_numPasses)) {
|
||||
releaseBuffers();
|
||||
return false;
|
||||
}
|
||||
m_flags = uint8(*p++);
|
||||
p += 2; // ignore line end contextuals for now
|
||||
m_aPseudo = uint8(*p++);
|
||||
m_aBreak = uint8(*p++);
|
||||
m_aBidi = uint8(*p++);
|
||||
m_aMirror = uint8(*p++);
|
||||
p += 1; // skip reserved stuff
|
||||
m_numJusts = uint8(*p++);
|
||||
else if (lSilf < 20) { releaseBuffers(); return false; }
|
||||
be::skip<uint16>(p); // maxGlyphID
|
||||
be::skip<int16>(p,2); // extra ascent & descent
|
||||
m_numPasses = be::read<uint8>(p);
|
||||
m_sPass = be::read<uint8>(p);
|
||||
m_pPass = be::read<uint8>(p);
|
||||
m_jPass = be::read<uint8>(p);
|
||||
m_bPass = be::read<uint8>(p);
|
||||
m_flags = be::read<uint8>(p);
|
||||
be::skip<uint8>(p,2); // max{Pre,Post}Context.
|
||||
m_aPseudo = be::read<uint8>(p);
|
||||
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
|
||||
|
||||
// Read Justification levels.
|
||||
m_numJusts = be::read<uint8>(p);
|
||||
if (p + m_numJusts * 8 >= silf_end) { releaseBuffers(); return false; }
|
||||
m_justs = gralloc<Justinfo>(m_numJusts);
|
||||
for (uint8 i = 0; i < m_numJusts; i++)
|
||||
{
|
||||
::new(m_justs + i) Justinfo(p[0], p[1], p[2], p[3]);
|
||||
p += 8;
|
||||
be::skip<byte>(p,8);
|
||||
}
|
||||
// p += uint8(*p) * 8 + 1; // ignore justification for now
|
||||
if (p + 9 >= eSilf) { releaseBuffers(); return false; }
|
||||
m_aLig = be::read<uint16>(p);
|
||||
if (m_aLig > 127) {
|
||||
releaseBuffers();
|
||||
return false;
|
||||
|
||||
if (p + sizeof(uint16) + sizeof(uint8)*8 >= silf_end) { releaseBuffers(); return false; }
|
||||
m_aLig = be::read<uint16>(p);
|
||||
m_aUser = be::read<uint8>(p);
|
||||
m_iMaxComp = be::read<uint8>(p);
|
||||
be::skip<byte>(p,5); // direction and 4 reserved bytes
|
||||
be::skip<uint16>(p, be::read<uint8>(p)); // don't need critical features yet
|
||||
be::skip<byte>(p); // reserved
|
||||
if (p >= silf_end) { releaseBuffers(); return false; }
|
||||
be::skip<uint32>(p, be::read<uint8>(p)); // don't use scriptTag array.
|
||||
be::skip<uint16>(p); // lbGID
|
||||
const byte * o_passes = p,
|
||||
* const passes_start = silf_start + be::read<uint32>(p);
|
||||
|
||||
if (m_numPasses > 128 || passes_start >= silf_end
|
||||
|| m_pPass < m_sPass
|
||||
|| m_jPass < m_pPass
|
||||
|| (m_bPass != 0xFF && (m_bPass < m_jPass || m_bPass > m_numPasses))
|
||||
|| m_aLig > 127) {
|
||||
releaseBuffers(); return false;
|
||||
}
|
||||
m_aUser = uint8(*p++);
|
||||
m_iMaxComp = uint8(*p++);
|
||||
p += 5; // skip direction and reserved
|
||||
p += uint8(*p) * 2 + 1; // don't need critical features yet
|
||||
p++; // reserved
|
||||
if (p >= eSilf)
|
||||
{
|
||||
releaseBuffers();
|
||||
return false;
|
||||
}
|
||||
p += uint8(*p) * 4 + 1; // skip scripts
|
||||
p += 2; // skip lbGID
|
||||
|
||||
if (p + 4 * (m_numPasses + 1) + 6 >= eSilf)
|
||||
{
|
||||
releaseBuffers();
|
||||
return false;
|
||||
}
|
||||
const byte * pPasses = p;
|
||||
p += 4 * (m_numPasses + 1);
|
||||
be::skip<uint32>(p, m_numPasses);
|
||||
if (p + sizeof(uint16) >= passes_start) { releaseBuffers(); return false; }
|
||||
m_numPseudo = be::read<uint16>(p);
|
||||
p += 6;
|
||||
if (p + m_numPseudo * 6 >= eSilf)
|
||||
{
|
||||
releaseBuffers();
|
||||
return false;
|
||||
be::skip<uint16>(p, 3); // searchPseudo, pseudoSelector, pseudoShift
|
||||
if (p + m_numPseudo*(sizeof(uint32) + sizeof(uint16)) >= passes_start) {
|
||||
releaseBuffers(); return false;
|
||||
}
|
||||
m_pseudos = new Pseudo[m_numPseudo];
|
||||
for (int i = 0; i < m_numPseudo; i++)
|
||||
|
@ -151,30 +134,21 @@ bool Silf::readGraphite(const void* pSilf, size_t lSilf, const Face& face, uint3
|
|||
m_pseudos[i].uid = be::read<uint32>(p);
|
||||
m_pseudos[i].gid = be::read<uint16>(p);
|
||||
}
|
||||
if (p >= eSilf)
|
||||
{
|
||||
releaseBuffers();
|
||||
return false;
|
||||
}
|
||||
|
||||
int clen = readClassMap(p, be::peek<uint32>(pPasses) - (p - (byte *)pSilf), version);
|
||||
if (clen < 0) {
|
||||
releaseBuffers();
|
||||
return false;
|
||||
}
|
||||
p += clen;
|
||||
const size_t clen = readClassMap(p, passes_start - p, version);
|
||||
if (clen == 0 || p + clen > passes_start) { releaseBuffers(); return false; }
|
||||
|
||||
m_passes = new Pass[m_numPasses];
|
||||
for (size_t i = 0; i < m_numPasses; ++i)
|
||||
{
|
||||
uint32 pOffset = be::read<uint32>(pPasses);
|
||||
uint32 pEnd = be::peek<uint32>(pPasses);
|
||||
if ((uint8 *)pSilf + pEnd > eSilf || pOffset > pEnd)
|
||||
{
|
||||
releaseBuffers();
|
||||
return false;
|
||||
const byte * const pass_start = silf_start + be::read<uint32>(o_passes),
|
||||
* const pass_end = silf_start + be::peek<uint32>(o_passes);
|
||||
if (pass_start > pass_end || pass_end > silf_end) {
|
||||
releaseBuffers(); return false;
|
||||
}
|
||||
|
||||
m_passes[i].init(this);
|
||||
if (!m_passes[i].readPass((char *)pSilf + pOffset, pEnd - pOffset, pOffset, face))
|
||||
if (!m_passes[i].readPass(pass_start, pass_end - pass_start, pass_start - silf_start, face))
|
||||
{
|
||||
releaseBuffers();
|
||||
return false;
|
||||
|
@ -204,7 +178,7 @@ template<typename T> inline uint32 Silf::readClassOffsets(const byte *&p, size_t
|
|||
|
||||
size_t Silf::readClassMap(const byte *p, size_t data_len, uint32 version)
|
||||
{
|
||||
if (data_len < sizeof(uint16)*2) return -1;
|
||||
if (data_len < sizeof(uint16)*2) return 0;
|
||||
|
||||
m_nClass = be::read<uint16>(p);
|
||||
m_nLinear = be::read<uint16>(p);
|
||||
|
@ -213,7 +187,7 @@ size_t Silf::readClassMap(const byte *p, size_t data_len, uint32 version)
|
|||
// that there is at least enough data for numClasses offsets.
|
||||
if (m_nLinear > m_nClass
|
||||
|| (m_nClass + 1) * (version >= 0x00040000 ? sizeof(uint32) : sizeof(uint16))> (data_len - 4))
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
|
||||
uint32 max_off;
|
||||
|
@ -222,12 +196,12 @@ size_t Silf::readClassMap(const byte *p, size_t data_len, uint32 version)
|
|||
else
|
||||
max_off = readClassOffsets<uint16>(p, data_len);
|
||||
|
||||
if (max_off == 0) return -1;
|
||||
if (max_off == 0) return 0;
|
||||
|
||||
// Check the linear offsets are sane, these must be monotonically increasing.
|
||||
for (const uint32 *o = m_classOffsets, * const o_end = o + m_nLinear; o != o_end; ++o)
|
||||
if (o[0] > o[1])
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
// Fortunately the class data is all uint16s so we can decode these now
|
||||
m_classData = gralloc<uint16>(max_off);
|
||||
|
@ -241,7 +215,7 @@ size_t Silf::readClassMap(const byte *p, size_t data_len, uint32 version)
|
|||
if (lookup[0] == 0 // A LookupClass with no looks is a suspicious thing ...
|
||||
|| lookup[0] > (max_off - *o - 4)/2 // numIDs lookup pairs fits within (start of LookupClass' lookups array, max_off]
|
||||
|| lookup[3] != lookup[0] - lookup[1]) // rangeShift: numIDs - searchRange
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return max_off;
|
||||
|
@ -271,7 +245,7 @@ uint16 Silf::findClassIndex(uint16 cid, uint16 gid) const
|
|||
* max = min + cls[0]*2; // lookups aray is numIDs (cls[0]) uint16 pairs long
|
||||
do
|
||||
{
|
||||
const uint16 * p = min + (-2U & ((max-min)/2));
|
||||
const uint16 * p = min + (-2 & ((max-min)/2));
|
||||
if (p[0] > gid) max = p;
|
||||
else min = p;
|
||||
}
|
||||
|
|
|
@ -205,7 +205,7 @@ int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
|
|||
{
|
||||
case gr_slatAdvX : return int(m_advance.x);
|
||||
case gr_slatAdvY : return int(m_advance.y);
|
||||
case gr_slatAttTo : return 0;
|
||||
case gr_slatAttTo : return m_parent ? 1 : 0;
|
||||
case gr_slatAttX : return int(m_attach.x);
|
||||
case gr_slatAttY : return int(m_attach.y);
|
||||
case gr_slatAttXOff :
|
||||
|
@ -229,8 +229,9 @@ int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
|
|||
case gr_slatJShrink :
|
||||
case gr_slatJStep :
|
||||
case gr_slatJWeight : return 0;
|
||||
case gr_slatJWidth : return m_just;
|
||||
case gr_slatJWidth : return int(m_just);
|
||||
case gr_slatUserDefn : return m_userAttr[subindex];
|
||||
case gr_slatSegSplit : return seg->charinfo(m_original)->flags() & 3;
|
||||
default : return 0;
|
||||
}
|
||||
}
|
||||
|
@ -291,6 +292,7 @@ void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, cons
|
|||
case gr_slatJStep : break;
|
||||
case gr_slatJWeight : break;
|
||||
case gr_slatJWidth : m_just = value; break;
|
||||
case gr_slatSegSplit : seg->charinfo(m_original)->addflags(value & 3); break;
|
||||
case gr_slatUserDefn : m_userAttr[subindex] = value; break;
|
||||
default :
|
||||
break;
|
||||
|
|
|
@ -50,7 +50,7 @@ sparse::~sparse() throw()
|
|||
|
||||
sparse::value sparse::operator [] (int k) const throw()
|
||||
{
|
||||
bool g = k < m_nchunks*SIZEOF_CHUNK; // This will be 0 is were out of bounds
|
||||
value g = value(k < m_nchunks*SIZEOF_CHUNK); // This will be 0 is were out of bounds
|
||||
k *= g; // Force k to 0 if out of bounds making the map look up safe
|
||||
const chunk & c = m_array.map[k/SIZEOF_CHUNK];
|
||||
const mask_t m = c.mask >> (SIZEOF_CHUNK - 1 - (k%SIZEOF_CHUNK));
|
||||
|
|
|
@ -798,7 +798,7 @@ bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize, const void
|
|||
size_t cLongHorMetrics = be::swap(phhea->num_long_hor_metrics);
|
||||
if (nGlyphId < cLongHorMetrics)
|
||||
{ // glyph id is acceptable
|
||||
if (nGlyphId * sizeof(Sfnt::HorizontalMetric) > lHmtxSize) return false;
|
||||
if (nGlyphId * sizeof(Sfnt::HorizontalMetric) >= lHmtxSize) return false;
|
||||
nAdvWid = be::swap(phmtx[nGlyphId].advance_width);
|
||||
nLsb = be::swap(phmtx[nGlyphId].left_side_bearing);
|
||||
}
|
||||
|
@ -1149,7 +1149,7 @@ size_t LocaLookup(gid16 nGlyphId,
|
|||
// CheckTable verifies the index_to_loc_format is valid
|
||||
if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::ShortIndexLocFormat)
|
||||
{ // loca entries are two bytes and have been divided by two
|
||||
if (nGlyphId <= (lLocaSize >> 1) - 1) // allow sentinel value to be accessed
|
||||
if (nGlyphId < (lLocaSize >> 1) - 1) // allow sentinel value to be accessed
|
||||
{
|
||||
const uint16 * pShortTable = reinterpret_cast<const uint16 *>(pLoca);
|
||||
return (be::peek<uint16>(pShortTable + nGlyphId) << 1);
|
||||
|
@ -1158,7 +1158,7 @@ size_t LocaLookup(gid16 nGlyphId,
|
|||
|
||||
if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::LongIndexLocFormat)
|
||||
{ // loca entries are four bytes
|
||||
if (nGlyphId <= (lLocaSize >> 2) - 1)
|
||||
if (nGlyphId < (lLocaSize >> 2) - 1)
|
||||
{
|
||||
const uint32 * pLongTable = reinterpret_cast<const uint32 *>(pLoca);
|
||||
return be::peek<uint32>(pLongTable + nGlyphId);
|
||||
|
|
|
@ -104,7 +104,7 @@ Machine::stack_t Machine::run(const instr * program,
|
|||
|
||||
{
|
||||
assert(program != 0);
|
||||
assert(_status == finished);
|
||||
// assert(_status == finished);
|
||||
|
||||
|
||||
// Declare virtual machine registers
|
||||
|
|
|
@ -107,7 +107,7 @@ Machine::stack_t Machine::run(const instr * program,
|
|||
slotref * & is)
|
||||
{
|
||||
assert(program != 0);
|
||||
assert(_status == finished);
|
||||
// assert(_status == finished);
|
||||
|
||||
const stack_t *sp = static_cast<const stack_t *>(
|
||||
direct_run(false, program, data, _stack, is, &_map));
|
||||
|
|
|
@ -121,14 +121,15 @@ void gr_tag_to_str(gr_uint32 tag, char *str)
|
|||
}
|
||||
}
|
||||
|
||||
#define zeropad(x) if (x == 0x20202020) x = 0; \
|
||||
else if ((x & 0x00FFFFFF) == 0x00202020) x = x & 0xFF000000; \
|
||||
else if ((x & 0x0000FFFF) == 0x00002020) x = x & 0xFFFF0000; \
|
||||
else if ((x & 0x000000FF) == 0x00000020) x = x & 0xFFFFFF00;
|
||||
|
||||
gr_feature_val* gr_face_featureval_for_lang(const gr_face* pFace, gr_uint32 langname/*0 means clone default*/) //clones the features. if none for language, clones the default
|
||||
{
|
||||
assert(pFace);
|
||||
if (langname == 0x20202020) langname = 0;
|
||||
else if ((langname & 0x00FFFFFF) == 0x00202020) langname = langname & 0xFF000000;
|
||||
else if ((langname & 0x0000FFFF) == 0x00002020) langname = langname & 0xFFFF0000;
|
||||
else if ((langname & 0x000000FF) == 0x00000020) langname = langname & 0xFFFFFF00;
|
||||
zeropad(langname)
|
||||
return static_cast<gr_feature_val *>(pFace->theSill().cloneFeatures(langname));
|
||||
}
|
||||
|
||||
|
@ -136,6 +137,7 @@ gr_feature_val* gr_face_featureval_for_lang(const gr_face* pFace, gr_uint32 lang
|
|||
const gr_feature_ref* gr_face_find_fref(const gr_face* pFace, gr_uint32 featId) //When finished with the FeatureRef, call destroy_FeatureRef
|
||||
{
|
||||
assert(pFace);
|
||||
zeropad(featId)
|
||||
const FeatureRef* pRef = pFace->featureById(featId);
|
||||
return static_cast<const gr_feature_ref*>(pRef);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ bool graphite_start_logging(FILE * logFile, GrLogMask mask)
|
|||
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
dbgout = new json(logFile);
|
||||
return dbgout;
|
||||
return dbgout != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
@ -68,6 +68,7 @@ json & graphite2::operator << (json & j, const CharInfo & ci) throw()
|
|||
<< "offset" << ci.base()
|
||||
<< "unicode" << ci.unicodeChar()
|
||||
<< "break" << ci.breakWeight()
|
||||
<< "flags" << ci.flags()
|
||||
<< "slot" << json::flat << json::object
|
||||
<< "before" << ci.before()
|
||||
<< "after" << ci.after()
|
||||
|
@ -92,7 +93,8 @@ json & graphite2::operator << (json & j, const dslot & ds) throw()
|
|||
<< "after" << s.after()
|
||||
<< json::close
|
||||
<< "origin" << s.origin()
|
||||
<< "shift" << Position(s.getAttr(0, gr_slatShiftX, 0), s.getAttr(0, gr_slatShiftY, 0))
|
||||
<< "shift" << Position(float(s.getAttr(0, gr_slatShiftX, 0)),
|
||||
float(s.getAttr(0, gr_slatShiftY, 0)))
|
||||
<< "advance" << s.advancePos()
|
||||
<< "insert" << s.isInsertBefore()
|
||||
<< "break" << s.getAttr(&seg, gr_slatBreak, 0);
|
||||
|
|
|
@ -168,7 +168,7 @@ void gr_seg_justify(gr_segment* pSeg/*not NULL*/, gr_slot* pSlot/*not NULL*/, co
|
|||
{
|
||||
assert(pSeg);
|
||||
assert(pSlot);
|
||||
pSeg->justify(pSlot, pFont, width, justFlags(flags), pFirst, pLast);
|
||||
pSeg->justify(pSlot, pFont, float(width), justFlags(flags), pFirst, pLast);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
@ -33,6 +33,7 @@ of the License or (at your option) any later version.
|
|||
namespace graphite2 {
|
||||
|
||||
class SegCacheStore;
|
||||
class SegCache;
|
||||
|
||||
class CachedFace : public Face
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@ class CharInfo
|
|||
{
|
||||
|
||||
public:
|
||||
CharInfo() : m_before(-1), m_after(0) {}
|
||||
CharInfo() : m_before(-1), m_after(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; }
|
||||
|
@ -47,6 +47,8 @@ public:
|
|||
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:
|
||||
|
@ -56,6 +58,7 @@ private:
|
|||
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
|
||||
|
|
|
@ -154,7 +154,12 @@ private:
|
|||
inline Machine::Machine(SlotMap & map) throw()
|
||||
: _map(map), _status(finished)
|
||||
{
|
||||
memset(_stack, 0, STACK_GUARD);
|
||||
// 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()
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
Pass();
|
||||
~Pass();
|
||||
|
||||
bool readPass(void* pPass, size_t pass_length, size_t subtable_base, const Face & face);
|
||||
bool readPass(const byte * pPass, size_t pass_length, size_t subtable_base, const Face & face);
|
||||
void runGraphite(vm::Machine & m, FiniteStateMachine & fsm) const;
|
||||
void init(Silf *silf) { m_silf = silf; }
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class Position
|
|||
{
|
||||
public:
|
||||
Position() : x(0), y(0) { }
|
||||
Position(float inx, float iny) { x = inx; y = iny; }
|
||||
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); }
|
||||
|
|
|
@ -53,7 +53,7 @@ class Segment;
|
|||
enum SpliceParam {
|
||||
/** sub-Segments longer than this are not cached
|
||||
* (in Unicode code points) */
|
||||
eMaxSpliceSize = 16
|
||||
eMaxSpliceSize = 96
|
||||
};
|
||||
|
||||
enum justFlags {
|
||||
|
@ -92,8 +92,9 @@ public:
|
|||
SegmentScopeState setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength);
|
||||
void removeScope(SegmentScopeState & state);
|
||||
void append(const Segment &other);
|
||||
void splice(size_t offset, size_t length, Slot * startSlot, Slot * endSlot,
|
||||
const Slot * firstSpliceSlot, size_t numGlyphs);
|
||||
void splice(size_t offset, size_t length, Slot * const startSlot,
|
||||
Slot * endSlot, const Slot * srcSlot,
|
||||
const size_t numGlyphs);
|
||||
#endif
|
||||
Slot *first() { return m_first; }
|
||||
void first(Slot *p) { m_first = p; }
|
||||
|
@ -103,6 +104,7 @@ public:
|
|||
Slot *newSlot();
|
||||
void freeSlot(Slot *);
|
||||
Position positionSlots(const Font *font, Slot *first=0, Slot *last=0);
|
||||
void associateChars();
|
||||
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); }
|
||||
|
@ -110,15 +112,7 @@ public:
|
|||
uint16 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, uint8 gattr) const { return m_face->glyphAttr(gid, gattr); }
|
||||
uint16 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const {
|
||||
if (attrLevel > 0)
|
||||
{
|
||||
Slot *is = findRoot(iSlot);
|
||||
return is->clusterMetric(this, metric, attrLevel);
|
||||
}
|
||||
else
|
||||
return m_face->getGlyphMetric(iSlot->gid(), metric);
|
||||
}
|
||||
uint16 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const;
|
||||
float glyphAdvance(uint16 gid) const { return m_face->getAdvance(gid, 1.0); }
|
||||
const Rect &theGlyphBBoxTemporary(uint16 gid) const { return m_face->theBBoxTemporary(gid); } //warning value may become invalid when another glyph is accessed
|
||||
Slot *findRoot(Slot *is) const { return is->attachedTo() ? findRoot(is->attachedTo()) : is; }
|
||||
|
@ -160,6 +154,29 @@ private: //defensive on m_charinfo
|
|||
Segment& operator=(const Segment&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline
|
||||
void Segment::finalise(const Font *font)
|
||||
{
|
||||
if (!m_first) return;
|
||||
|
||||
m_advance = positionSlots(font);
|
||||
associateChars();
|
||||
linkClusters(m_first, m_last);
|
||||
}
|
||||
|
||||
inline
|
||||
uint16 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const {
|
||||
if (attrLevel > 0)
|
||||
{
|
||||
Slot *is = findRoot(iSlot);
|
||||
return is->clusterMetric(this, metric, attrLevel);
|
||||
}
|
||||
else
|
||||
return m_face->getGlyphMetric(iSlot->gid(), metric);
|
||||
}
|
||||
|
||||
} // namespace graphite2
|
||||
|
||||
struct gr_segment : public graphite2::Segment {};
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
Silf() throw();
|
||||
~Silf() throw();
|
||||
|
||||
bool readGraphite(const void *pSilf, size_t lSilf, const Face &face, uint32 version);
|
||||
bool readGraphite(const byte * const pSilf, size_t lSilf, const Face &face, uint32 version);
|
||||
bool runGraphite(Segment *seg, uint8 firstPass=0, uint8 lastPass=0) const;
|
||||
uint16 findClassIndex(uint16 cid, uint16 gid) const;
|
||||
uint16 getClassGlyph(uint16 cid, unsigned int index) const;
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace graphite2 {
|
|||
typedef gr_attrCode attrCode;
|
||||
|
||||
class Segment;
|
||||
class SegCacheEntry;
|
||||
|
||||
class Slot
|
||||
{
|
||||
|
@ -134,6 +135,9 @@ private:
|
|||
byte m_bidiCls; // bidirectional class
|
||||
byte m_bidiLevel; // bidirectional level
|
||||
int16 *m_userAttr; // pointer to user attributes
|
||||
|
||||
friend class SegCacheEntry;
|
||||
friend class Segment;
|
||||
};
|
||||
|
||||
} // namespace graphite2
|
||||
|
|
|
@ -27,7 +27,9 @@ of the License or (at your option) any later version.
|
|||
// JSON debug logging
|
||||
// Author: Tim Eves
|
||||
|
||||
#include <stdio.h>
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
|
||||
#include <cstdio>
|
||||
#include "inc/json.h"
|
||||
|
||||
using namespace graphite2;
|
||||
|
@ -120,3 +122,5 @@ json & json::operator << (long unsigned d) throw() { context(seq); fprintf(_stre
|
|||
json & json::operator << (json::boolean b) throw() { context(seq); fputs(b ? "true" : "false", _stream); return *this; }
|
||||
json & json::operator << (json::_null_t) throw() { context(seq); fputs("null",_stream); return *this; }
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче