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-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
193
src/hb-ot-ebdt-table.hh
Normal 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 */
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user