[ot-font] Accelerate cmap format4 get_glyph
This commit is contained in:
parent
e0f16a715b
commit
23335deaad
|
@ -69,61 +69,78 @@ struct CmapSubtableFormat0
|
|||
|
||||
struct CmapSubtableFormat4
|
||||
{
|
||||
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
|
||||
struct accelerator_t
|
||||
{
|
||||
unsigned int segCount;
|
||||
inline void init (const CmapSubtableFormat4 *subtable)
|
||||
{
|
||||
segCount = subtable->segCountX2 / 2;
|
||||
endCount = subtable->values;
|
||||
startCount = endCount + segCount + 1;
|
||||
idDelta = startCount + segCount;
|
||||
idRangeOffset = idDelta + segCount;
|
||||
glyphIdArray = idRangeOffset + segCount;
|
||||
glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
|
||||
}
|
||||
|
||||
static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
|
||||
{
|
||||
const accelerator_t *thiz = (const accelerator_t *) obj;
|
||||
|
||||
/* Custom two-array bsearch. */
|
||||
int min = 0, max = (int) thiz->segCount - 1;
|
||||
const USHORT *startCount = thiz->startCount;
|
||||
const USHORT *endCount = thiz->endCount;
|
||||
unsigned int i;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
if (codepoint < startCount[mid])
|
||||
max = mid - 1;
|
||||
else if (codepoint > endCount[mid])
|
||||
min = mid + 1;
|
||||
else
|
||||
{
|
||||
i = mid;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
found:
|
||||
hb_codepoint_t gid;
|
||||
unsigned int rangeOffset = thiz->idRangeOffset[i];
|
||||
if (rangeOffset == 0)
|
||||
gid = codepoint + thiz->idDelta[i];
|
||||
else
|
||||
{
|
||||
/* Somebody has been smoking... */
|
||||
unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
|
||||
if (unlikely (index >= thiz->glyphIdArrayLength))
|
||||
return false;
|
||||
gid = thiz->glyphIdArray[index];
|
||||
if (unlikely (!gid))
|
||||
return false;
|
||||
gid += thiz->idDelta[i];
|
||||
}
|
||||
|
||||
*glyph = gid & 0xFFFFu;
|
||||
return true;
|
||||
}
|
||||
|
||||
const USHORT *endCount;
|
||||
const USHORT *startCount;
|
||||
const USHORT *idDelta;
|
||||
const USHORT *idRangeOffset;
|
||||
const USHORT *glyphIdArray;
|
||||
unsigned int segCount;
|
||||
unsigned int glyphIdArrayLength;
|
||||
};
|
||||
|
||||
segCount = this->segCountX2 / 2;
|
||||
endCount = this->values;
|
||||
startCount = endCount + segCount + 1;
|
||||
idDelta = startCount + segCount;
|
||||
idRangeOffset = idDelta + segCount;
|
||||
glyphIdArray = idRangeOffset + segCount;
|
||||
glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2;
|
||||
|
||||
/* Custom two-array bsearch. */
|
||||
int min = 0, max = (int) segCount - 1;
|
||||
unsigned int i;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
if (codepoint < startCount[mid])
|
||||
max = mid - 1;
|
||||
else if (codepoint > endCount[mid])
|
||||
min = mid + 1;
|
||||
else
|
||||
{
|
||||
i = mid;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
found:
|
||||
hb_codepoint_t gid;
|
||||
unsigned int rangeOffset = idRangeOffset[i];
|
||||
if (rangeOffset == 0)
|
||||
gid = codepoint + idDelta[i];
|
||||
else
|
||||
{
|
||||
/* Somebody has been smoking... */
|
||||
unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount;
|
||||
if (unlikely (index >= glyphIdArrayLength))
|
||||
return false;
|
||||
gid = glyphIdArray[index];
|
||||
if (unlikely (!gid))
|
||||
return false;
|
||||
gid += idDelta[i];
|
||||
}
|
||||
|
||||
*glyph = gid & 0xFFFFu;
|
||||
return true;
|
||||
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
|
||||
{
|
||||
accelerator_t accel;
|
||||
accel.init (this);
|
||||
return accel.get_glyph_func (&accel, codepoint, glyph);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
|
|
@ -218,6 +218,7 @@ struct hb_ot_face_cmap_accelerator_t
|
|||
{
|
||||
hb_cmap_get_glyph_func_t get_glyph_func;
|
||||
const void *get_glyph_data;
|
||||
OT::CmapSubtableFormat4::accelerator_t format4_accel;
|
||||
|
||||
const OT::CmapSubtableFormat14 *uvs_table;
|
||||
hb_blob_t *blob;
|
||||
|
@ -255,8 +256,19 @@ struct hb_ot_face_cmap_accelerator_t
|
|||
|
||||
this->uvs_table = subtable_uvs;
|
||||
|
||||
this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;
|
||||
this->get_glyph_data = subtable;
|
||||
switch (subtable->u.format) {
|
||||
/* Accelerate format 4 and format 12. */
|
||||
default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>; break;
|
||||
case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>; break;
|
||||
case 4:
|
||||
{
|
||||
this->format4_accel.init (&subtable->u.format4);
|
||||
this->get_glyph_data = &this->format4_accel;
|
||||
this->get_glyph_func = this->format4_accel.get_glyph_func;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
|
|
Loading…
Reference in New Issue