return_trace (c->check_struct (this));
}
+ inline void get_extents (hb_glyph_extents_t *extents) const
+ {
+ extents->x_bearing = bearingX;
+ extents->y_bearing = bearingY;
+ extents->width = width;
+ extents->height = height;
+ }
+
BYTE height;
BYTE width;
CHAR bearingX;
/*
* Index Subtables.
*/
-struct IndexSubtable
+struct IndexSubtableHeader
{
- USHORT firstGlyphIndex;
- USHORT lastGlyphIndex;
- ULONG offsetToSubtable;
-
- DEFINE_SIZE_STATIC(8);
-};
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
-struct IndexSubHeader
-{
USHORT indexFormat;
USHORT imageFormat;
ULONG imageDataOffset;
struct IndexSubtableFormat1
{
- IndexSubHeader header;
- ULONG offsetArrayZ[VAR];
+ inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
+ }
+
+ bool get_image_data (unsigned int idx,
+ unsigned int *offset,
+ unsigned int *length) const
+ {
+ if (unlikely (offsetArrayZ[idx + 1] <= offsetArrayZ[idx]))
+ return false;
+
+ *offset = header.imageDataOffset + offsetArrayZ[idx];
+ *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx];
+ return true;
+ }
+
+ IndexSubtableHeader header;
+ Offset<ULONG> offsetArrayZ[VAR];
DEFINE_SIZE_ARRAY(8, offsetArrayZ);
};
+struct IndexSubtable
+{
+ inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.header.sanitize (c)) return_trace (false);
+ switch (u.header.indexFormat) {
+ case 1: return_trace (u.format1.sanitize (c, glyph_count));
+ default:return_trace (true);
+ }
+ }
+
+ inline bool get_extents (hb_glyph_extents_t *extents) const
+ {
+ switch (u.header.indexFormat) {
+ case 2: case 5: /* TODO */
+ case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */
+ default:return (false);
+ }
+ }
+
+ bool get_image_data (unsigned int idx,
+ unsigned int *offset,
+ unsigned int *length,
+ unsigned int *format) const
+ {
+ *format = u.header.imageFormat;
+ switch (u.header.indexFormat) {
+ case 1: return u.format1.get_image_data (idx, offset, length);
+ default: return false;
+ }
+ }
+
+ protected:
+ union {
+ IndexSubtableHeader header;
+ IndexSubtableFormat1 format1;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (8, header);
+};
+
+struct IndexSubtableRecord
+{
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ firstGlyphIndex <= lastGlyphIndex &&
+ offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1));
+ }
+
+ inline bool get_extents (hb_glyph_extents_t *extents) const
+ {
+ return (this+offsetToSubtable).get_extents (extents);
+ }
+
+ bool get_image_data (unsigned int gid,
+ unsigned int *offset,
+ unsigned int *length,
+ unsigned int *format) const
+ {
+ if (gid < firstGlyphIndex || gid > lastGlyphIndex)
+ {
+ return false;
+ }
+ return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
+ offset, length, format);
+ }
+
+ USHORT firstGlyphIndex;
+ USHORT lastGlyphIndex;
+ OffsetTo<IndexSubtable, ULONG> offsetToSubtable;
+
+ DEFINE_SIZE_STATIC(8);
+};
+
/*
* Glyph Bitmap Data Formats.
*/
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
- return_trace (c->check_struct (this)); // XXX
+ if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, sizeof (count))))
+ return_trace (false);
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
+ return_trace (false);
+ return_trace (true);
}
public:
- const IndexSubtable* find_table (hb_codepoint_t glyph, unsigned int numTables) const
+ const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
{
for (unsigned int i = 0; i < numTables; ++i)
{
}
protected:
- IndexSubtable indexSubtablesZ[VAR];
+ IndexSubtableRecord indexSubtablesZ[VAR];
public:
DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
return false;
}
- const OT::IndexSubtableArray& subtables =
- OT::StructAtOffset<OT::IndexSubtableArray> (this->cblc, sizeTable->indexSubtableArrayOffset);
- const OT::IndexSubtable* subtable = subtables.find_table(glyph, sizeTable->numberOfIndexSubtables);
- if (subtable == NULL) {
+ const OT::IndexSubtableArray& subtables = this->cblc + sizeTable->indexSubtableArrayOffset;
+ const OT::IndexSubtableRecord *subtable_record = subtables.find_table (glyph, sizeTable->numberOfIndexSubtables);
+ if (subtable_record == NULL) {
return false;
}
- unsigned int offsetToSubtable = sizeTable->indexSubtableArrayOffset + subtable->offsetToSubtable;
- const OT::IndexSubHeader& header =
- OT::StructAtOffset<OT::IndexSubHeader> (this->cblc, offsetToSubtable);
+ if (subtable_record->get_extents (extents))
+ return true;
- unsigned int imageDataOffset = header.imageDataOffset;
- switch (header.indexFormat)
- {
- case 1:
- {
- const OT::IndexSubtableFormat1& format1 =
- OT::StructAtOffset<OT::IndexSubtableFormat1> (this->cblc, offsetToSubtable);
- imageDataOffset += format1.offsetArrayZ[glyph - subtable->firstGlyphIndex];
- }
- break;
- default:
- // TODO: Support other index subtable format.
- return false;
- }
+ unsigned int image_offset = 0, image_length = 0, image_format = 0;
+ if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
+ return false;
- switch (header.imageFormat)
+ switch (image_format)
{
case 17: {
const OT::GlyphBitmapDataFormat17& glyphFormat17 =
- OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, imageDataOffset);
- extents->x_bearing = glyphFormat17.glyphMetrics.bearingX;
- extents->y_bearing = glyphFormat17.glyphMetrics.bearingY;
- extents->width = glyphFormat17.glyphMetrics.width;
- extents->height = -glyphFormat17.glyphMetrics.height;
+ OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, image_offset);
+ glyphFormat17.glyphMetrics.get_extents (extents);
}
break;
default: