--- /dev/null
+/*
+ * Copyright © 2016 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Seigo Nonaka
+ */
+
+#ifndef HB_OT_EBDT_TABLE_HH
+#define HB_OT_EBDT_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+namespace OT {
+
+struct SmallGlyphMetrics
+{
+ BYTE height;
+ BYTE width;
+ int8_t bearingX;
+ int8_t bearingY;
+ BYTE advance;
+
+ DEFINE_SIZE_STATIC(5);
+};
+
+struct SBitLineMetrics {
+ int8_t ascender;
+ int8_t decender;
+ BYTE widthMax;
+ int8_t caretSlopeNumerator;
+ int8_t caretSlopeDenominator;
+ int8_t caretOffset;
+ int8_t minOriginSB;
+ int8_t minAdvanceSB;
+ int8_t maxBeforeBL;
+ int8_t minAfterBL;
+ int8_t padding1;
+ int8_t padding2;
+
+ DEFINE_SIZE_STATIC(12);
+};
+
+struct BitmapSizeTable
+{
+ ULONG indexSubtableArrayOffset;
+ ULONG indexTablesSize;
+ ULONG numberOfIndexSubtables;
+ ULONG colorRef;
+ SBitLineMetrics horizontal;
+ SBitLineMetrics vertical;
+ USHORT startGlyphIndex;
+ USHORT endGlyphIndex;
+ BYTE ppemX;
+ BYTE ppemY;
+ BYTE bitDepth;
+ int8_t flags;
+
+ DEFINE_SIZE_STATIC(48);
+};
+
+/*
+ * Index Subtables.
+ */
+struct IndexSubtable
+{
+ USHORT firstGlyphIndex;
+ USHORT lastGlyphIndex;
+ ULONG offsetToSubtable;
+
+ DEFINE_SIZE_STATIC(8);
+};
+
+struct IndexSubHeader
+{
+ USHORT indexFormat;
+ USHORT imageFormat;
+ ULONG imageDataOffset;
+};
+
+struct IndexSubtableFormat1
+{
+ IndexSubHeader header;
+ ULONG offsetArray[VAR];
+};
+
+/*
+ * Glyph Bitmap Data Formats.
+ */
+struct GlyphBitmapDataFormat17
+{
+ SmallGlyphMetrics glyphMetrics;
+ ULONG dataLen;
+ BYTE data[VAR];
+};
+
+struct IndexSubtableArray
+{
+ public:
+ const IndexSubtable* find_table(hb_codepoint_t glyph, unsigned int numTables) const
+ {
+ for (unsigned int i = 0; i < numTables; ++i) {
+ unsigned int firstGlyphIndex = indexSubtables[i].firstGlyphIndex;
+ unsigned int lastGlyphIndex = indexSubtables[i].lastGlyphIndex;
+ if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
+ return &indexSubtables[i];
+ }
+ }
+ return NULL;
+ }
+
+ protected:
+ IndexSubtable indexSubtables[VAR];
+};
+
+/*
+ * CBLC -- Color Bitmap Location Table
+ */
+
+#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
+
+struct CBLC
+{
+ static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (true);
+ }
+
+ public:
+ const BitmapSizeTable* find_table(hb_codepoint_t glyph) const
+ {
+ // TODO: Make it possible to select strike.
+ const uint32_t tableSize = numSizes;
+ for (uint32_t i = 0; i < tableSize; ++i) {
+ unsigned int startGlyphIndex = sizeTables[i].startGlyphIndex;
+ unsigned int endGlyphIndex = sizeTables[i].endGlyphIndex;
+ if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) {
+ return &sizeTables[i];
+ }
+ }
+ return NULL;
+ }
+
+ protected:
+ ULONG version;
+ ULONG numSizes;
+
+ BitmapSizeTable sizeTables[VAR];
+};
+
+/*
+ * CBDT -- Color Bitmap Data Table
+ */
+#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
+
+struct CBDT
+{
+ static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (true);
+ }
+
+ protected:
+ BYTE data[VAR];
+};
+
+} /* namespace OT */
+
+#endif /* HB_OT_EBDT_TABLE_HH */
#include "hb-font-private.hh"
#include "hb-ot-cmap-table.hh"
+#include "hb-ot-ebdt-table.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-hhea-table.hh"
}
};
+struct hb_ot_face_ebdt_accelerator_t
+{
+ hb_blob_t *cblc_blob = NULL;
+ hb_blob_t *cbdt_blob = NULL;
+ const OT::CBLC *cblc = NULL;
+ const OT::CBDT *cbdt = NULL;
+
+ float upem = 0.0f;
+
+ inline void init (hb_face_t *face)
+ {
+ this->cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
+ this->cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
+
+ if (hb_blob_get_length (this->cblc_blob) == 0) {
+ return; /* Not a bitmap font. */
+ }
+ cblc = OT::Sanitizer<OT::CBLC>::lock_instance (this->cblc_blob);
+ cbdt = OT::Sanitizer<OT::CBDT>::lock_instance (this->cbdt_blob);
+
+ upem = face->get_upem();
+ }
+
+ inline void fini (void)
+ {
+ if (this->cblc_blob) {
+ hb_blob_destroy (this->cblc_blob);
+ hb_blob_destroy (this->cbdt_blob);
+ }
+ }
+
+ inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+ {
+ if (cblc == NULL) {
+ return false; // Not a color bitmap font.
+ }
+
+ const OT::BitmapSizeTable* sizeTable = this->cblc->find_table(glyph);
+ if (sizeTable == NULL) {
+ 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) {
+ return false;
+ }
+
+ unsigned int offsetToSubtable = sizeTable->indexSubtableArrayOffset + subtable->offsetToSubtable;
+ const OT::IndexSubHeader& header =
+ OT::StructAtOffset<OT::IndexSubHeader> (this->cblc, offsetToSubtable);
+
+ unsigned int imageDataOffset = header.imageDataOffset;
+ switch (header.indexFormat) {
+ case 1: {
+ const OT::IndexSubtableFormat1& format1 =
+ OT::StructAtOffset<OT::IndexSubtableFormat1> (this->cblc, offsetToSubtable);
+ imageDataOffset += format1.offsetArray[glyph - subtable->firstGlyphIndex];
+ switch (header.imageFormat) {
+ 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;
+ }
+ break;
+ default:
+ // TODO: Support other image formats.
+ return false;
+ }
+ }
+ break;
+ default:
+ // TODO: Support other index subtable format.
+ return false;
+ }
+
+ // Convert to the font units.
+ extents->x_bearing *= upem / (float)(sizeTable->ppemX);
+ extents->y_bearing *= upem / (float)(sizeTable->ppemY);
+ extents->width *= upem / (float)(sizeTable->ppemX);
+ extents->height *= upem / (float)(sizeTable->ppemY);
+
+ return true;
+ }
+};
+
typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph);
hb_ot_face_metrics_accelerator_t h_metrics;
hb_ot_face_metrics_accelerator_t v_metrics;
hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
+ hb_lazy_loader_t<hb_ot_face_ebdt_accelerator_t> ebdt;
};
ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE,
ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
ot_font->glyf.init (face);
+ ot_font->ebdt.init (face);
return ot_font;
}
ot_font->h_metrics.fini ();
ot_font->v_metrics.fini ();
ot_font->glyf.fini ();
+ ot_font->ebdt.fini ();
free (ot_font);
}
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
bool ret = ot_font->glyf->get_extents (glyph, extents);
+ if ( !ret )
+ ret = ot_font->ebdt->get_extents (glyph, extents);
extents->x_bearing = font->em_scale_x (extents->x_bearing);
extents->y_bearing = font->em_scale_y (extents->y_bearing);
extents->width = font->em_scale_x (extents->width);