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:
parent
261837e720
commit
831852594b
|
@ -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 \
|
||||
|
|
|
@ -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 */
|
|
@ -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<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);
|
||||
|
@ -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<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->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);
|
||||
|
|
Loading…
Reference in New Issue