diff --git a/src/Makefile.sources b/src/Makefile.sources index 5c695c5c2..8d2f3c681 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -21,6 +21,7 @@ HB_BASE_sources = \ hb-open-file-private.hh \ hb-open-type-private.hh \ hb-ot-cmap-table.hh \ + hb-ot-ebdt-table.hh \ hb-ot-glyf-table.hh \ hb-ot-head-table.hh \ hb-ot-hhea-table.hh \ diff --git a/src/hb-ot-ebdt-table.hh b/src/hb-ot-ebdt-table.hh new file mode 100644 index 000000000..f3d0de619 --- /dev/null +++ b/src/hb-ot-ebdt-table.hh @@ -0,0 +1,193 @@ +/* + * 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 */ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 20f2f8944..d9be19690 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -31,6 +31,7 @@ #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" @@ -207,6 +208,96 @@ struct hb_ot_face_glyf_accelerator_t } }; +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::sanitize (face->reference_table (HB_OT_TAG_CBLC)); + this->cbdt_blob = OT::Sanitizer::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::lock_instance (this->cblc_blob); + cbdt = OT::Sanitizer::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 (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 (this->cblc, offsetToSubtable); + + unsigned int imageDataOffset = header.imageDataOffset; + switch (header.indexFormat) { + case 1: { + const OT::IndexSubtableFormat1& format1 = + OT::StructAtOffset (this->cblc, offsetToSubtable); + imageDataOffset += format1.offsetArray[glyph - subtable->firstGlyphIndex]; + switch (header.imageFormat) { + case 17: { + const OT::GlyphBitmapDataFormat17& glyphFormat17 = + OT::StructAtOffset (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); @@ -379,6 +470,7 @@ struct hb_ot_font_t hb_ot_face_metrics_accelerator_t h_metrics; hb_ot_face_metrics_accelerator_t v_metrics; hb_lazy_loader_t glyf; + hb_lazy_loader_t ebdt; }; @@ -395,6 +487,7 @@ _hb_ot_font_create (hb_face_t *face) 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; } @@ -406,6 +499,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font) ot_font->h_metrics.fini (); ot_font->v_metrics.fini (); ot_font->glyf.fini (); + ot_font->ebdt.fini (); free (ot_font); } @@ -464,6 +558,8 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, { 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);