Introduce get_extent support for color bitmap font. (#351)

hb_font_get_glyph_extents now works for color bitmap fonts.
Currently only font having index format 1 and image format 17
is supported.
This commit is contained in:
Seigo Nonaka 2016-12-02 15:03:50 -08:00 committed by Behdad Esfahbod
parent 261837e720
commit 831852594b
3 changed files with 290 additions and 0 deletions

View File

@ -21,6 +21,7 @@ HB_BASE_sources = \
hb-open-file-private.hh \ hb-open-file-private.hh \
hb-open-type-private.hh \ hb-open-type-private.hh \
hb-ot-cmap-table.hh \ hb-ot-cmap-table.hh \
hb-ot-ebdt-table.hh \
hb-ot-glyf-table.hh \ hb-ot-glyf-table.hh \
hb-ot-head-table.hh \ hb-ot-head-table.hh \
hb-ot-hhea-table.hh \ hb-ot-hhea-table.hh \

193
src/hb-ot-ebdt-table.hh Normal file
View File

@ -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 */

View File

@ -31,6 +31,7 @@
#include "hb-font-private.hh" #include "hb-font-private.hh"
#include "hb-ot-cmap-table.hh" #include "hb-ot-cmap-table.hh"
#include "hb-ot-ebdt-table.hh"
#include "hb-ot-glyf-table.hh" #include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh" #include "hb-ot-head-table.hh"
#include "hb-ot-hhea-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<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, typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
hb_codepoint_t codepoint, hb_codepoint_t codepoint,
hb_codepoint_t *glyph); 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 h_metrics;
hb_ot_face_metrics_accelerator_t v_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_glyf_accelerator_t> glyf;
hb_lazy_loader_t<hb_ot_face_ebdt_accelerator_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->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->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
ot_font->glyf.init (face); ot_font->glyf.init (face);
ot_font->ebdt.init (face);
return ot_font; return ot_font;
} }
@ -406,6 +499,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font)
ot_font->h_metrics.fini (); ot_font->h_metrics.fini ();
ot_font->v_metrics.fini (); ot_font->v_metrics.fini ();
ot_font->glyf.fini (); ot_font->glyf.fini ();
ot_font->ebdt.fini ();
free (ot_font); 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; const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
bool ret = ot_font->glyf->get_extents (glyph, extents); 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->x_bearing = font->em_scale_x (extents->x_bearing);
extents->y_bearing = font->em_scale_y (extents->y_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing);
extents->width = font->em_scale_x (extents->width); extents->width = font->em_scale_x (extents->width);