Update Harfbuzz to version 2.9.0
[ChangeLog][Text] Updated bundled Harfbuzz to version 2.9.0. Pick-to: 6.2 Change-Id: Ib8fed753b99a127d5a4cc793c5c1d55a0090f902 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>bb10
parent
d07742f333
commit
d8f815db7f
|
|
@ -34,6 +34,8 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
|
|||
src/hb-object.hh
|
||||
src/hb-open-file.hh
|
||||
src/hb-open-type.hh
|
||||
src/hb-priority-queue.hh
|
||||
src/hb-repacker.hh
|
||||
src/hb-set.cc src/hb-set.h src/hb-set.hh
|
||||
src/hb-set-digest.hh
|
||||
src/hb-shape.cc src/hb-shape.h
|
||||
|
|
@ -105,6 +107,7 @@ qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE # special case
|
|||
src/hb-ot-cmap-table.hh
|
||||
src/hb-ot-color.cc
|
||||
src/hb-ot-color-cbdt-table.hh
|
||||
src/hb-ot-color-colrv1-closure.hh
|
||||
src/hb-ot-face.cc
|
||||
src/hb-ot-font.cc src/hb-ot-font.h
|
||||
src/hb-ot-glyf-table.hh
|
||||
|
|
@ -128,6 +131,7 @@ qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE # special case
|
|||
src/hb-ot-os2-table.hh
|
||||
src/hb-ot-post-macroman.hh
|
||||
src/hb-ot-post-table.hh
|
||||
src/hb-ot-post-table-v2subset.hh
|
||||
src/hb-ot-shape.cc src/hb-ot-shape.h src/hb-ot-shape.hh
|
||||
src/hb-ot-shape-complex-arabic.cc src/hb-ot-shape-complex-arabic.hh
|
||||
src/hb-ot-shape-complex-arabic-fallback.hh
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ files names COPYING in subdirectories where applicable.
|
|||
|
||||
Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc.
|
||||
Copyright © 2018,2019,2020 Ebrahim Byagowi
|
||||
Copyright © 2019,2020 Facebook, Inc.
|
||||
Copyright © 2019,2020 Facebook, Inc.
|
||||
Copyright © 2012 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
Copyright © 2009 Keith Stribley
|
||||
Copyright © 2009 Martin Hosken and SIL International
|
||||
Copyright © 2007 Chris Wilson
|
||||
Copyright © 2006 Behdad Esfahbod
|
||||
Copyright © 2005,2006,2020,2021 Behdad Esfahbod
|
||||
Copyright © 2005 David Turner
|
||||
Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
|
||||
Copyright © 1998-2004 David Turner and Werner Lemberg
|
||||
|
|
|
|||
|
|
@ -1,3 +1,48 @@
|
|||
Overview of changes leading to 2.9.0
|
||||
Wednesday, August 18, 2021
|
||||
History Repeats Itself (Afghanistan)
|
||||
====================================
|
||||
- Subsetter API is being stabilized, with the first stable API to happen in
|
||||
3.0.0 release (https://github.com/harfbuzz/harfbuzz/issues/3078).
|
||||
- Support multiple variation axes with same tag, aka HOI.
|
||||
- The “coretext” testing shaper now passes font variations to CoreText.
|
||||
- hb-shape/hb-view does not break line at new lines unless text is read from
|
||||
file.
|
||||
- hb-view and hb-subset has a --batch now, similar to hb-shape.
|
||||
- The --batch mode now uses ; as argument separator instead of : used previously.
|
||||
- The --batch in hb-shape does not expect 0th argument anymore. That is, the
|
||||
lines read are interpreted as argv[1:], instead of argv[0:].
|
||||
- The --batch option has been undocumented. We are ready to document it; send
|
||||
feedback if you find it useful.
|
||||
- hb-subset got arguments revamps. Added much-requested --gids-file, --glyphs,
|
||||
--glyphs-file, --unicodes-file, supporting ranges in --unicodes.
|
||||
- Various bug fixes.
|
||||
|
||||
Overview of changes leading to 2.8.2
|
||||
Tuesday, July 8, 2021
|
||||
====================================
|
||||
- Shaping LTR digits for RTL scripts now makes the native direction of the
|
||||
digits LTR, applying shaping and positioning rules on the same glyph order as
|
||||
Uniscribe. (Jonathan Kew, Khaled Hosny).
|
||||
- Subsetting COLR v1 and CPAL tables is now supported. (Garret Rieger, Qunxin Liu)
|
||||
- Various fixes and improvements to the subsetter. (Garret Rieger, Qunxin Liu, Behdad)
|
||||
- When applying morx table, mark glyph widths should not be zeroed. (Jonathan Kew)
|
||||
- GPOS is preferred over kerx, if GSUB was applied. (Behdad)
|
||||
- Regional_Indicator pairs are grouped together when clustering. (Behdad)
|
||||
- New API:
|
||||
+hb_blob_create_or_fail()
|
||||
+hb_blob_create_from_file_or_fail()
|
||||
+hb_set_copy()
|
||||
|
||||
Overview of changes leading to 2.8.1
|
||||
Tuesday, May 4, 2021
|
||||
====================================
|
||||
- Subsetter now fully supports GSUB/GPOS/GDEF tables (including variations); as
|
||||
such, layout tables are retained by subsetter by default. (Garret Rieger, Qunxin Liu)
|
||||
- Build scripts no longer check for FontConfig as HarfBuzz does not use it.
|
||||
- hb-view supports iTerm2 and kitty inline image protocols (Khaled Hosny),
|
||||
it can also use Chafa for terminal graphics if available (Hans Petter Jansson).
|
||||
|
||||
Overview of changes leading to 2.8.0
|
||||
Tuesday, March 16, 2021
|
||||
====================================
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
[](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)
|
||||
[](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master)
|
||||
[](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main)
|
||||
[](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
|
||||
[](https://scan.coverity.com/projects/behdad-harfbuzz)
|
||||
[](https://app.codacy.com/app/behdad/harfbuzz)
|
||||
[](https://codecov.io/gh/harfbuzz/harfbuzz)
|
||||
[](https://codecov.io/gh/harfbuzz/harfbuzz)
|
||||
[](https://coveralls.io/r/harfbuzz/harfbuzz)
|
||||
[](https://repology.org/project/harfbuzz/versions)
|
||||
[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
"Description": "HarfBuzz is an OpenType text shaping engine.",
|
||||
"Homepage": "http://harfbuzz.org",
|
||||
"Version": "2.8.0",
|
||||
"Version": "2.9.0",
|
||||
|
||||
"License": "MIT License",
|
||||
"LicenseId": "MIT",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "hb-fallback-shape.cc"
|
||||
#include "hb-font.cc"
|
||||
#include "hb-map.cc"
|
||||
#include "hb-ms-feature-ranges.cc"
|
||||
#include "hb-number.cc"
|
||||
#include "hb-ot-cff1-table.cc"
|
||||
#include "hb-ot-cff2-table.cc"
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ struct Anchor
|
|||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
typedef LArrayOf<Anchor> GlyphAnchors;
|
||||
typedef Array32Of<Anchor> GlyphAnchors;
|
||||
|
||||
struct ankr
|
||||
{
|
||||
|
|
@ -64,7 +64,7 @@ struct ankr
|
|||
unsigned int i,
|
||||
unsigned int num_glyphs) const
|
||||
{
|
||||
const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
|
||||
const NNOffset16To<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
|
||||
if (!offset)
|
||||
return Null (Anchor);
|
||||
const GlyphAnchors &anchors = &(this+anchorData) + *offset;
|
||||
|
|
@ -83,9 +83,9 @@ struct ankr
|
|||
protected:
|
||||
HBUINT16 version; /* Version number (set to zero) */
|
||||
HBUINT16 flags; /* Flags (currently unused; set to zero) */
|
||||
LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors>>>
|
||||
Offset32To<Lookup<NNOffset16To<GlyphAnchors>>>
|
||||
lookupTable; /* Offset to the table's lookup table */
|
||||
LNNOffsetTo<HBUINT8>
|
||||
NNOffset32To<HBUINT8>
|
||||
anchorData; /* Offset to the glyph data table */
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
#include "hb-aat-layout.hh"
|
||||
#include "hb-open-type.hh"
|
||||
|
||||
namespace OT {
|
||||
struct GDEF;
|
||||
};
|
||||
|
||||
namespace AAT {
|
||||
|
||||
|
|
@ -164,7 +167,7 @@ struct LookupSegmentArray
|
|||
|
||||
HBGlyphID last; /* Last GlyphID in this segment */
|
||||
HBGlyphID first; /* First GlyphID in this segment */
|
||||
NNOffsetTo<UnsizedArrayOf<T>>
|
||||
NNOffset16To<UnsizedArrayOf<T>>
|
||||
valuesZ; /* A 16-bit offset from the start of
|
||||
* the table to the data. */
|
||||
public:
|
||||
|
|
@ -659,7 +662,7 @@ struct ClassTable
|
|||
}
|
||||
protected:
|
||||
HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */
|
||||
ArrayOf<HBUCHAR> classArray; /* The class codes (indexed by glyph index minus
|
||||
Array16Of<HBUCHAR> classArray; /* The class codes (indexed by glyph index minus
|
||||
* firstGlyph). */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, classArray);
|
||||
|
|
@ -678,7 +681,8 @@ struct ObsoleteTypes
|
|||
const void *base,
|
||||
const T *array)
|
||||
{
|
||||
return (offset - ((const char *) array - (const char *) base)) / T::static_size;
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/2816 */
|
||||
return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size;
|
||||
}
|
||||
template <typename T>
|
||||
static unsigned int byteOffsetToIndex (unsigned int offset,
|
||||
|
|
@ -862,6 +866,7 @@ struct hb_aat_apply_context_t :
|
|||
hb_buffer_t *buffer;
|
||||
hb_sanitize_context_t sanitizer;
|
||||
const ankr *ankr_table;
|
||||
const OT::GDEF *gdef_table;
|
||||
|
||||
/* Unused. For debug tracing only. */
|
||||
unsigned int lookup_index;
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ struct FeatureName
|
|||
protected:
|
||||
HBUINT16 feature; /* Feature type. */
|
||||
HBUINT16 nSettings; /* The number of records in the setting name array. */
|
||||
LNNOffsetTo<UnsizedArrayOf<SettingName>>
|
||||
NNOffset32To<UnsizedArrayOf<SettingName>>
|
||||
settingTableZ; /* Offset in bytes from the beginning of this table to
|
||||
* this feature's setting name array. The actual type of
|
||||
* record this offset refers to will depend on the
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ struct DecompositionAction
|
|||
* to decompose before more frequent ones. The ligatures
|
||||
* on the line of text will decompose in increasing
|
||||
* value of this field. */
|
||||
ArrayOf<HBUINT16>
|
||||
Array16Of<HBUINT16>
|
||||
decomposedglyphs;
|
||||
/* Number of 16-bit glyph indexes that follow;
|
||||
* the ligature will be decomposed into these glyphs.
|
||||
|
|
@ -310,7 +310,7 @@ struct WidthDeltaPair
|
|||
DEFINE_SIZE_STATIC (24);
|
||||
};
|
||||
|
||||
typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster;
|
||||
typedef OT::Array32Of<WidthDeltaPair> WidthDeltaCluster;
|
||||
|
||||
struct JustificationCategory
|
||||
{
|
||||
|
|
@ -358,20 +358,20 @@ struct JustificationHeader
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<JustificationCategory>
|
||||
Offset16To<JustificationCategory>
|
||||
justClassTable; /* Offset to the justification category state table. */
|
||||
OffsetTo<WidthDeltaCluster>
|
||||
Offset16To<WidthDeltaCluster>
|
||||
wdcTable; /* Offset from start of justification table to start
|
||||
* of the subtable containing the width delta factors
|
||||
* for the glyphs in your font.
|
||||
*
|
||||
* The width delta clusters table. */
|
||||
OffsetTo<PostcompensationActionChain>
|
||||
Offset16To<PostcompensationActionChain>
|
||||
pcTable; /* Offset from start of justification table to start
|
||||
* of postcompensation subtable (set to zero if none).
|
||||
*
|
||||
* The postcompensation subtable, if present in the font. */
|
||||
Lookup<OffsetTo<WidthDeltaCluster>>
|
||||
Lookup<Offset16To<WidthDeltaCluster>>
|
||||
lookupTable; /* Lookup table associating glyphs with width delta
|
||||
* clusters. See the description of Width Delta Clusters
|
||||
* table for details on how to interpret the lookup values. */
|
||||
|
|
@ -398,13 +398,13 @@ struct just
|
|||
FixedVersion<>version; /* Version of the justification table
|
||||
* (0x00010000u for version 1.0). */
|
||||
HBUINT16 format; /* Format of the justification table (set to 0). */
|
||||
OffsetTo<JustificationHeader>
|
||||
Offset16To<JustificationHeader>
|
||||
horizData; /* Byte offset from the start of the justification table
|
||||
* to the header for tables that contain justification
|
||||
* information for horizontal text.
|
||||
* If you are not including this information,
|
||||
* store 0. */
|
||||
OffsetTo<JustificationHeader>
|
||||
Offset16To<JustificationHeader>
|
||||
vertData; /* ditto, vertical */
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -710,18 +710,18 @@ struct KerxSubTableFormat6
|
|||
{
|
||||
struct Long
|
||||
{
|
||||
LNNOffsetTo<Lookup<HBUINT32>> rowIndexTable;
|
||||
LNNOffsetTo<Lookup<HBUINT32>> columnIndexTable;
|
||||
LNNOffsetTo<UnsizedArrayOf<FWORD32>> array;
|
||||
NNOffset32To<Lookup<HBUINT32>> rowIndexTable;
|
||||
NNOffset32To<Lookup<HBUINT32>> columnIndexTable;
|
||||
NNOffset32To<UnsizedArrayOf<FWORD32>> array;
|
||||
} l;
|
||||
struct Short
|
||||
{
|
||||
LNNOffsetTo<Lookup<HBUINT16>> rowIndexTable;
|
||||
LNNOffsetTo<Lookup<HBUINT16>> columnIndexTable;
|
||||
LNNOffsetTo<UnsizedArrayOf<FWORD>> array;
|
||||
NNOffset32To<Lookup<HBUINT16>> rowIndexTable;
|
||||
NNOffset32To<Lookup<HBUINT16>> columnIndexTable;
|
||||
NNOffset32To<UnsizedArrayOf<FWORD>> array;
|
||||
} s;
|
||||
} u;
|
||||
LNNOffsetTo<UnsizedArrayOf<FWORD>> vector;
|
||||
NNOffset32To<UnsizedArrayOf<FWORD>> vector;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "hb-open-type.hh"
|
||||
#include "hb-aat-layout-common.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-aat-map.hh"
|
||||
|
||||
/*
|
||||
|
|
@ -215,7 +216,9 @@ struct ContextualSubtable
|
|||
hb_aat_apply_context_t *c_) :
|
||||
ret (false),
|
||||
c (c_),
|
||||
gdef (*c->gdef_table),
|
||||
mark_set (false),
|
||||
has_glyph_classes (gdef.has_glyph_classes ()),
|
||||
mark (0),
|
||||
table (table_),
|
||||
subs (table+table->substitutionTables) {}
|
||||
|
|
@ -263,6 +266,9 @@ struct ContextualSubtable
|
|||
{
|
||||
buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
|
||||
buffer->info[mark].codepoint = *replacement;
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->info[mark],
|
||||
gdef.get_glyph_props (*replacement));
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
|
@ -287,6 +293,9 @@ struct ContextualSubtable
|
|||
if (replacement)
|
||||
{
|
||||
buffer->info[idx].codepoint = *replacement;
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->info[idx],
|
||||
gdef.get_glyph_props (*replacement));
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
|
@ -301,10 +310,12 @@ struct ContextualSubtable
|
|||
bool ret;
|
||||
private:
|
||||
hb_aat_apply_context_t *c;
|
||||
const OT::GDEF &gdef;
|
||||
bool mark_set;
|
||||
bool has_glyph_classes;
|
||||
unsigned int mark;
|
||||
const ContextualSubtable *table;
|
||||
const UnsizedOffsetListOf<Lookup<HBGlyphID>, HBUINT, false> &subs;
|
||||
const UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false> &subs;
|
||||
};
|
||||
|
||||
bool apply (hb_aat_apply_context_t *c) const
|
||||
|
|
@ -348,7 +359,7 @@ struct ContextualSubtable
|
|||
protected:
|
||||
StateTable<Types, EntryData>
|
||||
machine;
|
||||
NNOffsetTo<UnsizedOffsetListOf<Lookup<HBGlyphID>, HBUINT, false>, HBUINT>
|
||||
NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false>, HBUINT>
|
||||
substitutionTables;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (20);
|
||||
|
|
@ -599,6 +610,9 @@ struct NoncontextualSubtable
|
|||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
const OT::GDEF &gdef (*c->gdef_table);
|
||||
bool has_glyph_classes = gdef.has_glyph_classes ();
|
||||
|
||||
bool ret = false;
|
||||
unsigned int num_glyphs = c->face->get_num_glyphs ();
|
||||
|
||||
|
|
@ -610,6 +624,9 @@ struct NoncontextualSubtable
|
|||
if (replacement)
|
||||
{
|
||||
info[i].codepoint = *replacement;
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&info[i],
|
||||
gdef.get_glyph_props (*replacement));
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ struct opbdFormat0
|
|||
bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
|
||||
hb_glyph_extents_t *extents, const void *base) const
|
||||
{
|
||||
const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
|
||||
const Offset16To<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
|
||||
if (!bounds_offset) return false;
|
||||
const OpticalBounds &bounds = base+*bounds_offset;
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ struct opbdFormat0
|
|||
}
|
||||
|
||||
protected:
|
||||
Lookup<OffsetTo<OpticalBounds>>
|
||||
Lookup<Offset16To<OpticalBounds>>
|
||||
lookupTable; /* Lookup table associating glyphs with the four
|
||||
* int16 values for the left-side, top-side,
|
||||
* right-side, and bottom-side optical bounds. */
|
||||
|
|
@ -92,7 +92,7 @@ struct opbdFormat1
|
|||
bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
|
||||
hb_glyph_extents_t *extents, const void *base) const
|
||||
{
|
||||
const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
|
||||
const Offset16To<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
|
||||
if (!bounds_offset) return false;
|
||||
const OpticalBounds &bounds = base+*bounds_offset;
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ struct opbdFormat1
|
|||
}
|
||||
|
||||
protected:
|
||||
Lookup<OffsetTo<OpticalBounds>>
|
||||
Lookup<Offset16To<OpticalBounds>>
|
||||
lookupTable; /* Lookup table associating glyphs with the four
|
||||
* int16 values for the left-side, top-side,
|
||||
* right-side, and bottom-side optical bounds. */
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ struct TrackTableEntry
|
|||
NameID trackNameID; /* The 'name' table index for this track.
|
||||
* (a short word or phrase like "loose"
|
||||
* or "very tight") */
|
||||
NNOffsetTo<UnsizedArrayOf<FWORD>>
|
||||
NNOffset16To<UnsizedArrayOf<FWORD>>
|
||||
valuesZ; /* Offset from start of tracking table to
|
||||
* per-size tracking values for this track. */
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ struct TrackData
|
|||
protected:
|
||||
HBUINT16 nTracks; /* Number of separate tracks included in this table. */
|
||||
HBUINT16 nSizes; /* Number of point sizes included in this table. */
|
||||
LNNOffsetTo<UnsizedArrayOf<HBFixed>>
|
||||
NNOffset32To<UnsizedArrayOf<HBFixed>>
|
||||
sizeTable; /* Offset from start of the tracking table to
|
||||
* Array[nSizes] of size values.. */
|
||||
UnsizedArrayOf<TrackTableEntry>
|
||||
|
|
@ -212,10 +212,10 @@ struct trak
|
|||
FixedVersion<>version; /* Version of the tracking table
|
||||
* (0x00010000u for version 1.0). */
|
||||
HBUINT16 format; /* Format of the tracking table (set to 0). */
|
||||
OffsetTo<TrackData>
|
||||
Offset16To<TrackData>
|
||||
horizData; /* Offset from start of tracking table to TrackData
|
||||
* for horizontal text (or 0 if none). */
|
||||
OffsetTo<TrackData>
|
||||
Offset16To<TrackData>
|
||||
vertData; /* Offset from start of tracking table to TrackData
|
||||
* for vertical text (or 0 if none). */
|
||||
HBUINT16 reserved; /* Reserved. Set to 0. */
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p
|
|||
buffer (buffer_),
|
||||
sanitizer (),
|
||||
ankr_table (&Null (AAT::ankr)),
|
||||
gdef_table (face->table.GDEF->table),
|
||||
lookup_index (0)
|
||||
{
|
||||
sanitizer.init (blob);
|
||||
|
|
@ -79,7 +80,7 @@ AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
|
|||
* @short_description: Apple Advanced Typography Layout
|
||||
* @include: hb-aat.h
|
||||
*
|
||||
* Functions for querying AAT Layout features in the font face.
|
||||
* Functions for querying AAT Layout features in the font face.
|
||||
*
|
||||
* HarfBuzz supports all of the AAT tables used to implement shaping. Other
|
||||
* AAT tables and their associated features are not supported.
|
||||
|
|
@ -172,13 +173,13 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
|
|||
{HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* hb_aat_layout_find_feature_mapping:
|
||||
* @tag: The requested #hb_tag_t feature tag
|
||||
*
|
||||
* Fetches the AAT feature-and-selector combination that corresponds
|
||||
* to a given OpenType feature tag.
|
||||
*
|
||||
*
|
||||
* Return value: the AAT features and selectors corresponding to the
|
||||
* OpenType feature tag queried
|
||||
*
|
||||
|
|
@ -248,7 +249,9 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
|||
if (morx.has_data ())
|
||||
{
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
|
||||
if (!buffer->message (font, "start table morx")) return;
|
||||
morx.apply (&c);
|
||||
(void) buffer->message (font, "end table morx");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -257,7 +260,9 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
|||
if (mort.has_data ())
|
||||
{
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
|
||||
if (!buffer->message (font, "start table mort")) return;
|
||||
mort.apply (&c);
|
||||
(void) buffer->message (font, "end table mort");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -313,8 +318,10 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
|
|||
const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
|
||||
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
|
||||
if (!buffer->message (font, "start table kerx")) return;
|
||||
c.set_ankr_table (font->face->table.ankr.get ());
|
||||
kerx.apply (&c);
|
||||
(void) buffer->message (font, "end table kerx");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ struct FTStringRange
|
|||
}
|
||||
|
||||
protected:
|
||||
NNOffsetTo<UnsizedArrayOf<HBUINT8>>
|
||||
NNOffset16To<UnsizedArrayOf<HBUINT8>>
|
||||
tag; /* Offset from the start of the table to
|
||||
* the beginning of the string */
|
||||
HBUINT16 length; /* String length (in bytes) */
|
||||
|
|
@ -80,7 +80,7 @@ struct ltag
|
|||
protected:
|
||||
HBUINT32 version; /* Table version; currently 1 */
|
||||
HBUINT32 flags; /* Table flags; currently none defined */
|
||||
LArrayOf<FTStringRange>
|
||||
Array32Of<FTStringRange>
|
||||
tagRanges; /* Range for each tag's string */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (12, tagRanges);
|
||||
|
|
|
|||
|
|
@ -760,6 +760,14 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
|
|||
#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
|
||||
|
||||
|
||||
static inline void *
|
||||
hb_memcpy (void *__restrict dst, const void *__restrict src, size_t len)
|
||||
{
|
||||
/* It's illegal to pass 0 as size to memcpy. */
|
||||
if (unlikely (!len)) return dst;
|
||||
return memcpy (dst, src, len);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hb_memcmp (const void *a, const void *b, unsigned int len)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,6 +36,14 @@
|
|||
template <typename Type>
|
||||
struct hb_sorted_array_t;
|
||||
|
||||
enum hb_not_found_t
|
||||
{
|
||||
HB_NOT_FOUND_DONT_STORE,
|
||||
HB_NOT_FOUND_STORE,
|
||||
HB_NOT_FOUND_STORE_CLOSEST,
|
||||
};
|
||||
|
||||
|
||||
template <typename Type>
|
||||
struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
||||
{
|
||||
|
|
@ -139,7 +147,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
return lfind (x, &i) ? &this->arrayZ[i] : not_found;
|
||||
}
|
||||
template <typename T>
|
||||
bool lfind (const T &x, unsigned *pos = nullptr) const
|
||||
bool lfind (const T &x, unsigned *pos = nullptr,
|
||||
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{
|
||||
for (unsigned i = 0; i < length; ++i)
|
||||
if (hb_equal (x, this->arrayZ[i]))
|
||||
|
|
@ -149,6 +159,22 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
return true;
|
||||
}
|
||||
|
||||
if (pos)
|
||||
{
|
||||
switch (not_found)
|
||||
{
|
||||
case HB_NOT_FOUND_DONT_STORE:
|
||||
break;
|
||||
|
||||
case HB_NOT_FOUND_STORE:
|
||||
*pos = to_store;
|
||||
break;
|
||||
|
||||
case HB_NOT_FOUND_STORE_CLOSEST:
|
||||
*pos = length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +245,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
unsigned P = sizeof (Type),
|
||||
hb_enable_if (P == 1)>
|
||||
const T *as () const
|
||||
{ return length < hb_null_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
|
||||
{ return length < hb_min_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
|
||||
|
||||
template <typename T,
|
||||
unsigned P = sizeof (Type),
|
||||
|
|
@ -231,9 +257,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
&& (unsigned int) (arrayZ + length - (const char *) p) >= size;
|
||||
}
|
||||
|
||||
/* Only call if you allocated the underlying array using malloc() or similar. */
|
||||
void free ()
|
||||
{ ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
|
||||
/* Only call if you allocated the underlying array using hb_malloc() or similar. */
|
||||
void fini ()
|
||||
{ hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
|
||||
|
||||
template <typename hb_serialize_context_t>
|
||||
hb_array_t copy (hb_serialize_context_t *c) const
|
||||
|
|
@ -266,13 +292,6 @@ template <typename T, unsigned int length_> inline hb_array_t<T>
|
|||
hb_array (T (&array_)[length_])
|
||||
{ return hb_array_t<T> (array_); }
|
||||
|
||||
enum hb_bfind_not_found_t
|
||||
{
|
||||
HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
HB_BFIND_NOT_FOUND_STORE,
|
||||
HB_BFIND_NOT_FOUND_STORE_CLOSEST,
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct hb_sorted_array_t :
|
||||
hb_iter_t<hb_sorted_array_t<Type>, Type&>,
|
||||
|
|
@ -323,7 +342,7 @@ struct hb_sorted_array_t :
|
|||
}
|
||||
template <typename T>
|
||||
bool bfind (const T &x, unsigned int *i = nullptr,
|
||||
hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{
|
||||
unsigned pos;
|
||||
|
|
@ -339,14 +358,14 @@ struct hb_sorted_array_t :
|
|||
{
|
||||
switch (not_found)
|
||||
{
|
||||
case HB_BFIND_NOT_FOUND_DONT_STORE:
|
||||
case HB_NOT_FOUND_DONT_STORE:
|
||||
break;
|
||||
|
||||
case HB_BFIND_NOT_FOUND_STORE:
|
||||
case HB_NOT_FOUND_STORE:
|
||||
*i = to_store;
|
||||
break;
|
||||
|
||||
case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
|
||||
case HB_NOT_FOUND_STORE_CLOSEST:
|
||||
*i = pos;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,10 +58,15 @@ struct hb_bimap_t
|
|||
|
||||
void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
|
||||
{
|
||||
if (in_error ()) return;
|
||||
if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return;
|
||||
if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
|
||||
|
||||
forw_map.set (lhs, rhs);
|
||||
if (in_error ()) return;
|
||||
|
||||
back_map.set (rhs, lhs);
|
||||
if (in_error ()) forw_map.del (lhs);
|
||||
}
|
||||
|
||||
hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
|
||||
|
|
|
|||
|
|
@ -72,16 +72,54 @@ hb_blob_create (const char *data,
|
|||
void *user_data,
|
||||
hb_destroy_func_t destroy)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
|
||||
if (!length ||
|
||||
length >= 1u << 31 ||
|
||||
!(blob = hb_object_create<hb_blob_t> ())) {
|
||||
if (!length)
|
||||
{
|
||||
if (destroy)
|
||||
destroy (user_data);
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
hb_blob_t *blob = hb_blob_create_or_fail (data, length, mode,
|
||||
user_data, destroy);
|
||||
return likely (blob) ? blob : hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_blob_create_or_fail: (skip)
|
||||
* @data: Pointer to blob data.
|
||||
* @length: Length of @data in bytes.
|
||||
* @mode: Memory mode for @data.
|
||||
* @user_data: Data parameter to pass to @destroy.
|
||||
* @destroy: (nullable): Callback to call when @data is not needed anymore.
|
||||
*
|
||||
* Creates a new "blob" object wrapping @data. The @mode parameter is used
|
||||
* to negotiate ownership and lifecycle of @data.
|
||||
*
|
||||
* Note that this function returns a freshly-allocated empty blob even if @length
|
||||
* is zero. This is in contrast to hb_blob_create(), which returns the singleton
|
||||
* empty blob (as returned by hb_blob_get_empty()) if @length is zero.
|
||||
*
|
||||
* Return value: New blob, or %NULL if failed. Destroy with hb_blob_destroy().
|
||||
*
|
||||
* Since: 2.8.2
|
||||
**/
|
||||
hb_blob_t *
|
||||
hb_blob_create_or_fail (const char *data,
|
||||
unsigned int length,
|
||||
hb_memory_mode_t mode,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
|
||||
if (length >= 1u << 31 ||
|
||||
!(blob = hb_object_create<hb_blob_t> ()))
|
||||
{
|
||||
if (destroy)
|
||||
destroy (user_data);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
blob->data = data;
|
||||
blob->length = length;
|
||||
blob->mode = mode;
|
||||
|
|
@ -91,9 +129,10 @@ hb_blob_create (const char *data,
|
|||
|
||||
if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
|
||||
blob->mode = HB_MEMORY_MODE_READONLY;
|
||||
if (!blob->try_make_writable ()) {
|
||||
if (!blob->try_make_writable ())
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
return hb_blob_get_empty ();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +265,7 @@ hb_blob_destroy (hb_blob_t *blob)
|
|||
|
||||
blob->fini_shallow ();
|
||||
|
||||
free (blob);
|
||||
hb_free (blob);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -452,7 +491,7 @@ hb_blob_t::try_make_writable ()
|
|||
|
||||
char *new_data;
|
||||
|
||||
new_data = (char *) malloc (this->length);
|
||||
new_data = (char *) hb_malloc (this->length);
|
||||
if (unlikely (!new_data))
|
||||
return false;
|
||||
|
||||
|
|
@ -463,7 +502,7 @@ hb_blob_t::try_make_writable ()
|
|||
this->mode = HB_MEMORY_MODE_WRITABLE;
|
||||
this->data = new_data;
|
||||
this->user_data = new_data;
|
||||
this->destroy = free;
|
||||
this->destroy = hb_free;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -517,7 +556,7 @@ _hb_mapped_file_destroy (void *file_)
|
|||
assert (0); // If we don't have mmap we shouldn't reach here
|
||||
#endif
|
||||
|
||||
free (file);
|
||||
hb_free (file);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -528,7 +567,7 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
|
|||
size_t name_len = strlen (file_name);
|
||||
size_t len = name_len + sizeof (_PATH_RSRCFORKSPEC);
|
||||
|
||||
char *rsrc_name = (char *) malloc (len);
|
||||
char *rsrc_name = (char *) hb_malloc (len);
|
||||
if (unlikely (!rsrc_name)) return -1;
|
||||
|
||||
strncpy (rsrc_name, file_name, name_len);
|
||||
|
|
@ -536,7 +575,7 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
|
|||
sizeof (_PATH_RSRCFORKSPEC) - 1);
|
||||
|
||||
int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0);
|
||||
free (rsrc_name);
|
||||
hb_free (rsrc_name);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
|
|
@ -561,17 +600,37 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
|
|||
* Creates a new blob containing the data from the
|
||||
* specified binary font file.
|
||||
*
|
||||
* Returns: An #hb_blob_t pointer with the content of the file
|
||||
* Returns: An #hb_blob_t pointer with the content of the file,
|
||||
* or hb_blob_get_empty() if failed.
|
||||
*
|
||||
* Since: 1.7.7
|
||||
**/
|
||||
hb_blob_t *
|
||||
hb_blob_create_from_file (const char *file_name)
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (file_name);
|
||||
return likely (blob) ? blob : hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_blob_create_from_file_or_fail:
|
||||
* @file_name: A font filename
|
||||
*
|
||||
* Creates a new blob containing the data from the
|
||||
* specified binary font file.
|
||||
*
|
||||
* Returns: An #hb_blob_t pointer with the content of the file,
|
||||
* or %NULL if failed.
|
||||
*
|
||||
* Since: 2.8.2
|
||||
**/
|
||||
hb_blob_t *
|
||||
hb_blob_create_from_file_or_fail (const char *file_name)
|
||||
{
|
||||
/* Adopted from glib's gmappedfile.c with Matthias Clasen and
|
||||
Allison Lortie permission but changed a lot to suit our need. */
|
||||
#if defined(HAVE_MMAP) && !defined(HB_NO_MMAP)
|
||||
hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
|
||||
hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t));
|
||||
if (unlikely (!file)) return hb_blob_get_empty ();
|
||||
|
||||
int fd = open (file_name, O_RDONLY | O_BINARY, 0);
|
||||
|
|
@ -601,22 +660,22 @@ hb_blob_create_from_file (const char *file_name)
|
|||
|
||||
close (fd);
|
||||
|
||||
return hb_blob_create (file->contents, file->length,
|
||||
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
|
||||
(hb_destroy_func_t) _hb_mapped_file_destroy);
|
||||
return hb_blob_create_or_fail (file->contents, file->length,
|
||||
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
|
||||
(hb_destroy_func_t) _hb_mapped_file_destroy);
|
||||
|
||||
fail:
|
||||
close (fd);
|
||||
fail_without_close:
|
||||
free (file);
|
||||
hb_free (file);
|
||||
|
||||
#elif defined(_WIN32) && !defined(HB_NO_MMAP)
|
||||
hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
|
||||
hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t));
|
||||
if (unlikely (!file)) return hb_blob_get_empty ();
|
||||
|
||||
HANDLE fd;
|
||||
unsigned int size = strlen (file_name) + 1;
|
||||
wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size);
|
||||
wchar_t * wchar_file_name = (wchar_t *) hb_malloc (sizeof (wchar_t) * size);
|
||||
if (unlikely (!wchar_file_name)) goto fail_without_close;
|
||||
mbstowcs (wchar_file_name, file_name, size);
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
|
|
@ -636,7 +695,7 @@ fail_without_close:
|
|||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
|
||||
nullptr);
|
||||
#endif
|
||||
free (wchar_file_name);
|
||||
hb_free (wchar_file_name);
|
||||
|
||||
if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
|
||||
|
||||
|
|
@ -661,22 +720,22 @@ fail_without_close:
|
|||
if (unlikely (!file->contents)) goto fail;
|
||||
|
||||
CloseHandle (fd);
|
||||
return hb_blob_create (file->contents, file->length,
|
||||
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
|
||||
(hb_destroy_func_t) _hb_mapped_file_destroy);
|
||||
return hb_blob_create_or_fail (file->contents, file->length,
|
||||
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
|
||||
(hb_destroy_func_t) _hb_mapped_file_destroy);
|
||||
|
||||
fail:
|
||||
CloseHandle (fd);
|
||||
fail_without_close:
|
||||
free (file);
|
||||
hb_free (file);
|
||||
|
||||
#endif
|
||||
|
||||
/* The following tries to read a file without knowing its size beforehand
|
||||
It's used as a fallback for systems without mmap or to read from pipes */
|
||||
unsigned long len = 0, allocated = BUFSIZ * 16;
|
||||
char *data = (char *) malloc (allocated);
|
||||
if (unlikely (!data)) return hb_blob_get_empty ();
|
||||
char *data = (char *) hb_malloc (allocated);
|
||||
if (unlikely (!data)) return nullptr;
|
||||
|
||||
FILE *fp = fopen (file_name, "rb");
|
||||
if (unlikely (!fp)) goto fread_fail_without_close;
|
||||
|
|
@ -689,7 +748,7 @@ fail_without_close:
|
|||
/* Don't allocate and go more than ~536MB, our mmap reader still
|
||||
can cover files like that but lets limit our fallback reader */
|
||||
if (unlikely (allocated > (2 << 28))) goto fread_fail;
|
||||
char *new_data = (char *) realloc (data, allocated);
|
||||
char *new_data = (char *) hb_realloc (data, allocated);
|
||||
if (unlikely (!new_data)) goto fread_fail;
|
||||
data = new_data;
|
||||
}
|
||||
|
|
@ -706,13 +765,13 @@ fail_without_close:
|
|||
}
|
||||
fclose (fp);
|
||||
|
||||
return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data,
|
||||
(hb_destroy_func_t) free);
|
||||
return hb_blob_create_or_fail (data, len, HB_MEMORY_MODE_WRITABLE, data,
|
||||
(hb_destroy_func_t) hb_free);
|
||||
|
||||
fread_fail:
|
||||
fclose (fp);
|
||||
fread_fail_without_close:
|
||||
free (data);
|
||||
return hb_blob_get_empty ();
|
||||
hb_free (data);
|
||||
return nullptr;
|
||||
}
|
||||
#endif /* !HB_NO_OPEN */
|
||||
|
|
|
|||
|
|
@ -90,9 +90,19 @@ hb_blob_create (const char *data,
|
|||
void *user_data,
|
||||
hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_blob_create_or_fail (const char *data,
|
||||
unsigned int length,
|
||||
hb_memory_mode_t mode,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_blob_create_from_file (const char *file_name);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_blob_create_from_file_or_fail (const char *file_name);
|
||||
|
||||
/* Always creates with MEMORY_MODE_READONLY.
|
||||
* Even if the parent blob is writable, we don't
|
||||
* want the user of the sub-blob to be able to
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ struct hb_blob_ptr_t
|
|||
const T * get () const { return b->as<T> (); }
|
||||
hb_blob_t * get_blob () const { return b.get_raw (); }
|
||||
unsigned int get_length () const { return b.get ()->length; }
|
||||
void destroy () { hb_blob_destroy (b.get ()); b = nullptr; }
|
||||
void destroy () { hb_blob_destroy (b.get_raw ()); b = nullptr; }
|
||||
|
||||
private:
|
||||
hb_nonnull_ptr_t<hb_blob_t> b;
|
||||
|
|
|
|||
|
|
@ -96,14 +96,15 @@ hb_segment_properties_hash (const hb_segment_properties_t *p)
|
|||
* As an optimization, both info and out_info may point to the
|
||||
* same piece of memory, which is owned by info. This remains the
|
||||
* case as long as out_len doesn't exceed i at any time.
|
||||
* In that case, swap_buffers() is no-op and the glyph operations operate
|
||||
* mostly in-place.
|
||||
* In that case, swap_buffers() is mostly no-op and the glyph operations
|
||||
* operate mostly in-place.
|
||||
*
|
||||
* As soon as out_info gets longer than info, out_info is moved over
|
||||
* to an alternate buffer (which we reuse the pos buffer for!), and its
|
||||
* to an alternate buffer (which we reuse the pos buffer for), and its
|
||||
* current contents (out_len entries) are copied to the new place.
|
||||
*
|
||||
* This should all remain transparent to the user. swap_buffers() then
|
||||
* switches info and out_info.
|
||||
* switches info over to out_info and does housekeeping.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -136,8 +137,8 @@ hb_buffer_t::enlarge (unsigned int size)
|
|||
if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
|
||||
goto done;
|
||||
|
||||
new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
|
||||
new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
|
||||
new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0]));
|
||||
new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0]));
|
||||
|
||||
done:
|
||||
if (unlikely (!new_pos || !new_info))
|
||||
|
|
@ -281,22 +282,13 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
hb_buffer_t::remove_output ()
|
||||
{
|
||||
have_output = false;
|
||||
have_positions = false;
|
||||
|
||||
out_len = 0;
|
||||
out_info = info;
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::clear_output ()
|
||||
{
|
||||
have_output = true;
|
||||
have_positions = false;
|
||||
|
||||
idx = 0;
|
||||
out_len = 0;
|
||||
out_info = info;
|
||||
}
|
||||
|
|
@ -316,29 +308,23 @@ hb_buffer_t::clear_positions ()
|
|||
void
|
||||
hb_buffer_t::swap_buffers ()
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
assert (have_output);
|
||||
|
||||
assert (idx <= len);
|
||||
if (unlikely (!next_glyphs (len - idx))) return;
|
||||
|
||||
assert (have_output);
|
||||
have_output = false;
|
||||
if (unlikely (!successful || !next_glyphs (len - idx)))
|
||||
goto reset;
|
||||
|
||||
if (out_info != info)
|
||||
{
|
||||
hb_glyph_info_t *tmp;
|
||||
tmp = info;
|
||||
pos = (hb_glyph_position_t *) info;
|
||||
info = out_info;
|
||||
out_info = tmp;
|
||||
|
||||
pos = (hb_glyph_position_t *) out_info;
|
||||
}
|
||||
|
||||
unsigned int tmp;
|
||||
tmp = len;
|
||||
len = out_len;
|
||||
out_len = tmp;
|
||||
|
||||
reset:
|
||||
have_output = false;
|
||||
out_len = 0;
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
|
|
@ -373,12 +359,11 @@ hb_buffer_t::move_to (unsigned int i)
|
|||
/* This will blow in our face if memory allocation fails later
|
||||
* in this same lookup...
|
||||
*
|
||||
* We used to shift with extra 32 items, instead of the 0 below.
|
||||
* We used to shift with extra 32 items.
|
||||
* But that would leave empty slots in the buffer in case of allocation
|
||||
* failures. Setting to zero for now to avoid other problems (see
|
||||
* comments in shift_forward(). This can cause O(N^2) behavior more
|
||||
* severely than adding 32 empty slots can... */
|
||||
if (unlikely (idx < count && !shift_forward (count + 0))) return false;
|
||||
* failures. See comments in shift_forward(). This can cause O(N^2)
|
||||
* behavior more severely than adding 32 empty slots can... */
|
||||
if (unlikely (idx < count && !shift_forward (count - idx))) return false;
|
||||
|
||||
assert (idx >= count);
|
||||
|
||||
|
|
@ -630,7 +615,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
|
|||
HB_BUFFER_CONTENT_TYPE_INVALID,
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||
false, /* successful */
|
||||
true, /* have_output */
|
||||
false, /* have_output */
|
||||
true /* have_positions */
|
||||
|
||||
/* Zero is good enough for everything else. */
|
||||
|
|
@ -717,14 +702,14 @@ hb_buffer_destroy (hb_buffer_t *buffer)
|
|||
|
||||
hb_unicode_funcs_destroy (buffer->unicode);
|
||||
|
||||
free (buffer->info);
|
||||
free (buffer->pos);
|
||||
hb_free (buffer->info);
|
||||
hb_free (buffer->pos);
|
||||
#ifndef HB_NO_BUFFER_MESSAGE
|
||||
if (buffer->message_destroy)
|
||||
buffer->message_destroy (buffer->message_data);
|
||||
#endif
|
||||
|
||||
free (buffer);
|
||||
hb_free (buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1363,6 +1348,11 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
|
|||
* Returns @buffer glyph position array. Returned pointer
|
||||
* is valid as long as @buffer contents are not modified.
|
||||
*
|
||||
* If buffer did not have positions before, the positions will be
|
||||
* initialized to zeros, unless this function is called from
|
||||
* within a buffer message callback (see hb_buffer_set_message_func()),
|
||||
* in which case %NULL is returned.
|
||||
*
|
||||
* Return value: (transfer none) (array length=length):
|
||||
* The @buffer glyph position array.
|
||||
* The value valid as long as buffer has not been modified.
|
||||
|
|
@ -1373,12 +1363,17 @@ hb_glyph_position_t *
|
|||
hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
|
||||
unsigned int *length)
|
||||
{
|
||||
if (!buffer->have_positions)
|
||||
buffer->clear_positions ();
|
||||
|
||||
if (length)
|
||||
*length = buffer->len;
|
||||
|
||||
if (!buffer->have_positions)
|
||||
{
|
||||
if (unlikely (buffer->message_depth))
|
||||
return nullptr;
|
||||
|
||||
buffer->clear_positions ();
|
||||
}
|
||||
|
||||
return (hb_glyph_position_t *) buffer->pos;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ struct hb_buffer_t
|
|||
|
||||
unsigned int idx; /* Cursor into ->info and ->pos arrays */
|
||||
unsigned int len; /* Length of ->info and ->pos arrays */
|
||||
unsigned int out_len; /* Length of ->out array if have_output */
|
||||
unsigned int out_len; /* Length of ->out_info array if have_output */
|
||||
|
||||
unsigned int allocated; /* Length of allocated arrays */
|
||||
hb_glyph_info_t *info;
|
||||
|
|
@ -128,6 +128,9 @@ struct hb_buffer_t
|
|||
hb_buffer_message_func_t message_func;
|
||||
void *message_data;
|
||||
hb_destroy_func_t message_destroy;
|
||||
unsigned message_depth; /* How deeply are we inside a message callback? */
|
||||
#else
|
||||
static constexpr unsigned message_depth = 0u;
|
||||
#endif
|
||||
|
||||
/* Internal debugging. */
|
||||
|
|
@ -186,13 +189,10 @@ struct hb_buffer_t
|
|||
hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; }
|
||||
hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
|
||||
|
||||
HB_NODISCARD bool has_separate_output () const { return info != out_info; }
|
||||
|
||||
|
||||
HB_INTERNAL void reset ();
|
||||
HB_INTERNAL void clear ();
|
||||
|
||||
unsigned int backtrack_len () const { return have_output? out_len : idx; }
|
||||
unsigned int backtrack_len () const { return have_output ? out_len : idx; }
|
||||
unsigned int lookahead_len () const { return len - idx; }
|
||||
unsigned int next_serial () { return serial++; }
|
||||
|
||||
|
|
@ -206,7 +206,6 @@ struct hb_buffer_t
|
|||
HB_INTERNAL void guess_segment_properties ();
|
||||
|
||||
HB_INTERNAL void swap_buffers ();
|
||||
HB_INTERNAL void remove_output ();
|
||||
HB_INTERNAL void clear_output ();
|
||||
HB_INTERNAL void clear_positions ();
|
||||
|
||||
|
|
@ -400,10 +399,16 @@ struct hb_buffer_t
|
|||
#else
|
||||
if (!messaging ())
|
||||
return true;
|
||||
|
||||
message_depth++;
|
||||
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
bool ret = message_impl (font, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
message_depth--;
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include "hb.hh"
|
||||
|
||||
|
||||
/* Implements a lock-free cache for int->int functions. */
|
||||
/* Implements a lockfree cache for int->int functions. */
|
||||
|
||||
template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
|
||||
struct hb_cache_t
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
|
|||
|
||||
T *ip = c->allocate_size<T> (T::static_size);
|
||||
if (unlikely (!ip)) return_trace (false);
|
||||
return_trace (c->check_assign (*ip, value));
|
||||
return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
|
|
|
|||
|
|
@ -136,8 +136,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
|
|||
if (unlikely (!scalars.resize (region_count)))
|
||||
set_error ();
|
||||
else
|
||||
varStore->varStore.get_scalars (get_ivs (), coords, num_coords,
|
||||
&scalars[0], region_count);
|
||||
varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
|
||||
&scalars[0], region_count);
|
||||
}
|
||||
seen_blend = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -257,13 +257,11 @@ struct hb_language_item_t {
|
|||
bool operator == (const char *s) const
|
||||
{ return lang_equal (lang, s); }
|
||||
|
||||
hb_language_item_t & operator = (const char *s) {
|
||||
/* If a custom allocated is used calling strdup() pairs
|
||||
badly with a call to the custom free() in fini() below.
|
||||
Therefore don't call strdup(), implement its behavior.
|
||||
*/
|
||||
hb_language_item_t & operator = (const char *s)
|
||||
{
|
||||
/* We can't call strdup(), because we allow custom allocators. */
|
||||
size_t len = strlen(s) + 1;
|
||||
lang = (hb_language_t) malloc(len);
|
||||
lang = (hb_language_t) hb_malloc(len);
|
||||
if (likely (lang))
|
||||
{
|
||||
memcpy((unsigned char *) lang, s, len);
|
||||
|
|
@ -274,11 +272,11 @@ struct hb_language_item_t {
|
|||
return *this;
|
||||
}
|
||||
|
||||
void fini () { free ((void *) lang); }
|
||||
void fini () { hb_free ((void *) lang); }
|
||||
};
|
||||
|
||||
|
||||
/* Thread-safe lock-free language list */
|
||||
/* Thread-safe lockfree language list */
|
||||
|
||||
static hb_atomic_ptr_t <hb_language_item_t> langs;
|
||||
|
||||
|
|
@ -294,7 +292,7 @@ retry:
|
|||
while (first_lang) {
|
||||
hb_language_item_t *next = first_lang->next;
|
||||
first_lang->fini ();
|
||||
free (first_lang);
|
||||
hb_free (first_lang);
|
||||
first_lang = next;
|
||||
}
|
||||
}
|
||||
|
|
@ -311,21 +309,21 @@ retry:
|
|||
return lang;
|
||||
|
||||
/* Not found; allocate one. */
|
||||
hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t));
|
||||
hb_language_item_t *lang = (hb_language_item_t *) hb_calloc (1, sizeof (hb_language_item_t));
|
||||
if (unlikely (!lang))
|
||||
return nullptr;
|
||||
lang->next = first_lang;
|
||||
*lang = key;
|
||||
if (unlikely (!lang->lang))
|
||||
{
|
||||
free (lang);
|
||||
hb_free (lang);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (unlikely (!langs.cmpexch (first_lang, lang)))
|
||||
{
|
||||
lang->fini ();
|
||||
free (lang);
|
||||
hb_free (lang);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,9 @@
|
|||
#define HB_NO_LEGACY
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_OVERRIDE_H
|
||||
#include "config-override.h"
|
||||
#endif
|
||||
|
||||
/* Closure of options. */
|
||||
|
||||
|
|
@ -117,7 +120,7 @@
|
|||
#define HB_NO_CMAP_LEGACY_SUBTABLES
|
||||
#define HB_NO_FALLBACK_SHAPE
|
||||
#define HB_NO_OT_KERN
|
||||
#define HB_NO_OT_LAYOUT_BLACKLIST
|
||||
#define HB_NO_OT_LAYOUT_BLOCKLIST
|
||||
#define HB_NO_OT_SHAPE_FALLBACK
|
||||
#endif
|
||||
|
||||
|
|
@ -155,9 +158,5 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_OVERRIDE_H
|
||||
#include "config-override.h"
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HB_CONFIG_HH */
|
||||
|
|
|
|||
|
|
@ -332,6 +332,44 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (font->coords)
|
||||
{
|
||||
CFMutableDictionaryRef variations =
|
||||
CFDictionaryCreateMutable (kCFAllocatorDefault,
|
||||
font->num_coords,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
for (unsigned i = 0; i < font->num_coords; i++)
|
||||
{
|
||||
if (font->coords[i] == 0.) continue;
|
||||
|
||||
hb_ot_var_axis_info_t info;
|
||||
unsigned int c = 1;
|
||||
hb_ot_var_get_axis_infos (font->face, i, &c, &info);
|
||||
CFDictionarySetValue (variations,
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag),
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &font->design_coords[i])
|
||||
);
|
||||
}
|
||||
|
||||
CFDictionaryRef attributes =
|
||||
CFDictionaryCreate (kCFAllocatorDefault,
|
||||
(const void **) &kCTFontVariationAttribute,
|
||||
(const void **) &variations,
|
||||
1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
CTFontDescriptorRef varDesc = CTFontDescriptorCreateWithAttributes (attributes);
|
||||
CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0, nullptr, varDesc);
|
||||
|
||||
CFRelease (ct_font);
|
||||
CFRelease (attributes);
|
||||
CFRelease (variations);
|
||||
ct_font = new_ct_font;
|
||||
}
|
||||
|
||||
return (hb_coretext_font_data_t *) ct_font;
|
||||
}
|
||||
|
||||
|
|
@ -1061,7 +1099,7 @@ resize_and_retry:
|
|||
hb_glyph_info_t *info = run_info;
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||
{
|
||||
hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult;
|
||||
hb_position_t x_offset = round ((positions[0].x - advances_so_far) * x_mult);
|
||||
for (unsigned int j = 0; j < num_glyphs; j++)
|
||||
{
|
||||
CGFloat advance;
|
||||
|
|
@ -1069,15 +1107,15 @@ resize_and_retry:
|
|||
advance = positions[j + 1].x - positions[j].x;
|
||||
else /* last glyph */
|
||||
advance = run_advance - (positions[j].x - positions[0].x);
|
||||
info->mask = advance * x_mult;
|
||||
info->mask = round (advance * x_mult);
|
||||
info->var1.i32 = x_offset;
|
||||
info->var2.i32 = positions[j].y * y_mult;
|
||||
info->var2.i32 = round (positions[j].y * y_mult);
|
||||
info++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult;
|
||||
hb_position_t y_offset = round ((positions[0].y - advances_so_far) * y_mult);
|
||||
for (unsigned int j = 0; j < num_glyphs; j++)
|
||||
{
|
||||
CGFloat advance;
|
||||
|
|
@ -1085,8 +1123,8 @@ resize_and_retry:
|
|||
advance = positions[j + 1].y - positions[j].y;
|
||||
else /* last glyph */
|
||||
advance = run_advance - (positions[j].y - positions[0].y);
|
||||
info->mask = advance * y_mult;
|
||||
info->var1.i32 = positions[j].x * x_mult;
|
||||
info->mask = round (advance * y_mult);
|
||||
info->var1.i32 = round (positions[j].x * x_mult);
|
||||
info->var2.i32 = y_offset;
|
||||
info++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ struct hb_auto_trace_t
|
|||
|
||||
_hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
|
||||
"return %s (line %d)",
|
||||
hb_printer_t<decltype (v)>().print (v), line);
|
||||
hb_printer_t<hb_decay<decltype (v)>>().print (v), line);
|
||||
if (plevel) --*plevel;
|
||||
plevel = nullptr;
|
||||
returned = true;
|
||||
|
|
@ -438,6 +438,10 @@ struct hb_no_trace_t {
|
|||
#define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
|
||||
#endif
|
||||
|
||||
#ifndef HB_DEBUG_SUBSET_REPACK
|
||||
#define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
#ifndef HB_DEBUG_DISPATCH
|
||||
#define HB_DEBUG_DISPATCH ( \
|
||||
HB_DEBUG_APPLY + \
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "hb-directwrite.h"
|
||||
|
||||
#include "hb-ms-feature-ranges.hh"
|
||||
|
||||
/**
|
||||
* SECTION:hb-directwrite
|
||||
|
|
@ -42,24 +43,6 @@
|
|||
* Functions for using HarfBuzz with DirectWrite fonts.
|
||||
**/
|
||||
|
||||
/* Declare object creator for dynamic support of DWRITE */
|
||||
typedef HRESULT (* WINAPI t_DWriteCreateFactory)(
|
||||
DWRITE_FACTORY_TYPE factoryType,
|
||||
REFIID iid,
|
||||
IUnknown **factory
|
||||
);
|
||||
|
||||
/*
|
||||
* hb-directwrite uses new/delete syntatically but as we let users
|
||||
* to override malloc/free, we will redefine new/delete so users
|
||||
* won't need to do that by their own.
|
||||
*/
|
||||
void* operator new (size_t size) { return malloc (size); }
|
||||
void* operator new [] (size_t size) { return malloc (size); }
|
||||
void operator delete (void* pointer) { free (pointer); }
|
||||
void operator delete [] (void* pointer) { free (pointer); }
|
||||
|
||||
|
||||
/*
|
||||
* DirectWrite font stream helpers
|
||||
*/
|
||||
|
|
@ -154,7 +137,6 @@ public:
|
|||
|
||||
struct hb_directwrite_face_data_t
|
||||
{
|
||||
HMODULE dwrite_dll;
|
||||
IDWriteFactory *dwriteFactory;
|
||||
IDWriteFontFile *fontFile;
|
||||
DWriteFontFileStream *fontFileStream;
|
||||
|
|
@ -176,33 +158,12 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
|
|||
return nullptr; \
|
||||
} HB_STMT_END
|
||||
|
||||
data->dwrite_dll = LoadLibrary (TEXT ("DWRITE"));
|
||||
if (unlikely (!data->dwrite_dll))
|
||||
FAIL ("Cannot find DWrite.DLL");
|
||||
|
||||
t_DWriteCreateFactory p_DWriteCreateFactory;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
#endif
|
||||
|
||||
p_DWriteCreateFactory = (t_DWriteCreateFactory)
|
||||
GetProcAddress (data->dwrite_dll, "DWriteCreateFactory");
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
if (unlikely (!p_DWriteCreateFactory))
|
||||
FAIL ("Cannot find DWriteCreateFactory().");
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
// TODO: factory and fontFileLoader should be cached separately
|
||||
IDWriteFactory* dwriteFactory;
|
||||
hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
|
||||
(IUnknown**) &dwriteFactory);
|
||||
hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
|
||||
(IUnknown**) &dwriteFactory);
|
||||
|
||||
if (unlikely (hr != S_OK))
|
||||
FAIL ("Failed to run DWriteCreateFactory().");
|
||||
|
|
@ -266,8 +227,6 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
|
|||
delete data->fontFileStream;
|
||||
if (data->faceBlob)
|
||||
hb_blob_destroy (data->faceBlob);
|
||||
if (data->dwrite_dll)
|
||||
FreeLibrary (data->dwrite_dll);
|
||||
if (data)
|
||||
delete data;
|
||||
}
|
||||
|
|
@ -552,13 +511,12 @@ protected:
|
|||
* shaper
|
||||
*/
|
||||
|
||||
static hb_bool_t
|
||||
_hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features,
|
||||
float lineWidth)
|
||||
hb_bool_t
|
||||
_hb_directwrite_shape (hb_shape_plan_t *shape_plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features)
|
||||
{
|
||||
hb_face_t *face = font->face;
|
||||
const hb_directwrite_face_data_t *face_data = face->data.directwrite;
|
||||
|
|
@ -611,8 +569,6 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
|
|||
log_clusters[chars_len++] = cluster; /* Surrogates. */
|
||||
}
|
||||
|
||||
// TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
|
||||
|
||||
DWRITE_READING_DIRECTION readingDirection;
|
||||
readingDirection = buffer->props.direction ?
|
||||
DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
|
||||
|
|
@ -623,7 +579,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
|
|||
* but we never attempt to shape a word longer than 64K characters
|
||||
* in a single gfxShapedWord, so we cannot exceed that limit.
|
||||
*/
|
||||
uint32_t textLength = buffer->len;
|
||||
uint32_t textLength = chars_len;
|
||||
|
||||
TextAnalysis analysis (textString, textLength, nullptr, readingDirection);
|
||||
TextAnalysis::Run *runHead;
|
||||
|
|
@ -648,38 +604,54 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
|
|||
mbstowcs ((wchar_t*) localeName,
|
||||
hb_language_to_string (buffer->props.language), 20);
|
||||
|
||||
// TODO: it does work but doesn't care about ranges
|
||||
DWRITE_TYPOGRAPHIC_FEATURES typographic_features;
|
||||
typographic_features.featureCount = num_features;
|
||||
/*
|
||||
* Set up features.
|
||||
*/
|
||||
static_assert ((sizeof (DWRITE_TYPOGRAPHIC_FEATURES) == sizeof (hb_ms_features_t)), "");
|
||||
static_assert ((sizeof (DWRITE_FONT_FEATURE) == sizeof (hb_ms_feature_t)), "");
|
||||
hb_vector_t<hb_ms_features_t *> range_features;
|
||||
hb_vector_t<uint32_t> range_char_counts;
|
||||
if (num_features)
|
||||
{
|
||||
typographic_features.features = new DWRITE_FONT_FEATURE[num_features];
|
||||
for (unsigned int i = 0; i < num_features; ++i)
|
||||
{
|
||||
typographic_features.features[i].nameTag = (DWRITE_FONT_FEATURE_TAG)
|
||||
hb_uint32_swap (features[i].tag);
|
||||
typographic_features.features[i].parameter = features[i].value;
|
||||
}
|
||||
hb_vector_t<hb_ms_feature_t> feature_records;
|
||||
hb_vector_t<hb_ms_range_record_t> range_records;
|
||||
if (hb_ms_setup_features (features, num_features, feature_records, range_records))
|
||||
hb_ms_make_feature_ranges (feature_records,
|
||||
range_records,
|
||||
0,
|
||||
chars_len,
|
||||
log_clusters,
|
||||
range_features,
|
||||
range_char_counts);
|
||||
}
|
||||
const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures;
|
||||
dwFeatures = (const DWRITE_TYPOGRAPHIC_FEATURES*) &typographic_features;
|
||||
const uint32_t featureRangeLengths[] = { textLength };
|
||||
//
|
||||
|
||||
uint16_t* clusterMap;
|
||||
clusterMap = new uint16_t[textLength];
|
||||
DWRITE_SHAPING_TEXT_PROPERTIES* textProperties;
|
||||
textProperties = new DWRITE_SHAPING_TEXT_PROPERTIES[textLength];
|
||||
|
||||
retry_getglyphs:
|
||||
uint16_t* glyphIndices = new uint16_t[maxGlyphCount];
|
||||
DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties;
|
||||
glyphProperties = new DWRITE_SHAPING_GLYPH_PROPERTIES[maxGlyphCount];
|
||||
|
||||
hr = analyzer->GetGlyphs (textString, textLength, fontFace, false,
|
||||
isRightToLeft, &runHead->mScript, localeName,
|
||||
nullptr, &dwFeatures, featureRangeLengths, 1,
|
||||
maxGlyphCount, clusterMap, textProperties,
|
||||
glyphIndices, glyphProperties, &glyphCount);
|
||||
hr = analyzer->GetGlyphs (textString,
|
||||
chars_len,
|
||||
fontFace,
|
||||
false,
|
||||
isRightToLeft,
|
||||
&runHead->mScript,
|
||||
localeName,
|
||||
nullptr,
|
||||
(const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
|
||||
range_char_counts.arrayZ,
|
||||
range_features.length,
|
||||
maxGlyphCount,
|
||||
clusterMap,
|
||||
textProperties,
|
||||
glyphIndices,
|
||||
glyphProperties,
|
||||
&glyphCount);
|
||||
|
||||
if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
|
||||
{
|
||||
|
|
@ -715,101 +687,28 @@ retry_getglyphs:
|
|||
double x_mult = (double) font->x_scale / fontEmSize;
|
||||
double y_mult = (double) font->y_scale / fontEmSize;
|
||||
|
||||
hr = analyzer->GetGlyphPlacements (textString, clusterMap, textProperties,
|
||||
textLength, glyphIndices, glyphProperties,
|
||||
glyphCount, fontFace, fontEmSize,
|
||||
false, isRightToLeft, &runHead->mScript, localeName,
|
||||
&dwFeatures, featureRangeLengths, 1,
|
||||
glyphAdvances, glyphOffsets);
|
||||
hr = analyzer->GetGlyphPlacements (textString,
|
||||
clusterMap,
|
||||
textProperties,
|
||||
chars_len,
|
||||
glyphIndices,
|
||||
glyphProperties,
|
||||
glyphCount,
|
||||
fontFace,
|
||||
fontEmSize,
|
||||
false,
|
||||
isRightToLeft,
|
||||
&runHead->mScript,
|
||||
localeName,
|
||||
(const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
|
||||
range_char_counts.arrayZ,
|
||||
range_features.length,
|
||||
glyphAdvances,
|
||||
glyphOffsets);
|
||||
|
||||
if (FAILED (hr))
|
||||
FAIL ("Analyzer failed to get glyph placements.");
|
||||
|
||||
IDWriteTextAnalyzer1* analyzer1;
|
||||
analyzer->QueryInterface (&analyzer1);
|
||||
|
||||
if (analyzer1 && lineWidth)
|
||||
{
|
||||
DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities =
|
||||
new DWRITE_JUSTIFICATION_OPPORTUNITY[maxGlyphCount];
|
||||
hr = analyzer1->GetJustificationOpportunities (fontFace, fontEmSize, runHead->mScript,
|
||||
textLength, glyphCount, textString,
|
||||
clusterMap, glyphProperties,
|
||||
justificationOpportunities);
|
||||
|
||||
if (FAILED (hr))
|
||||
FAIL ("Analyzer failed to get justification opportunities.");
|
||||
|
||||
float* justifiedGlyphAdvances = new float[maxGlyphCount];
|
||||
DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = new DWRITE_GLYPH_OFFSET[glyphCount];
|
||||
hr = analyzer1->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities,
|
||||
glyphAdvances, glyphOffsets, justifiedGlyphAdvances,
|
||||
justifiedGlyphOffsets);
|
||||
|
||||
if (FAILED (hr)) FAIL ("Analyzer failed to get justify glyph advances.");
|
||||
|
||||
DWRITE_SCRIPT_PROPERTIES scriptProperties;
|
||||
hr = analyzer1->GetScriptProperties (runHead->mScript, &scriptProperties);
|
||||
if (FAILED (hr)) FAIL ("Analyzer failed to get script properties.");
|
||||
uint32_t justificationCharacter = scriptProperties.justificationCharacter;
|
||||
|
||||
// if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
|
||||
if (justificationCharacter != 32)
|
||||
{
|
||||
uint16_t* modifiedClusterMap = new uint16_t[textLength];
|
||||
retry_getjustifiedglyphs:
|
||||
uint16_t* modifiedGlyphIndices = new uint16_t[maxGlyphCount];
|
||||
float* modifiedGlyphAdvances = new float[maxGlyphCount];
|
||||
DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = new DWRITE_GLYPH_OFFSET[maxGlyphCount];
|
||||
uint32_t actualGlyphsCount;
|
||||
hr = analyzer1->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript,
|
||||
textLength, glyphCount, maxGlyphCount,
|
||||
clusterMap, glyphIndices, glyphAdvances,
|
||||
justifiedGlyphAdvances, justifiedGlyphOffsets,
|
||||
glyphProperties, &actualGlyphsCount,
|
||||
modifiedClusterMap, modifiedGlyphIndices,
|
||||
modifiedGlyphAdvances, modifiedGlyphOffsets);
|
||||
|
||||
if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))
|
||||
{
|
||||
maxGlyphCount = actualGlyphsCount;
|
||||
delete [] modifiedGlyphIndices;
|
||||
delete [] modifiedGlyphAdvances;
|
||||
delete [] modifiedGlyphOffsets;
|
||||
|
||||
maxGlyphCount = actualGlyphsCount;
|
||||
|
||||
goto retry_getjustifiedglyphs;
|
||||
}
|
||||
if (FAILED (hr))
|
||||
FAIL ("Analyzer failed to get justified glyphs.");
|
||||
|
||||
delete [] clusterMap;
|
||||
delete [] glyphIndices;
|
||||
delete [] glyphAdvances;
|
||||
delete [] glyphOffsets;
|
||||
|
||||
glyphCount = actualGlyphsCount;
|
||||
clusterMap = modifiedClusterMap;
|
||||
glyphIndices = modifiedGlyphIndices;
|
||||
glyphAdvances = modifiedGlyphAdvances;
|
||||
glyphOffsets = modifiedGlyphOffsets;
|
||||
|
||||
delete [] justifiedGlyphAdvances;
|
||||
delete [] justifiedGlyphOffsets;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete [] glyphAdvances;
|
||||
delete [] glyphOffsets;
|
||||
|
||||
glyphAdvances = justifiedGlyphAdvances;
|
||||
glyphOffsets = justifiedGlyphOffsets;
|
||||
}
|
||||
|
||||
delete [] justificationOpportunities;
|
||||
}
|
||||
|
||||
/* Ok, we've got everything we need, now compose output buffer,
|
||||
* very, *very*, carefully! */
|
||||
|
||||
|
|
@ -870,43 +769,10 @@ retry_getglyphs:
|
|||
delete [] glyphAdvances;
|
||||
delete [] glyphOffsets;
|
||||
|
||||
if (num_features)
|
||||
delete [] typographic_features.features;
|
||||
|
||||
/* Wow, done! */
|
||||
return true;
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
_hb_directwrite_shape (hb_shape_plan_t *shape_plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features)
|
||||
{
|
||||
return _hb_directwrite_shape_full (shape_plan, font, buffer,
|
||||
features, num_features, 0);
|
||||
}
|
||||
|
||||
HB_UNUSED static bool
|
||||
_hb_directwrite_shape_experimental_width (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features,
|
||||
float width)
|
||||
{
|
||||
static const char *shapers = "directwrite";
|
||||
hb_shape_plan_t *shape_plan;
|
||||
shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
|
||||
features, num_features, &shapers);
|
||||
hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer,
|
||||
features, num_features, width);
|
||||
|
||||
buffer->unsafe_to_break_all ();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct _hb_directwrite_font_table_context {
|
||||
IDWriteFontFace *face;
|
||||
void *table_context;
|
||||
|
|
@ -917,7 +783,7 @@ _hb_directwrite_table_data_release (void *data)
|
|||
{
|
||||
_hb_directwrite_font_table_context *context = (_hb_directwrite_font_table_context *) data;
|
||||
context->face->ReleaseFontTable (context->table_context);
|
||||
delete context;
|
||||
hb_free (context);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
|
|
@ -938,7 +804,7 @@ _hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
_hb_directwrite_font_table_context *context = new _hb_directwrite_font_table_context;
|
||||
_hb_directwrite_font_table_context *context = (_hb_directwrite_font_table_context *) hb_malloc (sizeof (_hb_directwrite_font_table_context));
|
||||
context->face = dw_face;
|
||||
context->table_context = table_context;
|
||||
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
|
|||
{
|
||||
if (!hb_object_destroy (funcs)) return;
|
||||
|
||||
free (funcs);
|
||||
hb_free (funcs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "hb-open-file.hh"
|
||||
#include "hb-ot-face.hh"
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-map.hh"
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -106,9 +107,9 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
|
|||
* convenient to provide data for individual tables instead of the whole font
|
||||
* data. With the caveat that hb_face_get_table_tags() does not currently work
|
||||
* with faces created this way.
|
||||
*
|
||||
*
|
||||
* Creates a new face object from the specified @user_data and @reference_table_func,
|
||||
* with the @destroy callback.
|
||||
* with the @destroy callback.
|
||||
*
|
||||
* Return value: (transfer full): The new face object
|
||||
*
|
||||
|
|
@ -150,7 +151,7 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
|
|||
{
|
||||
hb_face_for_data_closure_t *closure;
|
||||
|
||||
closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
|
||||
closure = (hb_face_for_data_closure_t *) hb_calloc (1, sizeof (hb_face_for_data_closure_t));
|
||||
if (unlikely (!closure))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -166,7 +167,7 @@ _hb_face_for_data_closure_destroy (void *data)
|
|||
hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
|
||||
|
||||
hb_blob_destroy (closure->blob);
|
||||
free (closure);
|
||||
hb_free (closure);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
|
|
@ -265,7 +266,7 @@ hb_face_reference (hb_face_t *face)
|
|||
/**
|
||||
* hb_face_destroy: (skip)
|
||||
* @face: A face object
|
||||
*
|
||||
*
|
||||
* Decreases the reference count on a face object. When the
|
||||
* reference count reaches zero, the face is destroyed,
|
||||
* freeing all memory.
|
||||
|
|
@ -281,7 +282,7 @@ hb_face_destroy (hb_face_t *face)
|
|||
{
|
||||
hb_face_t::plan_node_t *next = node->next;
|
||||
hb_shape_plan_destroy (node->shape_plan);
|
||||
free (node);
|
||||
hb_free (node);
|
||||
node = next;
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +292,7 @@ hb_face_destroy (hb_face_t *face)
|
|||
if (face->destroy)
|
||||
face->destroy (face->user_data);
|
||||
|
||||
free (face);
|
||||
hb_free (face);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -302,7 +303,7 @@ hb_face_destroy (hb_face_t *face)
|
|||
* @destroy: (nullable): A callback to call when @data is not needed anymore
|
||||
* @replace: Whether to replace an existing data with the same key
|
||||
*
|
||||
* Attaches a user-data key/data pair to the given face object.
|
||||
* Attaches a user-data key/data pair to the given face object.
|
||||
*
|
||||
* Return value: %true if success, %false otherwise
|
||||
*
|
||||
|
|
@ -441,7 +442,7 @@ hb_face_set_index (hb_face_t *face,
|
|||
*
|
||||
* <note>Note: face indices within a collection are zero-based.</note>
|
||||
*
|
||||
* Return value: The index of @face.
|
||||
* Return value: The index of @face.
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
|
@ -623,26 +624,26 @@ hb_face_collect_variation_unicodes (hb_face_t *face,
|
|||
|
||||
struct hb_face_builder_data_t
|
||||
{
|
||||
struct table_entry_t
|
||||
{
|
||||
int cmp (hb_tag_t t) const
|
||||
{
|
||||
if (t < tag) return -1;
|
||||
if (t > tag) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
hb_tag_t tag;
|
||||
hb_blob_t *blob;
|
||||
};
|
||||
|
||||
hb_vector_t<table_entry_t> tables;
|
||||
hb_hashmap_t<hb_tag_t, hb_blob_t *> tables;
|
||||
};
|
||||
|
||||
static int compare_entries (const void* pa, const void* pb)
|
||||
{
|
||||
const auto& a = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pa;
|
||||
const auto& b = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pb;
|
||||
|
||||
/* Order by blob size first (smallest to largest) and then table tag */
|
||||
|
||||
if (a.second->length != b.second->length)
|
||||
return a.second->length < b.second->length ? -1 : +1;
|
||||
|
||||
return a.first < b.first ? -1 : a.first == b.first ? 0 : +1;
|
||||
}
|
||||
|
||||
static hb_face_builder_data_t *
|
||||
_hb_face_builder_data_create ()
|
||||
{
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) hb_calloc (1, sizeof (hb_face_builder_data_t));
|
||||
if (unlikely (!data))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -656,25 +657,25 @@ _hb_face_builder_data_destroy (void *user_data)
|
|||
{
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
|
||||
|
||||
for (unsigned int i = 0; i < data->tables.length; i++)
|
||||
hb_blob_destroy (data->tables[i].blob);
|
||||
for (hb_blob_t* b : data->tables.values())
|
||||
hb_blob_destroy (b);
|
||||
|
||||
data->tables.fini ();
|
||||
|
||||
free (data);
|
||||
hb_free (data);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
||||
{
|
||||
|
||||
unsigned int table_count = data->tables.length;
|
||||
unsigned int table_count = data->tables.get_population ();
|
||||
unsigned int face_length = table_count * 16 + 12;
|
||||
|
||||
for (unsigned int i = 0; i < table_count; i++)
|
||||
face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob));
|
||||
for (hb_blob_t* b : data->tables.values())
|
||||
face_length += hb_ceil_to_4 (hb_blob_get_length (b));
|
||||
|
||||
char *buf = (char *) malloc (face_length);
|
||||
char *buf = (char *) hb_malloc (face_length);
|
||||
if (unlikely (!buf))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -682,20 +683,31 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
|||
c.propagate_error (data->tables);
|
||||
OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
|
||||
|
||||
bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
|
||||
bool is_cff = (data->tables.has (HB_TAG ('C','F','F',' '))
|
||||
|| data->tables.has (HB_TAG ('C','F','F','2')));
|
||||
hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
|
||||
|
||||
bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ());
|
||||
// Sort the tags so that produced face is deterministic.
|
||||
hb_vector_t<hb_pair_t <hb_tag_t, hb_blob_t*>> sorted_entries;
|
||||
data->tables.iter () | hb_sink (sorted_entries);
|
||||
if (unlikely (sorted_entries.in_error ()))
|
||||
{
|
||||
hb_free (buf);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sorted_entries.qsort (compare_entries);
|
||||
bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter());
|
||||
|
||||
c.end_serialize ();
|
||||
|
||||
if (unlikely (!ret))
|
||||
{
|
||||
free (buf);
|
||||
hb_free (buf);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
|
||||
return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, hb_free);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
|
|
@ -706,11 +718,7 @@ _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
|
|||
if (!tag)
|
||||
return _hb_face_builder_data_reference_blob (data);
|
||||
|
||||
hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
|
||||
if (entry)
|
||||
return hb_blob_reference (entry->blob);
|
||||
|
||||
return nullptr;
|
||||
return hb_blob_reference (data->tables[tag]);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -750,17 +758,21 @@ hb_face_builder_create ()
|
|||
hb_bool_t
|
||||
hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
|
||||
{
|
||||
if (tag == HB_MAP_VALUE_INVALID)
|
||||
return false;
|
||||
|
||||
if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
|
||||
return false;
|
||||
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
|
||||
|
||||
hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
|
||||
if (unlikely (data->tables.in_error()))
|
||||
hb_blob_t* previous = data->tables.get (tag);
|
||||
if (!data->tables.set (tag, hb_blob_reference (blob)))
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
return false;
|
||||
}
|
||||
|
||||
entry->tag = tag;
|
||||
entry->blob = hb_blob_reference (blob);
|
||||
|
||||
hb_blob_destroy (previous);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -620,7 +620,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
|
|||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
|
||||
free (ffuncs);
|
||||
hb_free (ffuncs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1544,8 +1544,8 @@ _hb_font_adopt_var_coords (hb_font_t *font,
|
|||
float *design_coords,
|
||||
unsigned int coords_length)
|
||||
{
|
||||
free (font->coords);
|
||||
free (font->design_coords);
|
||||
hb_free (font->coords);
|
||||
hb_free (font->design_coords);
|
||||
|
||||
font->coords = coords;
|
||||
font->design_coords = design_coords;
|
||||
|
|
@ -1586,8 +1586,8 @@ hb_font_create_sub_font (hb_font_t *parent)
|
|||
unsigned int num_coords = parent->num_coords;
|
||||
if (num_coords)
|
||||
{
|
||||
int *coords = (int *) calloc (num_coords, sizeof (parent->coords[0]));
|
||||
float *design_coords = (float *) calloc (num_coords, sizeof (parent->design_coords[0]));
|
||||
int *coords = (int *) hb_calloc (num_coords, sizeof (parent->coords[0]));
|
||||
float *design_coords = (float *) hb_calloc (num_coords, sizeof (parent->design_coords[0]));
|
||||
if (likely (coords && design_coords))
|
||||
{
|
||||
memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
|
||||
|
|
@ -1596,8 +1596,8 @@ hb_font_create_sub_font (hb_font_t *parent)
|
|||
}
|
||||
else
|
||||
{
|
||||
free (coords);
|
||||
free (design_coords);
|
||||
hb_free (coords);
|
||||
hb_free (design_coords);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1659,10 +1659,10 @@ hb_font_destroy (hb_font_t *font)
|
|||
hb_face_destroy (font->face);
|
||||
hb_font_funcs_destroy (font->klass);
|
||||
|
||||
free (font->coords);
|
||||
free (font->design_coords);
|
||||
hb_free (font->coords);
|
||||
hb_free (font->design_coords);
|
||||
|
||||
free (font);
|
||||
hb_free (font);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2052,29 +2052,30 @@ hb_font_set_variations (hb_font_t *font,
|
|||
return;
|
||||
}
|
||||
|
||||
unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
auto axes = fvar.get_axes ();
|
||||
const unsigned coords_length = axes.length;
|
||||
|
||||
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
|
||||
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
|
||||
|
||||
if (unlikely (coords_length && !(normalized && design_coords)))
|
||||
{
|
||||
free (normalized);
|
||||
free (design_coords);
|
||||
hb_free (normalized);
|
||||
hb_free (design_coords);
|
||||
return;
|
||||
}
|
||||
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
for (unsigned int i = 0; i < variations_length; i++)
|
||||
{
|
||||
hb_ot_var_axis_info_t info;
|
||||
if (hb_ot_var_find_axis_info (font->face, variations[i].tag, &info) &&
|
||||
info.axis_index < coords_length)
|
||||
{
|
||||
float v = variations[i].value;
|
||||
design_coords[info.axis_index] = v;
|
||||
normalized[info.axis_index] = fvar.normalize_axis_value (info.axis_index, v);
|
||||
}
|
||||
const auto tag = variations[i].tag;
|
||||
const auto v = variations[i].value;
|
||||
for (unsigned axis_index = 0; axis_index < coords_length; axis_index++)
|
||||
if (axes[axis_index].axisTag == tag)
|
||||
{
|
||||
design_coords[axis_index] = v;
|
||||
normalized[axis_index] = fvar.normalize_axis_value (axis_index, v);
|
||||
}
|
||||
}
|
||||
font->face->table.avar->map_coords (normalized, coords_length);
|
||||
|
||||
|
|
@ -2100,13 +2101,13 @@ hb_font_set_var_coords_design (hb_font_t *font,
|
|||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
|
||||
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
|
||||
|
||||
if (unlikely (coords_length && !(normalized && design_coords)))
|
||||
{
|
||||
free (normalized);
|
||||
free (design_coords);
|
||||
hb_free (normalized);
|
||||
hb_free (design_coords);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2135,13 +2136,13 @@ hb_font_set_var_named_instance (hb_font_t *font,
|
|||
|
||||
unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
|
||||
|
||||
float *coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
|
||||
float *coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
|
||||
if (unlikely (coords_length && !coords))
|
||||
return;
|
||||
|
||||
hb_ot_var_named_instance_get_design_coords (font->face, instance_index, &coords_length, coords);
|
||||
hb_font_set_var_coords_design (font, coords, coords_length);
|
||||
free (coords);
|
||||
hb_free (coords);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2165,15 +2166,15 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
|
|||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
int *unmapped = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (design_coords[0])) : nullptr;
|
||||
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;
|
||||
|
||||
if (unlikely (coords_length && !(copy && unmapped && design_coords)))
|
||||
{
|
||||
free (copy);
|
||||
free (unmapped);
|
||||
free (design_coords);
|
||||
hb_free (copy);
|
||||
hb_free (unmapped);
|
||||
hb_free (design_coords);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2187,7 +2188,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
|
|||
font->face->table.avar->unmap_coords (unmapped, coords_length);
|
||||
for (unsigned int i = 0; i < coords_length; ++i)
|
||||
design_coords[i] = font->face->table.fvar->unnormalize_axis_value (i, unmapped[i]);
|
||||
free (unmapped);
|
||||
hb_free (unmapped);
|
||||
|
||||
_hb_font_adopt_var_coords (font, copy, design_coords, coords_length);
|
||||
}
|
||||
|
|
@ -2267,7 +2268,7 @@ trampoline_create (FuncType func,
|
|||
{
|
||||
typedef hb_trampoline_t<FuncType> trampoline_t;
|
||||
|
||||
trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
|
||||
trampoline_t *trampoline = (trampoline_t *) hb_calloc (1, sizeof (trampoline_t));
|
||||
|
||||
if (unlikely (!trampoline))
|
||||
return nullptr;
|
||||
|
|
@ -2296,7 +2297,7 @@ trampoline_destroy (void *user_data)
|
|||
|
||||
if (closure->destroy)
|
||||
closure->destroy (closure->user_data);
|
||||
free (closure);
|
||||
hb_free (closure);
|
||||
}
|
||||
|
||||
typedef hb_trampoline_t<hb_font_get_glyph_func_t> hb_font_get_glyph_trampoline_t;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ struct hb_ft_font_t
|
|||
static hb_ft_font_t *
|
||||
_hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
|
||||
{
|
||||
hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t));
|
||||
hb_ft_font_t *ft_font = (hb_ft_font_t *) hb_calloc (1, sizeof (hb_ft_font_t));
|
||||
if (unlikely (!ft_font)) return nullptr;
|
||||
|
||||
ft_font->lock.init ();
|
||||
|
|
@ -125,7 +125,7 @@ _hb_ft_font_destroy (void *data)
|
|||
|
||||
ft_font->lock.fini ();
|
||||
|
||||
free (ft_font);
|
||||
hb_free (ft_font);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -642,20 +642,20 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data
|
|||
if (error)
|
||||
return nullptr;
|
||||
|
||||
buffer = (FT_Byte *) malloc (length);
|
||||
buffer = (FT_Byte *) hb_malloc (length);
|
||||
if (!buffer)
|
||||
return nullptr;
|
||||
|
||||
error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
|
||||
if (error)
|
||||
{
|
||||
free (buffer);
|
||||
hb_free (buffer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return hb_blob_create ((const char *) buffer, length,
|
||||
HB_MEMORY_MODE_WRITABLE,
|
||||
buffer, free);
|
||||
buffer, hb_free);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -846,8 +846,8 @@ hb_ft_font_changed (hb_font_t *font)
|
|||
FT_MM_Var *mm_var = nullptr;
|
||||
if (!FT_Get_MM_Var (ft_face, &mm_var))
|
||||
{
|
||||
FT_Fixed *ft_coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed));
|
||||
int *coords = (int *) calloc (mm_var->num_axis, sizeof (int));
|
||||
FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (mm_var->num_axis, sizeof (FT_Fixed));
|
||||
int *coords = (int *) hb_calloc (mm_var->num_axis, sizeof (int));
|
||||
if (coords && ft_coords)
|
||||
{
|
||||
if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords))
|
||||
|
|
@ -866,12 +866,12 @@ hb_ft_font_changed (hb_font_t *font)
|
|||
hb_font_set_var_coords_normalized (font, nullptr, 0);
|
||||
}
|
||||
}
|
||||
free (coords);
|
||||
free (ft_coords);
|
||||
hb_free (coords);
|
||||
hb_free (ft_coords);
|
||||
#ifdef HAVE_FT_DONE_MM_VAR
|
||||
FT_Done_MM_Var (ft_face->glyph->library, mm_var);
|
||||
#else
|
||||
free (mm_var);
|
||||
hb_free (mm_var);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1020,13 +1020,13 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
|||
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
|
||||
if (num_coords)
|
||||
{
|
||||
FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
|
||||
FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
|
||||
if (ft_coords)
|
||||
{
|
||||
for (unsigned int i = 0; i < num_coords; i++)
|
||||
ft_coords[i] = coords[i] * 4;
|
||||
FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
|
||||
free (ft_coords);
|
||||
hb_free (ft_coords);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,16 +50,16 @@ _hb_gdi_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_dat
|
|||
length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
|
||||
if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc;
|
||||
|
||||
buffer = (char *) malloc (length);
|
||||
buffer = (char *) hb_malloc (length);
|
||||
if (unlikely (!buffer)) goto fail_with_releasedc;
|
||||
length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
|
||||
if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc_and_free;
|
||||
ReleaseDC (nullptr, hdc);
|
||||
|
||||
return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, free);
|
||||
return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, hb_free);
|
||||
|
||||
fail_with_releasedc_and_free:
|
||||
free (buffer);
|
||||
hb_free (buffer);
|
||||
fail_with_releasedc:
|
||||
ReleaseDC (nullptr, hdc);
|
||||
fail:
|
||||
|
|
|
|||
|
|
@ -80,12 +80,12 @@ hb_gobject_##name##_get_type () \
|
|||
#define HB_DEFINE_VALUE_TYPE(name) \
|
||||
static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \
|
||||
{ \
|
||||
hb_##name##_t *c = (hb_##name##_t *) calloc (1, sizeof (hb_##name##_t)); \
|
||||
hb_##name##_t *c = (hb_##name##_t *) hb_calloc (1, sizeof (hb_##name##_t)); \
|
||||
if (unlikely (!c)) return nullptr; \
|
||||
*c = *l; \
|
||||
return c; \
|
||||
} \
|
||||
static void _hb_##name##_destroy (hb_##name##_t *l) { free (l); } \
|
||||
static void _hb_##name##_destroy (hb_##name##_t *l) { hb_free (l); } \
|
||||
HB_DEFINE_BOXED_TYPE (name, _hb_##name##_reference, _hb_##name##_destroy)
|
||||
|
||||
HB_DEFINE_OBJECT_TYPE (buffer)
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ static const void *hb_graphite2_get_table (const void *data, unsigned int tag, s
|
|||
{
|
||||
blob = face_data->face->reference_table (tag);
|
||||
|
||||
hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) calloc (1, sizeof (hb_graphite2_tablelist_t));
|
||||
hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) hb_calloc (1, sizeof (hb_graphite2_tablelist_t));
|
||||
if (unlikely (!p)) {
|
||||
hb_blob_destroy (blob);
|
||||
return nullptr;
|
||||
|
|
@ -123,15 +123,16 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
|
|||
}
|
||||
hb_blob_destroy (silf_blob);
|
||||
|
||||
hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) calloc (1, sizeof (hb_graphite2_face_data_t));
|
||||
hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) hb_calloc (1, sizeof (hb_graphite2_face_data_t));
|
||||
if (unlikely (!data))
|
||||
return nullptr;
|
||||
|
||||
data->face = face;
|
||||
data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
|
||||
const gr_face_ops ops = {sizeof(gr_face_ops), &hb_graphite2_get_table, NULL};
|
||||
data->grface = gr_make_face_with_ops (data, &ops, gr_face_preloadAll);
|
||||
|
||||
if (unlikely (!data->grface)) {
|
||||
free (data);
|
||||
hb_free (data);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -148,12 +149,12 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
|
|||
hb_graphite2_tablelist_t *old = tlist;
|
||||
hb_blob_destroy (tlist->blob);
|
||||
tlist = tlist->next;
|
||||
free (old);
|
||||
hb_free (old);
|
||||
}
|
||||
|
||||
gr_face_destroy (data->grface);
|
||||
|
||||
free (data);
|
||||
hb_free (data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
* TODO Document more.
|
||||
*
|
||||
* If iterator implementation implements operator!=, then can be
|
||||
* used in range-based for loop. That comes free if the iterator
|
||||
* used in range-based for loop. That already happens if the iterator
|
||||
* is random-access. Otherwise, the range-based for loop incurs
|
||||
* one traversal to find end(), which can be avoided if written
|
||||
* as a while-style for loop, or if iterator implements a faster
|
||||
|
|
|
|||
|
|
@ -242,14 +242,14 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
|
|||
static const Stored* get_null () { return &Null (Stored); }
|
||||
static Stored *create (Data *data)
|
||||
{
|
||||
Stored *p = (Stored *) calloc (1, sizeof (Stored));
|
||||
Stored *p = (Stored *) hb_calloc (1, sizeof (Stored));
|
||||
if (likely (p))
|
||||
p->init (data);
|
||||
return p;
|
||||
}
|
||||
static Stored *create ()
|
||||
{
|
||||
Stored *p = (Stored *) calloc (1, sizeof (Stored));
|
||||
Stored *p = (Stored *) hb_calloc (1, sizeof (Stored));
|
||||
if (likely (p))
|
||||
p->init ();
|
||||
return p;
|
||||
|
|
@ -257,7 +257,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
|
|||
static void destroy (Stored *p)
|
||||
{
|
||||
p->fini ();
|
||||
free (p);
|
||||
hb_free (p);
|
||||
}
|
||||
|
||||
// private:
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ hb_map_destroy (hb_map_t *map)
|
|||
|
||||
map->fini_shallow ();
|
||||
|
||||
free (map);
|
||||
hb_free (map);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ struct hb_hashmap_t
|
|||
}
|
||||
void fini_shallow ()
|
||||
{
|
||||
free (items);
|
||||
hb_free (items);
|
||||
items = nullptr;
|
||||
population = occupancy = 0;
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ struct hb_hashmap_t
|
|||
|
||||
unsigned int power = hb_bit_storage (population * 2 + 8);
|
||||
unsigned int new_size = 1u << power;
|
||||
item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
|
||||
item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t));
|
||||
if (unlikely (!new_items))
|
||||
{
|
||||
successful = false;
|
||||
|
|
@ -135,14 +135,14 @@ struct hb_hashmap_t
|
|||
old_items[i].hash,
|
||||
old_items[i].value);
|
||||
|
||||
free (old_items);
|
||||
hb_free (old_items);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void set (K key, V value)
|
||||
bool set (K key, V value)
|
||||
{
|
||||
set_with_hash (key, hb_hash (key), value);
|
||||
return set_with_hash (key, hb_hash (key), value);
|
||||
}
|
||||
|
||||
V get (K key) const
|
||||
|
|
@ -211,20 +211,20 @@ struct hb_hashmap_t
|
|||
|
||||
protected:
|
||||
|
||||
void set_with_hash (K key, uint32_t hash, V value)
|
||||
bool set_with_hash (K key, uint32_t hash, V value)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
if (unlikely (key == kINVALID)) return;
|
||||
if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
|
||||
if (unlikely (!successful)) return false;
|
||||
if (unlikely (key == kINVALID)) return true;
|
||||
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
|
||||
unsigned int i = bucket_for_hash (key, hash);
|
||||
|
||||
if (value == vINVALID && items[i].key != key)
|
||||
return; /* Trying to delete non-existent key. */
|
||||
return true; /* Trying to delete non-existent key. */
|
||||
|
||||
if (!items[i].is_unused ())
|
||||
{
|
||||
occupancy--;
|
||||
if (items[i].is_tombstone ())
|
||||
if (!items[i].is_tombstone ())
|
||||
population--;
|
||||
}
|
||||
|
||||
|
|
@ -235,6 +235,8 @@ struct hb_hashmap_t
|
|||
occupancy++;
|
||||
if (!items[i].is_tombstone ())
|
||||
population++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int bucket_for (K key) const
|
||||
|
|
|
|||
|
|
@ -101,14 +101,14 @@ HB_FUNCOBJ (hb_addressof);
|
|||
template <typename T> static inline T hb_declval ();
|
||||
#define hb_declval(T) (hb_declval<T> ())
|
||||
|
||||
template <typename T> struct hb_match_const : hb_type_identity_t<T>, hb_bool_constant<false>{};
|
||||
template <typename T> struct hb_match_const<const T> : hb_type_identity_t<T>, hb_bool_constant<true> {};
|
||||
template <typename T> struct hb_match_const : hb_type_identity_t<T>, hb_false_type {};
|
||||
template <typename T> struct hb_match_const<const T> : hb_type_identity_t<T>, hb_true_type {};
|
||||
template <typename T> using hb_remove_const = typename hb_match_const<T>::type;
|
||||
template <typename T> using hb_add_const = const T;
|
||||
#define hb_is_const(T) hb_match_const<T>::value
|
||||
template <typename T> struct hb_match_reference : hb_type_identity_t<T>, hb_bool_constant<false>{};
|
||||
template <typename T> struct hb_match_reference<T &> : hb_type_identity_t<T>, hb_bool_constant<true> {};
|
||||
template <typename T> struct hb_match_reference<T &&> : hb_type_identity_t<T>, hb_bool_constant<true> {};
|
||||
template <typename T> struct hb_match_reference : hb_type_identity_t<T>, hb_false_type {};
|
||||
template <typename T> struct hb_match_reference<T &> : hb_type_identity_t<T>, hb_true_type {};
|
||||
template <typename T> struct hb_match_reference<T &&> : hb_type_identity_t<T>, hb_true_type {};
|
||||
template <typename T> using hb_remove_reference = typename hb_match_reference<T>::type;
|
||||
template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<1>) -> hb_type_identity<T&>;
|
||||
template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
|
||||
|
|
@ -117,8 +117,8 @@ template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_t
|
|||
template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
|
||||
template <typename T> using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference<T> (hb_prioritize));
|
||||
#define hb_is_reference(T) hb_match_reference<T>::value
|
||||
template <typename T> struct hb_match_pointer : hb_type_identity_t<T>, hb_bool_constant<false>{};
|
||||
template <typename T> struct hb_match_pointer<T *> : hb_type_identity_t<T>, hb_bool_constant<true> {};
|
||||
template <typename T> struct hb_match_pointer : hb_type_identity_t<T>, hb_false_type {};
|
||||
template <typename T> struct hb_match_pointer<T *> : hb_type_identity_t<T>, hb_true_type {};
|
||||
template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
|
||||
template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<hb_remove_reference<T>*>;
|
||||
template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<T>;
|
||||
|
|
@ -259,15 +259,15 @@ using hb_is_arithmetic = hb_bool_constant<
|
|||
#define hb_is_arithmetic(T) hb_is_arithmetic<T>::value
|
||||
|
||||
|
||||
template <typename T>
|
||||
using hb_is_signed = hb_conditional<hb_is_arithmetic (T),
|
||||
hb_bool_constant<(T) -1 < (T) 0>,
|
||||
hb_false_type>;
|
||||
template <typename T, bool is_arithmetic> struct hb_is_signed_;
|
||||
template <typename T> struct hb_is_signed_<T, false> : hb_false_type {};
|
||||
template <typename T> struct hb_is_signed_<T, true> : hb_bool_constant<(T) -1 < (T) 0> {};
|
||||
template <typename T> struct hb_is_signed : hb_is_signed_<T, hb_is_arithmetic (T)> {};
|
||||
#define hb_is_signed(T) hb_is_signed<T>::value
|
||||
template <typename T>
|
||||
using hb_is_unsigned = hb_conditional<hb_is_arithmetic (T),
|
||||
hb_bool_constant<(T) 0 < (T) -1>,
|
||||
hb_false_type>;
|
||||
template <typename T, bool is_arithmetic> struct hb_is_unsigned_;
|
||||
template <typename T> struct hb_is_unsigned_<T, false> : hb_false_type {};
|
||||
template <typename T> struct hb_is_unsigned_<T, true> : hb_bool_constant<(T) 0 < (T) -1> {};
|
||||
template <typename T> struct hb_is_unsigned : hb_is_unsigned_<T, hb_is_arithmetic (T)> {};
|
||||
#define hb_is_unsigned(T) hb_is_unsigned<T>::value
|
||||
|
||||
template <typename T> struct hb_int_min;
|
||||
|
|
@ -282,6 +282,7 @@ template <> struct hb_int_min<signed long> : hb_integral_constant<signed long,
|
|||
template <> struct hb_int_min<unsigned long> : hb_integral_constant<unsigned long, 0> {};
|
||||
template <> struct hb_int_min<signed long long> : hb_integral_constant<signed long long, LLONG_MIN> {};
|
||||
template <> struct hb_int_min<unsigned long long> : hb_integral_constant<unsigned long long, 0> {};
|
||||
template <typename T> struct hb_int_min<T *> : hb_integral_constant<T *, nullptr> {};
|
||||
#define hb_int_min(T) hb_int_min<T>::value
|
||||
template <typename T> struct hb_int_max;
|
||||
template <> struct hb_int_max<char> : hb_integral_constant<char, CHAR_MAX> {};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright © 2011,2012,2013 Google, Inc.
|
||||
* Copyright © 2021 Khaled Hosny
|
||||
*
|
||||
* 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): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb-ms-feature-ranges.hh"
|
||||
|
||||
bool
|
||||
hb_ms_setup_features (const hb_feature_t *features,
|
||||
unsigned int num_features,
|
||||
hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */
|
||||
hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */)
|
||||
{
|
||||
feature_records.shrink(0);
|
||||
range_records.shrink(0);
|
||||
|
||||
/* Sort features by start/end events. */
|
||||
hb_vector_t<hb_ms_feature_event_t> feature_events;
|
||||
for (unsigned int i = 0; i < num_features; i++)
|
||||
{
|
||||
hb_ms_active_feature_t feature;
|
||||
feature.fea.tag_le = hb_uint32_swap (features[i].tag);
|
||||
feature.fea.value = features[i].value;
|
||||
feature.order = i;
|
||||
|
||||
hb_ms_feature_event_t *event;
|
||||
|
||||
event = feature_events.push ();
|
||||
event->index = features[i].start;
|
||||
event->start = true;
|
||||
event->feature = feature;
|
||||
|
||||
event = feature_events.push ();
|
||||
event->index = features[i].end;
|
||||
event->start = false;
|
||||
event->feature = feature;
|
||||
}
|
||||
feature_events.qsort ();
|
||||
/* Add a strategic final event. */
|
||||
{
|
||||
hb_ms_active_feature_t feature;
|
||||
feature.fea.tag_le = 0;
|
||||
feature.fea.value = 0;
|
||||
feature.order = num_features + 1;
|
||||
|
||||
auto *event = feature_events.push ();
|
||||
event->index = 0; /* This value does magic. */
|
||||
event->start = false;
|
||||
event->feature = feature;
|
||||
}
|
||||
|
||||
/* Scan events and save features for each range. */
|
||||
hb_vector_t<hb_ms_active_feature_t> active_features;
|
||||
unsigned int last_index = 0;
|
||||
for (unsigned int i = 0; i < feature_events.length; i++)
|
||||
{
|
||||
auto *event = &feature_events[i];
|
||||
|
||||
if (event->index != last_index)
|
||||
{
|
||||
/* Save a snapshot of active features and the range. */
|
||||
auto *range = range_records.push ();
|
||||
auto offset = feature_records.length;
|
||||
|
||||
active_features.qsort ();
|
||||
for (unsigned int j = 0; j < active_features.length; j++)
|
||||
{
|
||||
if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le)
|
||||
{
|
||||
feature_records.push (active_features[j].fea);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Overrides value for existing feature. */
|
||||
feature_records[feature_records.length - 1].value = active_features[j].fea.value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Will convert to pointer after all is ready, since feature_records.array
|
||||
* may move as we grow it. */
|
||||
range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset);
|
||||
range->features.num_features = feature_records.length - offset;
|
||||
range->index_first = last_index;
|
||||
range->index_last = event->index - 1;
|
||||
|
||||
last_index = event->index;
|
||||
}
|
||||
|
||||
if (event->start)
|
||||
{
|
||||
active_features.push (event->feature);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto *feature = active_features.find (&event->feature);
|
||||
if (feature)
|
||||
active_features.remove (feature - active_features.arrayZ);
|
||||
}
|
||||
}
|
||||
|
||||
if (!range_records.length) /* No active feature found. */
|
||||
num_features = 0;
|
||||
|
||||
/* Fixup the pointers. */
|
||||
for (unsigned int i = 0; i < range_records.length; i++)
|
||||
{
|
||||
auto *range = &range_records[i];
|
||||
range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features);
|
||||
}
|
||||
|
||||
return !!num_features;
|
||||
}
|
||||
|
||||
void
|
||||
hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records,
|
||||
hb_vector_t<hb_ms_range_record_t> &range_records,
|
||||
unsigned int chars_offset,
|
||||
unsigned int chars_len,
|
||||
uint16_t *log_clusters,
|
||||
hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */
|
||||
hb_vector_t<uint32_t> &range_counts /* OUT */)
|
||||
{
|
||||
range_features.shrink (0);
|
||||
range_counts.shrink (0);
|
||||
|
||||
auto *last_range = &range_records[0];
|
||||
for (unsigned int i = chars_offset; i < chars_len; i++)
|
||||
{
|
||||
auto *range = last_range;
|
||||
while (log_clusters[i] < range->index_first)
|
||||
range--;
|
||||
while (log_clusters[i] > range->index_last)
|
||||
range++;
|
||||
if (!range_features.length ||
|
||||
&range->features != range_features[range_features.length - 1])
|
||||
{
|
||||
auto **features = range_features.push ();
|
||||
auto *c = range_counts.push ();
|
||||
if (unlikely (!features || !c))
|
||||
{
|
||||
range_features.shrink (0);
|
||||
range_counts.shrink (0);
|
||||
break;
|
||||
}
|
||||
*features = &range->features;
|
||||
*c = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
range_counts[range_counts.length - 1]++;
|
||||
}
|
||||
|
||||
last_range = range;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright © 2011,2012,2013 Google, Inc.
|
||||
* Copyright © 2021 Khaled Hosny
|
||||
*
|
||||
* 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): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_MS_FEATURE_RANGES_HH
|
||||
#define HB_MS_FEATURE_RANGES_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
typedef struct hb_ms_feature_t {
|
||||
uint32_t tag_le;
|
||||
uint32_t value;
|
||||
} hb_ms_feature_t;
|
||||
|
||||
typedef struct hb_ms_features_t {
|
||||
hb_ms_feature_t *features;
|
||||
uint32_t num_features;
|
||||
} hb_ms_features_t;
|
||||
|
||||
struct hb_ms_active_feature_t {
|
||||
hb_ms_feature_t fea;
|
||||
unsigned int order;
|
||||
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb) {
|
||||
const auto *a = (const hb_ms_active_feature_t *) pa;
|
||||
const auto *b = (const hb_ms_active_feature_t *) pb;
|
||||
return a->fea.tag_le < b->fea.tag_le ? -1 : a->fea.tag_le > b->fea.tag_le ? 1 :
|
||||
a->order < b->order ? -1 : a->order > b->order ? 1 :
|
||||
a->fea.value < b->fea.value ? -1 : a->fea.value > b->fea.value ? 1 :
|
||||
0;
|
||||
}
|
||||
bool operator== (const hb_ms_active_feature_t *f)
|
||||
{ return cmp (this, f) == 0; }
|
||||
};
|
||||
|
||||
struct hb_ms_feature_event_t {
|
||||
unsigned int index;
|
||||
bool start;
|
||||
hb_ms_active_feature_t feature;
|
||||
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb)
|
||||
{
|
||||
const auto *a = (const hb_ms_feature_event_t *) pa;
|
||||
const auto *b = (const hb_ms_feature_event_t *) pb;
|
||||
return a->index < b->index ? -1 : a->index > b->index ? 1 :
|
||||
a->start < b->start ? -1 : a->start > b->start ? 1 :
|
||||
hb_ms_active_feature_t::cmp (&a->feature, &b->feature);
|
||||
}
|
||||
};
|
||||
|
||||
struct hb_ms_range_record_t {
|
||||
hb_ms_features_t features;
|
||||
unsigned int index_first; /* == start */
|
||||
unsigned int index_last; /* == end - 1 */
|
||||
};
|
||||
|
||||
HB_INTERNAL bool
|
||||
hb_ms_setup_features (const hb_feature_t *features,
|
||||
unsigned int num_features,
|
||||
hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */
|
||||
hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */);
|
||||
|
||||
|
||||
HB_INTERNAL void
|
||||
hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records,
|
||||
hb_vector_t<hb_ms_range_record_t> &range_records,
|
||||
unsigned int chars_offset,
|
||||
unsigned int chars_len,
|
||||
uint16_t *log_clusters,
|
||||
hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */
|
||||
hb_vector_t<uint32_t> &range_counts /* OUT */);
|
||||
|
||||
#endif /* HB_MS_FEATURE_RANGES_HH */
|
||||
|
|
@ -39,8 +39,7 @@
|
|||
|
||||
/* We need external help for these */
|
||||
|
||||
#if defined(HB_MUTEX_IMPL_INIT) \
|
||||
&& defined(hb_mutex_impl_init) \
|
||||
#if defined(hb_mutex_impl_init) \
|
||||
&& defined(hb_mutex_impl_lock) \
|
||||
&& defined(hb_mutex_impl_unlock) \
|
||||
&& defined(hb_mutex_impl_finish)
|
||||
|
|
@ -52,7 +51,6 @@
|
|||
|
||||
#include <pthread.h>
|
||||
typedef pthread_mutex_t hb_mutex_impl_t;
|
||||
#define HB_MUTEX_IMPL_INIT PTHREAD_MUTEX_INITIALIZER
|
||||
#define hb_mutex_impl_init(M) pthread_mutex_init (M, nullptr)
|
||||
#define hb_mutex_impl_lock(M) pthread_mutex_lock (M)
|
||||
#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M)
|
||||
|
|
@ -62,7 +60,6 @@ typedef pthread_mutex_t hb_mutex_impl_t;
|
|||
#elif !defined(HB_NO_MT) && defined(_WIN32)
|
||||
|
||||
typedef CRITICAL_SECTION hb_mutex_impl_t;
|
||||
#define HB_MUTEX_IMPL_INIT {0}
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0)
|
||||
#else
|
||||
|
|
@ -76,7 +73,6 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
|
|||
#elif defined(HB_NO_MT)
|
||||
|
||||
typedef int hb_mutex_impl_t;
|
||||
#define HB_MUTEX_IMPL_INIT 0
|
||||
#define hb_mutex_impl_init(M) HB_STMT_START {} HB_STMT_END
|
||||
#define hb_mutex_impl_lock(M) HB_STMT_START {} HB_STMT_END
|
||||
#define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END
|
||||
|
|
@ -91,8 +87,6 @@ typedef int hb_mutex_impl_t;
|
|||
#endif
|
||||
|
||||
|
||||
#define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT}
|
||||
|
||||
struct hb_mutex_t
|
||||
{
|
||||
hb_mutex_impl_t m;
|
||||
|
|
|
|||
|
|
@ -39,8 +39,11 @@
|
|||
|
||||
#define HB_NULL_POOL_SIZE 384
|
||||
|
||||
/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
|
||||
* otherwise return sizeof(T). */
|
||||
/* Use SFINAE to sniff whether T has min_size; in which case return the larger
|
||||
* of sizeof(T) and T::null_size, otherwise return sizeof(T).
|
||||
*
|
||||
* The main purpose of this is to let structs communicate that they are not nullable,
|
||||
* by defining min_size but *not* null_size. */
|
||||
|
||||
/* The hard way...
|
||||
* https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
|
||||
|
|
@ -49,8 +52,9 @@
|
|||
template <typename T, typename>
|
||||
struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {};
|
||||
template <typename T>
|
||||
struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::null_size> {};
|
||||
|
||||
struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>>
|
||||
: hb_integral_constant<unsigned,
|
||||
(sizeof (T) > T::null_size ? sizeof (T) : T::null_size)> {};
|
||||
template <typename T>
|
||||
using hb_null_size = _hb_null_size<T, void>;
|
||||
#define hb_null_size(T) hb_null_size<T>::value
|
||||
|
|
@ -68,6 +72,14 @@ template <typename T>
|
|||
using hb_static_size = _hb_static_size<T, void>;
|
||||
#define hb_static_size(T) hb_static_size<T>::value
|
||||
|
||||
template <typename T, typename>
|
||||
struct _hb_min_size : hb_integral_constant<unsigned, sizeof (T)> {};
|
||||
template <typename T>
|
||||
struct _hb_min_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::min_size> {};
|
||||
template <typename T>
|
||||
using hb_min_size = _hb_min_size<T, void>;
|
||||
#define hb_min_size(T) hb_min_size<T>::value
|
||||
|
||||
|
||||
/*
|
||||
* Null()
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ static inline void hb_object_trace (const Type *obj, const char *function)
|
|||
template <typename Type>
|
||||
static inline Type *hb_object_create ()
|
||||
{
|
||||
Type *obj = (Type *) calloc (1, sizeof (Type));
|
||||
Type *obj = (Type *) hb_calloc (1, sizeof (Type));
|
||||
|
||||
if (unlikely (!obj))
|
||||
return obj;
|
||||
|
|
@ -284,7 +284,7 @@ static inline void hb_object_fini (Type *obj)
|
|||
if (user_data)
|
||||
{
|
||||
user_data->fini ();
|
||||
free (user_data);
|
||||
hb_free (user_data);
|
||||
user_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -303,14 +303,14 @@ retry:
|
|||
hb_user_data_array_t *user_data = obj->header.user_data.get ();
|
||||
if (unlikely (!user_data))
|
||||
{
|
||||
user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
|
||||
user_data = (hb_user_data_array_t *) hb_calloc (sizeof (hb_user_data_array_t), 1);
|
||||
if (unlikely (!user_data))
|
||||
return false;
|
||||
user_data->init ();
|
||||
if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data)))
|
||||
{
|
||||
user_data->fini ();
|
||||
free (user_data);
|
||||
hb_free (user_data);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
namespace OT {
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* The OpenType Font File
|
||||
|
|
@ -102,7 +101,13 @@ typedef struct OpenTypeOffsetTable
|
|||
{
|
||||
Tag t;
|
||||
t = tag;
|
||||
return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
/* Use lfind for small fonts; there are fonts that have unsorted table entries;
|
||||
* those tend to work in other tools, so tolerate them.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/3065 */
|
||||
if (tables.len < 16)
|
||||
return tables.lfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
else
|
||||
return tables.bfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
}
|
||||
const TableRecord& get_table_by_tag (hb_tag_t tag) const
|
||||
{
|
||||
|
|
@ -113,44 +118,53 @@ typedef struct OpenTypeOffsetTable
|
|||
|
||||
public:
|
||||
|
||||
template <typename item_t>
|
||||
template <typename Iterator,
|
||||
hb_requires ((hb_is_source_of<Iterator, hb_pair_t<hb_tag_t, hb_blob_t *>>::value))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_tag_t sfnt_tag,
|
||||
hb_array_t<item_t> items)
|
||||
Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
/* Alloc 12 for the OTHeader. */
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
/* Write sfntVersion (bytes 0..3). */
|
||||
sfnt_version = sfnt_tag;
|
||||
/* Take space for numTables, searchRange, entrySelector, RangeShift
|
||||
* and the TableRecords themselves. */
|
||||
if (unlikely (!tables.serialize (c, items.length))) return_trace (false);
|
||||
unsigned num_items = it.len ();
|
||||
if (unlikely (!tables.serialize (c, num_items))) return_trace (false);
|
||||
|
||||
const char *dir_end = (const char *) c->head;
|
||||
HBUINT32 *checksum_adjustment = nullptr;
|
||||
|
||||
/* Write OffsetTables, alloc for and write actual table blobs. */
|
||||
for (unsigned int i = 0; i < tables.len; i++)
|
||||
unsigned i = 0;
|
||||
for (hb_pair_t<hb_tag_t, hb_blob_t*> entry : it)
|
||||
{
|
||||
TableRecord &rec = tables.arrayZ[i];
|
||||
hb_blob_t *blob = items[i].blob;
|
||||
rec.tag = items[i].tag;
|
||||
rec.length = blob->length;
|
||||
rec.offset.serialize (c, this);
|
||||
hb_blob_t *blob = entry.second;
|
||||
unsigned len = blob->length;
|
||||
|
||||
/* Allocate room for the table and copy it. */
|
||||
char *start = (char *) c->allocate_size<void> (rec.length);
|
||||
char *start = (char *) c->allocate_size<void> (len);
|
||||
if (unlikely (!start)) return false;
|
||||
|
||||
if (likely (rec.length))
|
||||
memcpy (start, blob->data, rec.length);
|
||||
TableRecord &rec = tables.arrayZ[i];
|
||||
rec.tag = entry.first;
|
||||
rec.length = len;
|
||||
rec.offset = 0;
|
||||
if (unlikely (!c->check_assign (rec.offset,
|
||||
(unsigned) ((char *) start - (char *) this),
|
||||
HB_SERIALIZE_ERROR_OFFSET_OVERFLOW)))
|
||||
return_trace (false);
|
||||
|
||||
if (likely (len))
|
||||
memcpy (start, blob->data, len);
|
||||
|
||||
/* 4-byte alignment. */
|
||||
c->align (4);
|
||||
const char *end = (const char *) c->head;
|
||||
|
||||
if (items[i].tag == HB_OT_TAG_head &&
|
||||
if (entry.first == HB_OT_TAG_head &&
|
||||
(unsigned) (end - start) >= head::static_size)
|
||||
{
|
||||
head *h = (head *) start;
|
||||
|
|
@ -159,6 +173,7 @@ typedef struct OpenTypeOffsetTable
|
|||
}
|
||||
|
||||
rec.checkSum.set_for_data (start, end - start);
|
||||
i++;
|
||||
}
|
||||
|
||||
tables.qsort ();
|
||||
|
|
@ -170,7 +185,7 @@ typedef struct OpenTypeOffsetTable
|
|||
/* The following line is a slower version of the following block. */
|
||||
//checksum.set_for_data (this, (const char *) c->head - (const char *) this);
|
||||
checksum.set_for_data (this, dir_end - (const char *) this);
|
||||
for (unsigned int i = 0; i < items.length; i++)
|
||||
for (unsigned int i = 0; i < num_items; i++)
|
||||
{
|
||||
TableRecord &rec = tables.arrayZ[i];
|
||||
checksum = checksum + rec.checkSum;
|
||||
|
|
@ -218,7 +233,7 @@ struct TTCHeaderVersion1
|
|||
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
|
||||
FixedVersion<>version; /* Version of the TTC Header (1.0),
|
||||
* 0x00010000u */
|
||||
LArrayOf<LOffsetTo<OpenTypeOffsetTable>>
|
||||
Array32Of<Offset32To<OpenTypeOffsetTable>>
|
||||
table; /* Array of offsets to the OffsetTable for each font
|
||||
* from the beginning of the file */
|
||||
public:
|
||||
|
|
@ -295,7 +310,7 @@ struct ResourceRecord
|
|||
HBINT16 nameOffset; /* Offset from beginning of resource name list
|
||||
* to resource name, -1 means there is none. */
|
||||
HBUINT8 attrs; /* Resource attributes */
|
||||
NNOffsetTo<LArrayOf<HBUINT8>, HBUINT24>
|
||||
NNOffset24To<Array32Of<HBUINT8>>
|
||||
offset; /* Offset from beginning of data block to
|
||||
* data for this resource */
|
||||
HBUINT32 reserved; /* Reserved for handle to resource */
|
||||
|
|
@ -330,7 +345,7 @@ struct ResourceTypeRecord
|
|||
protected:
|
||||
Tag tag; /* Resource type. */
|
||||
HBUINT16 resCountM1; /* Number of resources minus 1. */
|
||||
NNOffsetTo<UnsizedArrayOf<ResourceRecord>>
|
||||
NNOffset16To<UnsizedArrayOf<ResourceRecord>>
|
||||
resourcesZ; /* Offset from beginning of resource type list
|
||||
* to reference item list for this type. */
|
||||
public:
|
||||
|
|
@ -386,7 +401,7 @@ struct ResourceMap
|
|||
HBUINT32 reserved1; /* Reserved for handle to next resource map */
|
||||
HBUINT16 resreved2; /* Reserved for file reference number */
|
||||
HBUINT16 attrs; /* Resource fork attribute */
|
||||
NNOffsetTo<ArrayOfM1<ResourceTypeRecord>>
|
||||
NNOffset16To<ArrayOfM1<ResourceTypeRecord>>
|
||||
typeList; /* Offset from beginning of map to
|
||||
* resource type list */
|
||||
Offset16 nameList; /* Offset from beginning of map to
|
||||
|
|
@ -418,10 +433,10 @@ struct ResourceForkHeader
|
|||
}
|
||||
|
||||
protected:
|
||||
LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT8>>
|
||||
data; /* Offset from beginning of resource fork
|
||||
* to resource data */
|
||||
LNNOffsetTo<ResourceMap >
|
||||
NNOffset32To<ResourceMap >
|
||||
map; /* Offset from beginning of resource fork
|
||||
* to resource map */
|
||||
HBUINT32 dataLen; /* Length of resource data */
|
||||
|
|
@ -477,14 +492,15 @@ struct OpenTypeFontFile
|
|||
}
|
||||
}
|
||||
|
||||
template <typename item_t>
|
||||
template <typename Iterator,
|
||||
hb_requires ((hb_is_source_of<Iterator, hb_pair_t<hb_tag_t, hb_blob_t *>>::value))>
|
||||
bool serialize_single (hb_serialize_context_t *c,
|
||||
hb_tag_t sfnt_tag,
|
||||
hb_array_t<item_t> items)
|
||||
Iterator items)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
assert (sfnt_tag != TTCTag);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
return_trace (u.fontFace.serialize (c, sfnt_tag, items));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,6 +196,12 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
|
|||
|
||||
typedef Index NameID;
|
||||
|
||||
struct VarIdx : HBUINT32 {
|
||||
static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu;
|
||||
VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
|
||||
};
|
||||
DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx);
|
||||
|
||||
/* Offset, Null offset = 0 */
|
||||
template <typename Type, bool has_null=true>
|
||||
struct Offset : Type
|
||||
|
|
@ -206,18 +212,12 @@ struct Offset : Type
|
|||
|
||||
bool is_null () const { return has_null && 0 == *this; }
|
||||
|
||||
void *serialize (hb_serialize_context_t *c, const void *base)
|
||||
{
|
||||
void *t = c->start_embed<void> ();
|
||||
c->check_assign (*this, (unsigned) ((char *) t - (char *) base));
|
||||
return t;
|
||||
}
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (sizeof (Type));
|
||||
};
|
||||
|
||||
typedef Offset<HBUINT16> Offset16;
|
||||
typedef Offset<HBUINT24> Offset24;
|
||||
typedef Offset<HBUINT32> Offset32;
|
||||
|
||||
|
||||
|
|
@ -287,7 +287,7 @@ struct _hb_has_null<Type, true>
|
|||
static Type *get_crap () { return &Crap (Type); }
|
||||
};
|
||||
|
||||
template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
|
||||
template <typename Type, typename OffsetType, bool has_null=true>
|
||||
struct OffsetTo : Offset<OffsetType, has_null>
|
||||
{
|
||||
HB_DELETE_COPY_ASSIGN (OffsetTo);
|
||||
|
|
@ -319,10 +319,6 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
hb_enable_if (hb_is_convertible (Base, void *))>
|
||||
friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); }
|
||||
|
||||
Type& serialize (hb_serialize_context_t *c, const void *base)
|
||||
{
|
||||
return * (Type *) Offset<OffsetType>::serialize (c, base);
|
||||
}
|
||||
|
||||
template <typename ...Ts>
|
||||
bool serialize_subset (hb_subset_context_t *c, const OffsetTo& src,
|
||||
|
|
@ -346,6 +342,23 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template <typename ...Ts>
|
||||
bool serialize_serialize (hb_serialize_context_t *c, Ts&&... ds)
|
||||
{
|
||||
*this = 0;
|
||||
|
||||
Type* obj = c->push<Type> ();
|
||||
bool ret = obj->serialize (c, hb_forward<Ts> (ds)...);
|
||||
|
||||
if (ret)
|
||||
c->add_link (*this, c->pop_pack ());
|
||||
else
|
||||
c->pop_discard ();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: Somehow merge this with previous function into a serialize_dispatch(). */
|
||||
/* Workaround clang bug: https://bugs.llvm.org/show_bug.cgi?id=23029
|
||||
* Can't compile: whence = hb_serialize_context_t::Head followed by Ts&&...
|
||||
|
|
@ -378,7 +391,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this))) return_trace (false);
|
||||
if (unlikely (this->is_null ())) return_trace (true);
|
||||
if (unlikely (!c->check_range (base, *this))) return_trace (false);
|
||||
if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
@ -401,12 +414,14 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
DEFINE_SIZE_STATIC (sizeof (OffsetType));
|
||||
};
|
||||
/* Partial specializations. */
|
||||
template <typename Type, bool has_null=true>
|
||||
using LOffsetTo = OffsetTo<Type, HBUINT32, has_null>;
|
||||
template <typename Type, typename OffsetType=HBUINT16>
|
||||
using NNOffsetTo = OffsetTo<Type, OffsetType, false>;
|
||||
template <typename Type>
|
||||
using LNNOffsetTo = LOffsetTo<Type, false>;
|
||||
template <typename Type, bool has_null=true> using Offset16To = OffsetTo<Type, HBUINT16, has_null>;
|
||||
template <typename Type, bool has_null=true> using Offset24To = OffsetTo<Type, HBUINT24, has_null>;
|
||||
template <typename Type, bool has_null=true> using Offset32To = OffsetTo<Type, HBUINT32, has_null>;
|
||||
|
||||
template <typename Type, typename OffsetType> using NNOffsetTo = OffsetTo<Type, OffsetType, false>;
|
||||
template <typename Type> using NNOffset16To = Offset16To<Type, false>;
|
||||
template <typename Type> using NNOffset24To = Offset24To<Type, false>;
|
||||
template <typename Type> using NNOffset32To = Offset32To<Type, false>;
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -453,8 +468,10 @@ struct UnsizedArrayOf
|
|||
const Type &lsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const
|
||||
{ return *as_array (len).lsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
bool lfind (unsigned int len, const T &x, unsigned *pos = nullptr) const
|
||||
{ return as_array (len).lfind (x, pos); }
|
||||
bool lfind (unsigned int len, const T &x, unsigned int *i = nullptr,
|
||||
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{ return as_array (len).lfind (x, i, not_found, to_store); }
|
||||
|
||||
void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
|
||||
{ as_array (len).qsort (start, end); }
|
||||
|
|
@ -462,7 +479,7 @@ struct UnsizedArrayOf
|
|||
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend (*this, items_len))) return_trace (false);
|
||||
if (unlikely (!c->extend (this, items_len))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
template <typename Iterator,
|
||||
|
|
@ -513,11 +530,11 @@ struct UnsizedArrayOf
|
|||
|
||||
/* Unsized array of offset's */
|
||||
template <typename Type, typename OffsetType, bool has_null=true>
|
||||
using UnsizedOffsetArrayOf = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>;
|
||||
using UnsizedArray16OfOffsetTo = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>;
|
||||
|
||||
/* Unsized array of offsets relative to the beginning of the array itself. */
|
||||
template <typename Type, typename OffsetType, bool has_null=true>
|
||||
struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
|
||||
struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
|
||||
{
|
||||
const Type& operator [] (int i_) const
|
||||
{
|
||||
|
|
@ -538,7 +555,7 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
|
|||
bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>
|
||||
return_trace ((UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
|
||||
::sanitize (c, count, this, hb_forward<Ts> (ds)...)));
|
||||
}
|
||||
};
|
||||
|
|
@ -562,14 +579,14 @@ struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
|
|||
{ return *as_array (len).bsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr,
|
||||
hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{ return as_array (len).bfind (x, i, not_found, to_store); }
|
||||
};
|
||||
|
||||
|
||||
/* An array with a number of elements. */
|
||||
template <typename Type, typename LenType=HBUINT16>
|
||||
template <typename Type, typename LenType>
|
||||
struct ArrayOf
|
||||
{
|
||||
typedef Type item_t;
|
||||
|
|
@ -617,17 +634,32 @@ struct ArrayOf
|
|||
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
|
||||
hb_success_t serialize (hb_serialize_context_t *c, unsigned items_len)
|
||||
template <typename T>
|
||||
Type &lsearch (const T &x, Type ¬_found = Crap (Type))
|
||||
{ return *as_array ().lsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const
|
||||
{ return *as_array ().lsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
bool lfind (const T &x, unsigned int *i = nullptr,
|
||||
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{ return as_array ().lfind (x, i, not_found, to_store); }
|
||||
|
||||
void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
|
||||
{ as_array ().qsort (start, end); }
|
||||
|
||||
HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
c->check_assign (len, items_len);
|
||||
if (unlikely (!c->extend (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
|
||||
if (unlikely (!c->extend (this))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_source_of (Iterator, Type))>
|
||||
hb_success_t serialize (hb_serialize_context_t *c, Iterator items)
|
||||
HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
unsigned count = items.len ();
|
||||
|
|
@ -643,7 +675,7 @@ struct ArrayOf
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
len++;
|
||||
if (unlikely (!len || !c->extend (*this)))
|
||||
if (unlikely (!len || !c->extend (this)))
|
||||
{
|
||||
len--;
|
||||
return_trace (nullptr);
|
||||
|
|
@ -656,7 +688,7 @@ struct ArrayOf
|
|||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->start_embed (this);
|
||||
if (unlikely (!c->extend_min (out))) return_trace (nullptr);
|
||||
c->check_assign (out->len, len);
|
||||
c->check_assign (out->len, len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
|
||||
if (unlikely (!as_array ().copy (c))) return_trace (nullptr);
|
||||
return_trace (out);
|
||||
}
|
||||
|
|
@ -674,19 +706,6 @@ struct ArrayOf
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Type &lsearch (const T &x, Type ¬_found = Crap (Type))
|
||||
{ return *as_array ().lsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const
|
||||
{ return *as_array ().lsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
bool lfind (const T &x, unsigned *pos = nullptr) const
|
||||
{ return as_array ().lfind (x, pos); }
|
||||
|
||||
void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
|
||||
{ as_array ().qsort (start, end); }
|
||||
|
||||
bool sanitize_shallow (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -699,21 +718,18 @@ struct ArrayOf
|
|||
public:
|
||||
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
|
||||
};
|
||||
template <typename Type>
|
||||
using LArrayOf = ArrayOf<Type, HBUINT32>;
|
||||
template <typename Type> using Array16Of = ArrayOf<Type, HBUINT16>;
|
||||
template <typename Type> using Array32Of = ArrayOf<Type, HBUINT32>;
|
||||
using PString = ArrayOf<HBUINT8, HBUINT8>;
|
||||
|
||||
/* Array of Offset's */
|
||||
template <typename Type>
|
||||
using OffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT16>>;
|
||||
template <typename Type>
|
||||
using LOffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>>;
|
||||
template <typename Type>
|
||||
using LOffsetLArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
|
||||
template <typename Type> using Array16OfOffset16To = ArrayOf<OffsetTo<Type, HBUINT16>, HBUINT16>;
|
||||
template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT16>;
|
||||
template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
|
||||
|
||||
/* Array of offsets relative to the beginning of the array itself. */
|
||||
template <typename Type>
|
||||
struct OffsetListOf : OffsetArrayOf<Type>
|
||||
struct List16OfOffset16To : Array16OfOffset16To<Type>
|
||||
{
|
||||
const Type& operator [] (int i_) const
|
||||
{
|
||||
|
|
@ -731,7 +747,7 @@ struct OffsetListOf : OffsetArrayOf<Type>
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
struct OffsetListOf<Type> *out = c->serializer->embed (*this);
|
||||
struct List16OfOffset16To<Type> *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
unsigned int count = this->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
|
|
@ -743,7 +759,7 @@ struct OffsetListOf : OffsetArrayOf<Type>
|
|||
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (OffsetArrayOf<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
|
||||
return_trace (Array16OfOffset16To<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -786,9 +802,9 @@ struct HeadlessArrayOf
|
|||
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
c->check_assign (lenP1, items_len + 1);
|
||||
if (unlikely (!c->extend (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
|
||||
if (unlikely (!c->extend (this))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
template <typename Iterator,
|
||||
|
|
@ -859,6 +875,7 @@ struct ArrayOfM1
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||
if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
|
||||
unsigned int count = lenM1 + 1;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
|
||||
|
|
@ -882,7 +899,7 @@ struct ArrayOfM1
|
|||
};
|
||||
|
||||
/* An array with sorted elements. Supports binary searching. */
|
||||
template <typename Type, typename LenType=HBUINT16>
|
||||
template <typename Type, typename LenType>
|
||||
struct SortedArrayOf : ArrayOf<Type, LenType>
|
||||
{
|
||||
hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->len); }
|
||||
|
|
@ -928,11 +945,14 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
|
|||
{ return *as_array ().bsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
bool bfind (const T &x, unsigned int *i = nullptr,
|
||||
hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{ return as_array ().bfind (x, i, not_found, to_store); }
|
||||
};
|
||||
|
||||
template <typename Type> using SortedArray16Of = SortedArrayOf<Type, HBUINT16>;
|
||||
template <typename Type> using SortedArray32Of = SortedArrayOf<Type, HBUINT32>;
|
||||
|
||||
/*
|
||||
* Binary-search arrays
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ struct CFFIndex
|
|||
else
|
||||
{
|
||||
/* serialize CFFIndex header */
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
this->count = byteArray.length;
|
||||
this->offSize = offSize_;
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
|
||||
|
|
@ -214,7 +214,7 @@ struct CFFIndex
|
|||
unsigned off_size = calcOffSize (total);
|
||||
|
||||
/* serialize CFFIndex header */
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
this->count = it.len ();
|
||||
this->offSize = off_size;
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (off_size * (it.len () + 1))))
|
||||
|
|
@ -335,7 +335,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
/* serialize CFFIndex header */
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
this->count = dataArrayLen;
|
||||
this->offSize = offSize_;
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ struct Encoding
|
|||
const hb_vector_t<code_pair_t>& supp_codes)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
Encoding *dest = c->extend_min (*this);
|
||||
Encoding *dest = c->extend_min (this);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
|
||||
switch (format) {
|
||||
|
|
@ -457,7 +457,7 @@ struct Charset
|
|||
const hb_vector_t<code_pair_t>& sid_ranges)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
Charset *dest = c->extend_min (*this);
|
||||
Charset *dest = c->extend_min (this);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
dest->format = format;
|
||||
switch (format)
|
||||
|
|
@ -713,6 +713,7 @@ struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
|
|||
case OpCode_Notice:
|
||||
case OpCode_Copyright:
|
||||
case OpCode_FullName:
|
||||
case OpCode_FontName:
|
||||
case OpCode_FamilyName:
|
||||
case OpCode_Weight:
|
||||
case OpCode_PostScript:
|
||||
|
|
@ -1390,7 +1391,7 @@ struct cff1
|
|||
|
||||
public:
|
||||
FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */
|
||||
OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
|
||||
NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
|
||||
HBUINT8 offSize; /* offset size (unused?) */
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ struct CmapSubtableFormat0
|
|||
*glyph = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
for (unsigned int i = 0; i < 256; i++)
|
||||
|
|
@ -253,7 +259,7 @@ struct CmapSubtableFormat4
|
|||
if (format4_iter.len () == 0) return;
|
||||
|
||||
unsigned table_initpos = c->length ();
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
if (unlikely (!c->extend_min (this))) return;
|
||||
this->format = 4;
|
||||
|
||||
//serialize endCode[]
|
||||
|
|
@ -276,7 +282,9 @@ struct CmapSubtableFormat4
|
|||
HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
|
||||
if (unlikely (!c->check_success (idRangeOffset))) return;
|
||||
|
||||
if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return;
|
||||
if (unlikely (!c->check_assign(this->length,
|
||||
c->length () - table_initpos,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
|
||||
this->segCountX2 = segcount * 2;
|
||||
this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1;
|
||||
this->searchRange = 2 * (1u << this->entrySelector);
|
||||
|
|
@ -285,6 +293,11 @@ struct CmapSubtableFormat4
|
|||
: 0;
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
accelerator_t () {}
|
||||
|
|
@ -547,6 +560,12 @@ struct CmapSubtableTrimmed
|
|||
*glyph = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
hb_codepoint_t start = startCharCode;
|
||||
|
|
@ -606,6 +625,11 @@ struct CmapSubtableLongSegmented
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
|
||||
{
|
||||
for (unsigned int i = 0; i < this->groups.len; i++)
|
||||
|
|
@ -670,7 +694,7 @@ struct CmapSubtableLongSegmented
|
|||
HBUINT16 reserved; /* Reserved; set to 0. */
|
||||
HBUINT32 length; /* Byte length of this subtable. */
|
||||
HBUINT32 language; /* Ignore. */
|
||||
SortedArrayOf<CmapSubtableLongGroup, HBUINT32>
|
||||
SortedArray32Of<CmapSubtableLongGroup>
|
||||
groups; /* Groupings. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (16, groups);
|
||||
|
|
@ -691,7 +715,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
|
|||
{
|
||||
if (it.len () == 0) return;
|
||||
unsigned table_initpos = c->length ();
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
if (unlikely (!c->extend_min (this))) return;
|
||||
|
||||
hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
|
||||
hb_codepoint_t glyphID = 0;
|
||||
|
|
@ -784,7 +808,7 @@ struct UnicodeValueRange
|
|||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32>
|
||||
struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
|
||||
{
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
|
|
@ -850,7 +874,9 @@ struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32>
|
|||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (!c->check_assign (out->len, (c->length () - init_len) / UnicodeValueRange::static_size))) return nullptr;
|
||||
if (unlikely (!c->check_assign (out->len,
|
||||
(c->length () - init_len) / UnicodeValueRange::static_size,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))) return nullptr;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
@ -876,23 +902,21 @@ struct UVSMapping
|
|||
DEFINE_SIZE_STATIC (5);
|
||||
};
|
||||
|
||||
struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32>
|
||||
struct NonDefaultUVS : SortedArray32Of<UVSMapping>
|
||||
{
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
out->add (arrayZ[i].unicodeValue);
|
||||
for (const auto& a : as_array ())
|
||||
out->add (a.unicodeValue);
|
||||
}
|
||||
|
||||
void collect_mapping (hb_set_t *unicodes, /* OUT */
|
||||
hb_map_t *mapping /* OUT */) const
|
||||
{
|
||||
unsigned count = len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
for (const auto& a : as_array ())
|
||||
{
|
||||
hb_codepoint_t unicode = arrayZ[i].unicodeValue;
|
||||
hb_codepoint_t glyphid = arrayZ[i].glyphID;
|
||||
hb_codepoint_t unicode = a.unicodeValue;
|
||||
hb_codepoint_t glyphid = a.glyphID;
|
||||
unicodes->add (unicode);
|
||||
mapping->set (unicode, glyphid);
|
||||
}
|
||||
|
|
@ -1041,9 +1065,9 @@ struct VariationSelectorRecord
|
|||
}
|
||||
|
||||
HBUINT24 varSelector; /* Variation selector. */
|
||||
LOffsetTo<DefaultUVS>
|
||||
Offset32To<DefaultUVS>
|
||||
defaultUVS; /* Offset to Default UVS Table. May be 0. */
|
||||
LOffsetTo<NonDefaultUVS>
|
||||
Offset32To<NonDefaultUVS>
|
||||
nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (11);
|
||||
|
|
@ -1058,9 +1082,8 @@ struct CmapSubtableFormat14
|
|||
|
||||
void collect_variation_selectors (hb_set_t *out) const
|
||||
{
|
||||
unsigned int count = record.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
out->add (record.arrayZ[i].varSelector);
|
||||
for (const auto& a : record.as_array ())
|
||||
out->add (a.varSelector);
|
||||
}
|
||||
void collect_variation_unicodes (hb_codepoint_t variation_selector,
|
||||
hb_set_t *out) const
|
||||
|
|
@ -1076,7 +1099,7 @@ struct CmapSubtableFormat14
|
|||
unsigned table_initpos = c->length ();
|
||||
const char* init_tail = c->tail;
|
||||
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
if (unlikely (!c->extend_min (this))) return;
|
||||
this->format = 14;
|
||||
|
||||
auto src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (base);
|
||||
|
|
@ -1112,10 +1135,12 @@ struct CmapSubtableFormat14
|
|||
return;
|
||||
|
||||
int tail_len = init_tail - c->tail;
|
||||
c->check_assign (this->length, c->length () - table_initpos + tail_len);
|
||||
c->check_assign (this->length, c->length () - table_initpos + tail_len,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
c->check_assign (this->record.len,
|
||||
(c->length () - table_initpos - CmapSubtableFormat14::min_size) /
|
||||
VariationSelectorRecord::static_size);
|
||||
VariationSelectorRecord::static_size,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
|
||||
/* Correct the incorrect write order by reversing the order of the variation
|
||||
records array. */
|
||||
|
|
@ -1180,7 +1205,7 @@ struct CmapSubtableFormat14
|
|||
protected:
|
||||
HBUINT16 format; /* Format number is set to 14. */
|
||||
HBUINT32 length; /* Byte length of this subtable. */
|
||||
SortedArrayOf<VariationSelectorRecord, HBUINT32>
|
||||
SortedArray32Of<VariationSelectorRecord>
|
||||
record; /* Variation selector records; sorted
|
||||
* in increasing order of `varSelector'. */
|
||||
public:
|
||||
|
|
@ -1235,6 +1260,20 @@ struct CmapSubtable
|
|||
}
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 0: return u.format0 .get_language ();
|
||||
case 4: return u.format4 .get_language ();
|
||||
case 6: return u.format6 .get_language ();
|
||||
case 10: return u.format10.get_language ();
|
||||
case 12: return u.format12.get_language ();
|
||||
case 13: return u.format13.get_language ();
|
||||
case 14:
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
|
|
@ -1338,7 +1377,7 @@ struct EncodingRecord
|
|||
|
||||
HBUINT16 platformID; /* Platform ID. */
|
||||
HBUINT16 encodingID; /* Platform-specific encoding ID. */
|
||||
LOffsetTo<CmapSubtable>
|
||||
Offset32To<CmapSubtable>
|
||||
subtable; /* Byte offset from beginning of table to the subtable for this encoding. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
|
|
@ -1364,44 +1403,77 @@ struct cmap
|
|||
for (const EncodingRecord& _ : encodingrec_iter)
|
||||
{
|
||||
unsigned format = (base+_.subtable).u.format;
|
||||
if (!plan->glyphs_requested->is_empty ())
|
||||
if (format != 4 && format != 12 && format != 14) continue;
|
||||
|
||||
hb_set_t unicodes_set;
|
||||
(base+_.subtable).collect_unicodes (&unicodes_set);
|
||||
|
||||
if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
|
||||
else if (format == 12)
|
||||
{
|
||||
hb_set_t unicodes_set;
|
||||
hb_map_t cp_glyphid_map;
|
||||
(base+_.subtable).collect_mapping (&unicodes_set, &cp_glyphid_map);
|
||||
|
||||
auto table_iter =
|
||||
+ hb_zip (unicodes_set.iter(), unicodes_set.iter() | hb_map(cp_glyphid_map))
|
||||
| hb_filter (plan->_glyphset, hb_second)
|
||||
| hb_filter ([plan] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& p)
|
||||
{
|
||||
return plan->unicodes->has (p.first) ||
|
||||
plan->glyphs_requested->has (p.second);
|
||||
})
|
||||
| hb_map ([plan] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& p_org)
|
||||
{
|
||||
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (p_org.first, plan->glyph_map->get(p_org.second));
|
||||
})
|
||||
;
|
||||
|
||||
if (format == 4) c->copy (_, table_iter, 4u, base, plan, &format4objidx);
|
||||
else if (format == 12) c->copy (_, table_iter, 12u, base, plan, &format12objidx);
|
||||
else if (format == 14) c->copy (_, table_iter, 14u, base, plan, &format14objidx);
|
||||
}
|
||||
/* when --gids option is not used, we iterate input unicodes instead of
|
||||
* all codepoints in each subtable, which is more efficient */
|
||||
else
|
||||
{
|
||||
hb_set_t unicodes_set;
|
||||
(base+_.subtable).collect_unicodes (&unicodes_set);
|
||||
|
||||
if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
|
||||
else if (format == 12) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
|
||||
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
|
||||
if (_can_drop (_, unicodes_set, base, + it | hb_map (hb_first), encodingrec_iter)) continue;
|
||||
c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
|
||||
}
|
||||
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
|
||||
}
|
||||
|
||||
c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size);
|
||||
c->check_assign(this->encodingRecord.len,
|
||||
(c->length () - cmap::min_size)/EncodingRecord::static_size,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
}
|
||||
|
||||
template<typename Iterator, typename EncodingRecordIterator,
|
||||
hb_requires (hb_is_iterator (Iterator)),
|
||||
hb_requires (hb_is_iterator (EncodingRecordIterator))>
|
||||
bool _can_drop (const EncodingRecord& cmap12,
|
||||
const hb_set_t& cmap12_unicodes,
|
||||
const void* base,
|
||||
Iterator subset_unicodes,
|
||||
EncodingRecordIterator encoding_records)
|
||||
{
|
||||
for (auto cp : + subset_unicodes | hb_filter (cmap12_unicodes))
|
||||
{
|
||||
if (cp >= 0x10000) return false;
|
||||
}
|
||||
|
||||
unsigned target_platform;
|
||||
unsigned target_encoding;
|
||||
unsigned target_language = (base+cmap12.subtable).get_language ();
|
||||
|
||||
if (cmap12.platformID == 0 && cmap12.encodingID == 4)
|
||||
{
|
||||
target_platform = 0;
|
||||
target_encoding = 3;
|
||||
} else if (cmap12.platformID == 3 && cmap12.encodingID == 10) {
|
||||
target_platform = 3;
|
||||
target_encoding = 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& _ : encoding_records)
|
||||
{
|
||||
if (_.platformID != target_platform
|
||||
|| _.encodingID != target_encoding
|
||||
|| (base+_.subtable).get_language() != target_language)
|
||||
continue;
|
||||
|
||||
hb_set_t sibling_unicodes;
|
||||
(base+_.subtable).collect_unicodes (&sibling_unicodes);
|
||||
|
||||
auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes);
|
||||
auto sibling = + subset_unicodes | hb_filter (sibling_unicodes);
|
||||
for (; cmap12 && sibling; cmap12++, sibling++)
|
||||
{
|
||||
unsigned a = *cmap12;
|
||||
unsigned b = *sibling;
|
||||
if (a != b) return false;
|
||||
}
|
||||
|
||||
return !cmap12 && !sibling;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void closure_glyphs (const hb_set_t *unicodes,
|
||||
|
|
@ -1697,7 +1769,7 @@ struct cmap
|
|||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number (0). */
|
||||
SortedArrayOf<EncodingRecord>
|
||||
SortedArray16Of<EncodingRecord>
|
||||
encodingRecord; /* Encoding tables. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, encodingRecord);
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ struct IndexSubtableRecord
|
|||
|
||||
HBGlyphID firstGlyphIndex;
|
||||
HBGlyphID lastGlyphIndex;
|
||||
LOffsetTo<IndexSubtable> offsetToSubtable;
|
||||
Offset32To<IndexSubtable> offsetToSubtable;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
|
@ -672,7 +672,7 @@ struct BitmapSizeTable
|
|||
}
|
||||
|
||||
protected:
|
||||
LNNOffsetTo<IndexSubtableArray>
|
||||
NNOffset32To<IndexSubtableArray>
|
||||
indexSubtableArrayOffset;
|
||||
HBUINT32 indexTablesSize;
|
||||
HBUINT32 numberOfIndexSubtables;
|
||||
|
|
@ -697,7 +697,7 @@ struct BitmapSizeTable
|
|||
struct GlyphBitmapDataFormat17
|
||||
{
|
||||
SmallGlyphMetrics glyphMetrics;
|
||||
LArrayOf<HBUINT8> data;
|
||||
Array32Of<HBUINT8> data;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (9, data);
|
||||
};
|
||||
|
|
@ -705,14 +705,14 @@ struct GlyphBitmapDataFormat17
|
|||
struct GlyphBitmapDataFormat18
|
||||
{
|
||||
BigGlyphMetrics glyphMetrics;
|
||||
LArrayOf<HBUINT8> data;
|
||||
Array32Of<HBUINT8> data;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (12, data);
|
||||
};
|
||||
|
||||
struct GlyphBitmapDataFormat19
|
||||
{
|
||||
LArrayOf<HBUINT8> data;
|
||||
Array32Of<HBUINT8> data;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, data);
|
||||
};
|
||||
|
|
@ -738,7 +738,7 @@ struct CBLC
|
|||
cbdt_prime->length,
|
||||
HB_MEMORY_MODE_WRITABLE,
|
||||
cbdt_prime->arrayZ,
|
||||
free);
|
||||
hb_free);
|
||||
cbdt_prime->init (); // Leak arrayZ to the blob.
|
||||
bool ret = c->plan->add_table (HB_OT_TAG_CBDT, cbdt_prime_blob);
|
||||
hb_blob_destroy (cbdt_prime_blob);
|
||||
|
|
@ -798,7 +798,7 @@ struct CBLC
|
|||
|
||||
protected:
|
||||
FixedVersion<> version;
|
||||
LArrayOf<BitmapSizeTable> sizeTables;
|
||||
Array32Of<BitmapSizeTable> sizeTables;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, sizeTables);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#define HB_OT_COLOR_COLR_TABLE_HH
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
|
||||
/*
|
||||
* COLR -- Color
|
||||
|
|
@ -36,9 +37,78 @@
|
|||
*/
|
||||
#define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
|
||||
|
||||
#ifndef COLRV1_MAX_NESTING_LEVEL
|
||||
#define COLRV1_MAX_NESTING_LEVEL 100
|
||||
#endif
|
||||
|
||||
#ifndef COLRV1_ENABLE_SUBSETTING
|
||||
#define COLRV1_ENABLE_SUBSETTING 0
|
||||
#endif
|
||||
|
||||
namespace OT {
|
||||
|
||||
struct COLR;
|
||||
struct hb_colrv1_closure_context_t :
|
||||
hb_dispatch_context_t<hb_colrv1_closure_context_t>
|
||||
{
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj)
|
||||
{
|
||||
if (unlikely (nesting_level_left == 0))
|
||||
return hb_empty_t ();
|
||||
|
||||
if (paint_visited (&obj))
|
||||
return hb_empty_t ();
|
||||
|
||||
nesting_level_left--;
|
||||
obj.closurev1 (this);
|
||||
nesting_level_left++;
|
||||
return hb_empty_t ();
|
||||
}
|
||||
static return_t default_return_value () { return hb_empty_t (); }
|
||||
|
||||
bool paint_visited (const void *paint)
|
||||
{
|
||||
hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) paint - (uintptr_t) base);
|
||||
if (visited_paint.has (delta))
|
||||
return true;
|
||||
|
||||
visited_paint.add (delta);
|
||||
return false;
|
||||
}
|
||||
|
||||
const COLR* get_colr_table () const
|
||||
{ return reinterpret_cast<const COLR *> (base); }
|
||||
|
||||
void add_glyph (unsigned glyph_id)
|
||||
{ glyphs->add (glyph_id); }
|
||||
|
||||
void add_layer_indices (unsigned first_layer_index, unsigned num_of_layers)
|
||||
{ layer_indices->add_range (first_layer_index, first_layer_index + num_of_layers - 1); }
|
||||
|
||||
void add_palette_index (unsigned palette_index)
|
||||
{ palette_indices->add (palette_index); }
|
||||
|
||||
public:
|
||||
const void *base;
|
||||
hb_set_t visited_paint;
|
||||
hb_set_t *glyphs;
|
||||
hb_set_t *layer_indices;
|
||||
hb_set_t *palette_indices;
|
||||
unsigned nesting_level_left;
|
||||
|
||||
hb_colrv1_closure_context_t (const void *base_,
|
||||
hb_set_t *glyphs_,
|
||||
hb_set_t *layer_indices_,
|
||||
hb_set_t *palette_indices_,
|
||||
unsigned nesting_level_left_ = COLRV1_MAX_NESTING_LEVEL) :
|
||||
base (base_),
|
||||
glyphs (glyphs_),
|
||||
layer_indices (layer_indices_),
|
||||
palette_indices (palette_indices_),
|
||||
nesting_level_left (nesting_level_left_)
|
||||
{}
|
||||
};
|
||||
|
||||
struct LayerRecord
|
||||
{
|
||||
|
|
@ -90,6 +160,707 @@ struct BaseGlyphRecord
|
|||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Variable
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
protected:
|
||||
T value;
|
||||
VarIdx varIdx;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + T::static_size);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct NoVariable
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
T value;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (T::static_size);
|
||||
};
|
||||
|
||||
// Color structures
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct ColorIndex
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
HBUINT16 paletteIndex;
|
||||
Var<F2DOT14> alpha;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2 + Var<F2DOT14>::static_size);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct ColorStop
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (unlikely (!c->serializer->embed (stopOffset))) return_trace (false);
|
||||
return_trace (color.subset (c));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
Var<F2DOT14> stopOffset;
|
||||
ColorIndex<Var> color;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (Var<F2DOT14>::static_size + ColorIndex<Var>::static_size);
|
||||
};
|
||||
|
||||
struct Extend : HBUINT8
|
||||
{
|
||||
enum {
|
||||
EXTEND_PAD = 0,
|
||||
EXTEND_REPEAT = 1,
|
||||
EXTEND_REFLECT = 2,
|
||||
};
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (1);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct ColorLine
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
|
||||
if (!c->serializer->check_assign (out->stops.len, stops.len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)) return_trace (false);
|
||||
|
||||
for (const auto& stop : stops.iter ())
|
||||
{
|
||||
if (!stop.subset (c)) return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
stops.sanitize (c));
|
||||
}
|
||||
|
||||
Extend extend;
|
||||
Array16Of<ColorStop<Var>> stops;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY_SIZED (3, stops);
|
||||
};
|
||||
|
||||
// Composition modes
|
||||
|
||||
// Compositing modes are taken from https://www.w3.org/TR/compositing-1/
|
||||
// NOTE: a brief audit of major implementations suggests most support most
|
||||
// or all of the specified modes.
|
||||
struct CompositeMode : HBUINT8
|
||||
{
|
||||
enum {
|
||||
// Porter-Duff modes
|
||||
// https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators
|
||||
COMPOSITE_CLEAR = 0, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_clear
|
||||
COMPOSITE_SRC = 1, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_src
|
||||
COMPOSITE_DEST = 2, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dst
|
||||
COMPOSITE_SRC_OVER = 3, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcover
|
||||
COMPOSITE_DEST_OVER = 4, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstover
|
||||
COMPOSITE_SRC_IN = 5, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin
|
||||
COMPOSITE_DEST_IN = 6, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstin
|
||||
COMPOSITE_SRC_OUT = 7, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcout
|
||||
COMPOSITE_DEST_OUT = 8, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstout
|
||||
COMPOSITE_SRC_ATOP = 9, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcatop
|
||||
COMPOSITE_DEST_ATOP = 10, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstatop
|
||||
COMPOSITE_XOR = 11, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_xor
|
||||
COMPOSITE_PLUS = 12, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_plus
|
||||
|
||||
// Blend modes
|
||||
// https://www.w3.org/TR/compositing-1/#blending
|
||||
COMPOSITE_SCREEN = 13, // https://www.w3.org/TR/compositing-1/#blendingscreen
|
||||
COMPOSITE_OVERLAY = 14, // https://www.w3.org/TR/compositing-1/#blendingoverlay
|
||||
COMPOSITE_DARKEN = 15, // https://www.w3.org/TR/compositing-1/#blendingdarken
|
||||
COMPOSITE_LIGHTEN = 16, // https://www.w3.org/TR/compositing-1/#blendinglighten
|
||||
COMPOSITE_COLOR_DODGE = 17, // https://www.w3.org/TR/compositing-1/#blendingcolordodge
|
||||
COMPOSITE_COLOR_BURN = 18, // https://www.w3.org/TR/compositing-1/#blendingcolorburn
|
||||
COMPOSITE_HARD_LIGHT = 19, // https://www.w3.org/TR/compositing-1/#blendinghardlight
|
||||
COMPOSITE_SOFT_LIGHT = 20, // https://www.w3.org/TR/compositing-1/#blendingsoftlight
|
||||
COMPOSITE_DIFFERENCE = 21, // https://www.w3.org/TR/compositing-1/#blendingdifference
|
||||
COMPOSITE_EXCLUSION = 22, // https://www.w3.org/TR/compositing-1/#blendingexclusion
|
||||
COMPOSITE_MULTIPLY = 23, // https://www.w3.org/TR/compositing-1/#blendingmultiply
|
||||
|
||||
// Modes that, uniquely, do not operate on components
|
||||
// https://www.w3.org/TR/compositing-1/#blendingnonseparable
|
||||
COMPOSITE_HSL_HUE = 24, // https://www.w3.org/TR/compositing-1/#blendinghue
|
||||
COMPOSITE_HSL_SATURATION = 25, // https://www.w3.org/TR/compositing-1/#blendingsaturation
|
||||
COMPOSITE_HSL_COLOR = 26, // https://www.w3.org/TR/compositing-1/#blendingcolor
|
||||
COMPOSITE_HSL_LUMINOSITY = 27, // https://www.w3.org/TR/compositing-1/#blendingluminosity
|
||||
};
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (1);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct Affine2x3
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
Var<HBFixed> xx;
|
||||
Var<HBFixed> yx;
|
||||
Var<HBFixed> xy;
|
||||
Var<HBFixed> yy;
|
||||
Var<HBFixed> dx;
|
||||
Var<HBFixed> dy;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6 * Var<HBFixed>::static_size);
|
||||
};
|
||||
|
||||
struct PaintColrLayers
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers->get (firstLayerIndex),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 1 */
|
||||
HBUINT8 numLayers;
|
||||
HBUINT32 firstLayerIndex; /* index into COLRv1::layersV1 */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct PaintSolid
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ c->add_palette_index (color.paletteIndex); }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (unlikely (!c->serializer->embed (format))) return_trace (false);
|
||||
return_trace (color.subset (c));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 2(noVar) or 3(Var)*/
|
||||
ColorIndex<Var> color;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (1 + ColorIndex<Var>::static_size);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct PaintLinearGradient
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
for (const auto &stop : (this+colorLine).stops.iter ())
|
||||
c->add_palette_index (stop.color.paletteIndex);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 4(noVar) or 5 (Var) */
|
||||
Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintLinearGradient
|
||||
* table) to ColorLine subtable. */
|
||||
Var<FWORD> x0;
|
||||
Var<FWORD> y0;
|
||||
Var<FWORD> x1;
|
||||
Var<FWORD> y1;
|
||||
Var<FWORD> x2;
|
||||
Var<FWORD> y2;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct PaintRadialGradient
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
||||
}
|
||||
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
for (const auto &stop : (this+colorLine).stops.iter ())
|
||||
c->add_palette_index (stop.color.paletteIndex);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 6(noVar) or 7 (Var) */
|
||||
Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintRadialGradient
|
||||
* table) to ColorLine subtable. */
|
||||
Var<FWORD> x0;
|
||||
Var<FWORD> y0;
|
||||
Var<UFWORD> radius0;
|
||||
Var<FWORD> x1;
|
||||
Var<FWORD> y1;
|
||||
Var<UFWORD> radius1;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct PaintSweepGradient
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
||||
}
|
||||
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
for (const auto &stop : (this+colorLine).stops.iter ())
|
||||
c->add_palette_index (stop.color.paletteIndex);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 8(noVar) or 9 (Var) */
|
||||
Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintSweepGradient
|
||||
* table) to ColorLine subtable. */
|
||||
Var<FWORD> centerX;
|
||||
Var<FWORD> centerY;
|
||||
Var<HBFixed> startAngle;
|
||||
Var<HBFixed> endAngle;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2 * Var<FWORD>::static_size + 2 * Var<HBFixed>::static_size);
|
||||
};
|
||||
|
||||
struct Paint;
|
||||
// Paint a non-COLR glyph, filled as indicated by paint.
|
||||
struct PaintGlyph
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (! c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->paint.serialize_subset (c, paint, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && paint.sanitize (c, this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 10 */
|
||||
Offset24To<Paint> paint; /* Offset (from beginning of PaintGlyph table) to Paint subtable. */
|
||||
HBUINT16 gid;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
||||
struct PaintColrGlyph
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 11 */
|
||||
HBUINT16 gid;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (3);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct PaintTransform
|
||||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && src.sanitize (c, this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 12(noVar) or 13 (Var) */
|
||||
Offset24To<Paint> src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */
|
||||
Affine2x3<Var> transform;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + Affine2x3<Var>::static_size);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct PaintTranslate
|
||||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && src.sanitize (c, this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 14(noVar) or 15 (Var) */
|
||||
Offset24To<Paint> src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */
|
||||
Var<HBFixed> dx;
|
||||
Var<HBFixed> dy;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + Var<HBFixed>::static_size);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct PaintRotate
|
||||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && src.sanitize (c, this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 16 (noVar) or 17(Var) */
|
||||
Offset24To<Paint> src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */
|
||||
Var<HBFixed> angle;
|
||||
Var<HBFixed> centerX;
|
||||
Var<HBFixed> centerY;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 3 * Var<HBFixed>::static_size);
|
||||
};
|
||||
|
||||
template <template<typename> class Var>
|
||||
struct PaintSkew
|
||||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && src.sanitize (c, this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 18(noVar) or 19 (Var) */
|
||||
Offset24To<Paint> src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */
|
||||
Var<HBFixed> xSkewAngle;
|
||||
Var<HBFixed> ySkewAngle;
|
||||
Var<HBFixed> centerX;
|
||||
Var<HBFixed> centerY;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Var<HBFixed>::static_size);
|
||||
};
|
||||
|
||||
struct PaintComposite
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (!out->src.serialize_subset (c, src, this)) return_trace (false);
|
||||
return_trace (out->backdrop.serialize_subset (c, backdrop, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
src.sanitize (c, this) &&
|
||||
backdrop.sanitize (c, this));
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 20 */
|
||||
Offset24To<Paint> src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */
|
||||
CompositeMode mode; /* If mode is unrecognized use COMPOSITE_CLEAR */
|
||||
Offset24To<Paint> backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
struct Paint
|
||||
{
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.paintformat1, hb_forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.paintformat2, hb_forward<Ts> (ds)...));
|
||||
case 3: return_trace (c->dispatch (u.paintformat3, hb_forward<Ts> (ds)...));
|
||||
case 4: return_trace (c->dispatch (u.paintformat4, hb_forward<Ts> (ds)...));
|
||||
case 5: return_trace (c->dispatch (u.paintformat5, hb_forward<Ts> (ds)...));
|
||||
case 6: return_trace (c->dispatch (u.paintformat6, hb_forward<Ts> (ds)...));
|
||||
case 7: return_trace (c->dispatch (u.paintformat7, hb_forward<Ts> (ds)...));
|
||||
case 8: return_trace (c->dispatch (u.paintformat8, hb_forward<Ts> (ds)...));
|
||||
case 9: return_trace (c->dispatch (u.paintformat9, hb_forward<Ts> (ds)...));
|
||||
case 10: return_trace (c->dispatch (u.paintformat10, hb_forward<Ts> (ds)...));
|
||||
case 11: return_trace (c->dispatch (u.paintformat11, hb_forward<Ts> (ds)...));
|
||||
case 12: return_trace (c->dispatch (u.paintformat12, hb_forward<Ts> (ds)...));
|
||||
case 13: return_trace (c->dispatch (u.paintformat13, hb_forward<Ts> (ds)...));
|
||||
case 14: return_trace (c->dispatch (u.paintformat14, hb_forward<Ts> (ds)...));
|
||||
case 15: return_trace (c->dispatch (u.paintformat15, hb_forward<Ts> (ds)...));
|
||||
case 16: return_trace (c->dispatch (u.paintformat16, hb_forward<Ts> (ds)...));
|
||||
case 17: return_trace (c->dispatch (u.paintformat17, hb_forward<Ts> (ds)...));
|
||||
case 18: return_trace (c->dispatch (u.paintformat18, hb_forward<Ts> (ds)...));
|
||||
case 19: return_trace (c->dispatch (u.paintformat19, hb_forward<Ts> (ds)...));
|
||||
case 20: return_trace (c->dispatch (u.paintformat20, hb_forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
union {
|
||||
HBUINT8 format;
|
||||
PaintColrLayers paintformat1;
|
||||
PaintSolid<NoVariable> paintformat2;
|
||||
PaintSolid<Variable> paintformat3;
|
||||
PaintLinearGradient<NoVariable> paintformat4;
|
||||
PaintLinearGradient<Variable> paintformat5;
|
||||
PaintRadialGradient<NoVariable> paintformat6;
|
||||
PaintRadialGradient<Variable> paintformat7;
|
||||
PaintSweepGradient<NoVariable> paintformat8;
|
||||
PaintSweepGradient<Variable> paintformat9;
|
||||
PaintGlyph paintformat10;
|
||||
PaintColrGlyph paintformat11;
|
||||
PaintTransform<NoVariable> paintformat12;
|
||||
PaintTransform<Variable> paintformat13;
|
||||
PaintTranslate<NoVariable> paintformat14;
|
||||
PaintTranslate<Variable> paintformat15;
|
||||
PaintRotate<NoVariable> paintformat16;
|
||||
PaintRotate<Variable> paintformat17;
|
||||
PaintSkew<NoVariable> paintformat18;
|
||||
PaintSkew<Variable> paintformat19;
|
||||
PaintComposite paintformat20;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct BaseGlyphV1Record
|
||||
{
|
||||
int cmp (hb_codepoint_t g) const
|
||||
{ return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
|
||||
|
||||
bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
|
||||
const void* src_base, hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = s->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (!s->check_assign (out->glyphId, glyph_map->get (glyphId),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->paint.serialize_subset (c, paint, src_base));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) && paint.sanitize (c, base)));
|
||||
}
|
||||
|
||||
public:
|
||||
HBGlyphID glyphId; /* Glyph ID of reference glyph */
|
||||
Offset32To<Paint> paint; /* Offset (from beginning of BaseGlyphV1Record array) to Paint,
|
||||
* Typically PaintColrLayers */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
||||
struct BaseGlyphV1List : SortedArray32Of<BaseGlyphV1Record>
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
const hb_set_t* glyphset = c->plan->_glyphset;
|
||||
|
||||
for (const auto& _ : as_array ())
|
||||
{
|
||||
unsigned gid = _.glyphId;
|
||||
if (!glyphset->has (gid)) continue;
|
||||
|
||||
if (_.serialize (c->serializer, c->plan->glyph_map, this, c)) out->len++;
|
||||
else return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (out->len != 0);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (SortedArray32Of<BaseGlyphV1Record>::sanitize (c, this));
|
||||
}
|
||||
};
|
||||
|
||||
struct LayerV1List : Array32OfOffset32To<Paint>
|
||||
{
|
||||
const Paint& get_paint (unsigned i) const
|
||||
{ return this+(*this)[i]; }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
for (const auto& _ : + hb_enumerate (*this)
|
||||
| hb_filter (c->plan->colrv1_layers, hb_first))
|
||||
|
||||
{
|
||||
auto *o = out->serialize_append (c->serializer);
|
||||
if (unlikely (!o) || !o->serialize_subset (c, _.second, this))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (Array32OfOffset32To<Paint>::sanitize (c, this));
|
||||
}
|
||||
};
|
||||
|
||||
struct COLR
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
|
||||
|
|
@ -131,6 +902,15 @@ struct COLR
|
|||
hb_set_t *related_ids /* OUT */) const
|
||||
{ colr->closure_glyphs (glyph, related_ids); }
|
||||
|
||||
void closure_V0palette_indices (const hb_set_t *glyphs,
|
||||
hb_set_t *palettes /* OUT */) const
|
||||
{ colr->closure_V0palette_indices (glyphs, palettes); }
|
||||
|
||||
void closure_forV1 (hb_set_t *glyphset,
|
||||
hb_set_t *layer_indices,
|
||||
hb_set_t *palette_indices) const
|
||||
{ colr->closure_forV1 (glyphset, layer_indices, palette_indices); }
|
||||
|
||||
private:
|
||||
hb_blob_ptr_t<COLR> colr;
|
||||
};
|
||||
|
|
@ -147,21 +927,70 @@ struct COLR
|
|||
related_ids->add_array (&glyph_layers[0].glyphId, glyph_layers.length, LayerRecord::min_size);
|
||||
}
|
||||
|
||||
void closure_V0palette_indices (const hb_set_t *glyphs,
|
||||
hb_set_t *palettes /* OUT */) const
|
||||
{
|
||||
if (!numBaseGlyphs || !numLayers) return;
|
||||
hb_array_t<const BaseGlyphRecord> baseGlyphs = (this+baseGlyphsZ).as_array (numBaseGlyphs);
|
||||
hb_array_t<const LayerRecord> all_layers = (this+layersZ).as_array (numLayers);
|
||||
|
||||
for (const BaseGlyphRecord record : baseGlyphs)
|
||||
{
|
||||
if (!glyphs->has (record.glyphId)) continue;
|
||||
hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
|
||||
record.numLayers);
|
||||
for (const LayerRecord layer : glyph_layers)
|
||||
palettes->add (layer.colorIdx);
|
||||
}
|
||||
}
|
||||
|
||||
void closure_forV1 (hb_set_t *glyphset,
|
||||
hb_set_t *layer_indices,
|
||||
hb_set_t *palette_indices) const
|
||||
{
|
||||
if (version != 1) return;
|
||||
hb_set_t visited_glyphs;
|
||||
|
||||
hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices);
|
||||
const BaseGlyphV1List &baseglyphV1_records = this+baseGlyphsV1List;
|
||||
|
||||
for (const BaseGlyphV1Record &baseglyphV1record: baseglyphV1_records.iter ())
|
||||
{
|
||||
unsigned gid = baseglyphV1record.glyphId;
|
||||
if (!glyphset->has (gid)) continue;
|
||||
|
||||
const Paint &paint = &baseglyphV1_records+baseglyphV1record.paint;
|
||||
paint.dispatch (&c);
|
||||
}
|
||||
hb_set_union (glyphset, &visited_glyphs);
|
||||
}
|
||||
|
||||
const LayerV1List& get_layerV1List () const
|
||||
{ return (this+layersV1); }
|
||||
|
||||
const BaseGlyphV1List& get_baseglyphV1List () const
|
||||
{ return (this+baseGlyphsV1List); }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
(this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
|
||||
(this+layersZ).sanitize (c, numLayers)));
|
||||
return_trace (c->check_struct (this) &&
|
||||
(this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
|
||||
(this+layersZ).sanitize (c, numLayers) &&
|
||||
(version == 0 ||
|
||||
(COLRV1_ENABLE_SUBSETTING && version == 1 &&
|
||||
baseGlyphsV1List.sanitize (c, this) &&
|
||||
layersV1.sanitize (c, this) &&
|
||||
varStore.sanitize (c, this))));
|
||||
}
|
||||
|
||||
template<typename BaseIterator, typename LayerIterator,
|
||||
hb_requires (hb_is_iterator (BaseIterator)),
|
||||
hb_requires (hb_is_iterator (LayerIterator))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
unsigned version,
|
||||
BaseIterator base_it,
|
||||
LayerIterator layer_it)
|
||||
bool serialize_V0 (hb_serialize_context_t *c,
|
||||
unsigned version,
|
||||
BaseIterator base_it,
|
||||
LayerIterator layer_it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (base_it.len () != layer_it.len ()))
|
||||
|
|
@ -171,6 +1000,12 @@ struct COLR
|
|||
this->version = version;
|
||||
numLayers = 0;
|
||||
numBaseGlyphs = base_it.len ();
|
||||
if (base_it.len () == 0)
|
||||
{
|
||||
baseGlyphsZ = 0;
|
||||
layersZ = 0;
|
||||
return_trace (true);
|
||||
}
|
||||
baseGlyphsZ = COLR::min_size;
|
||||
layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size;
|
||||
|
||||
|
|
@ -198,6 +1033,14 @@ struct COLR
|
|||
return record;
|
||||
}
|
||||
|
||||
const BaseGlyphV1Record* get_base_glyphV1_record (hb_codepoint_t gid) const
|
||||
{
|
||||
const BaseGlyphV1Record* record = &(this+baseGlyphsV1List).bsearch ((unsigned) gid);
|
||||
if ((record && (hb_codepoint_t) record->glyphId != gid))
|
||||
record = nullptr;
|
||||
return record;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
|
@ -245,6 +1088,7 @@ struct COLR
|
|||
if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid)))
|
||||
return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
|
||||
out_layers[i].glyphId = new_gid;
|
||||
out_layers[i].colorIdx = c->plan->colr_palettes->get (layers[i].colorIdx);
|
||||
}
|
||||
|
||||
return hb_pair_t<bool, hb_vector_t<LayerRecord>> (true, out_layers);
|
||||
|
|
@ -253,23 +1097,45 @@ struct COLR
|
|||
| hb_map_retains_sorting (hb_second)
|
||||
;
|
||||
|
||||
if (unlikely (!base_it || !layer_it || base_it.len () != layer_it.len ()))
|
||||
if (version == 0 && (!base_it || !layer_it))
|
||||
return_trace (false);
|
||||
|
||||
COLR *colr_prime = c->serializer->start_embed<COLR> ();
|
||||
return_trace (colr_prime->serialize (c->serializer, version, base_it, layer_it));
|
||||
bool ret = colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it);
|
||||
|
||||
if (version == 0) return_trace (ret);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (!c->serializer->allocate_size<void> (3 * HBUINT32::static_size)) return_trace (false);
|
||||
if (!colr_prime->baseGlyphsV1List.serialize_subset (c, baseGlyphsV1List, this))
|
||||
{
|
||||
if (c->serializer->in_error ()) return_trace (false);
|
||||
//no more COLRv1 glyphs: downgrade to version 0
|
||||
c->serializer->revert (snap);
|
||||
colr_prime->version = 0;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
if (!colr_prime->layersV1.serialize_subset (c, layersV1, this)) return_trace (false);
|
||||
|
||||
colr_prime->varStore = 0;
|
||||
//TODO: subset varStore once it's implemented in fonttools
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number (starts at 0). */
|
||||
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */
|
||||
LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord>>
|
||||
NNOffset32To<SortedUnsizedArrayOf<BaseGlyphRecord>>
|
||||
baseGlyphsZ; /* Offset to Base Glyph records. */
|
||||
LNNOffsetTo<UnsizedArrayOf<LayerRecord>>
|
||||
NNOffset32To<UnsizedArrayOf<LayerRecord>>
|
||||
layersZ; /* Offset to Layer Records. */
|
||||
HBUINT16 numLayers; /* Number of Layer Records. */
|
||||
// Version-1 additions
|
||||
Offset32To<BaseGlyphV1List> baseGlyphsV1List;
|
||||
Offset32To<LayerV1List> layersV1;
|
||||
Offset32To<VariationStore> varStore;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (14);
|
||||
DEFINE_SIZE_MIN (14);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
* Copyright © 2020 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_COLR_COLRV1_CLOSURE_HH
|
||||
#define HB_OT_COLR_COLRV1_CLOSURE_HH
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
#include "hb-ot-color-colr-table.hh"
|
||||
|
||||
/*
|
||||
* COLR -- Color
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/colr
|
||||
*/
|
||||
namespace OT {
|
||||
|
||||
HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
c->add_layer_indices (firstLayerIndex, numLayers);
|
||||
const LayerV1List &paint_offset_lists = c->get_colr_table ()->get_layerV1List ();
|
||||
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
|
||||
{
|
||||
const Paint &paint = hb_addressof (paint_offset_lists) + paint_offset_lists[i];
|
||||
paint.dispatch (c);
|
||||
}
|
||||
}
|
||||
|
||||
HB_INTERNAL void PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
c->add_glyph (gid);
|
||||
(this+paint).dispatch (c);
|
||||
}
|
||||
|
||||
HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
const COLR *colr_table = c->get_colr_table ();
|
||||
const BaseGlyphV1Record* baseglyphV1_record = colr_table->get_base_glyphV1_record (gid);
|
||||
if (!baseglyphV1_record) return;
|
||||
c->add_glyph (gid);
|
||||
|
||||
const BaseGlyphV1List &baseglyphV1_list = colr_table->get_baseglyphV1List ();
|
||||
(&baseglyphV1_list+baseglyphV1_record->paint).dispatch (c);
|
||||
}
|
||||
|
||||
template <template<typename> class Var>
|
||||
HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
(this+src).dispatch (c);
|
||||
}
|
||||
|
||||
template <template<typename> class Var>
|
||||
HB_INTERNAL void PaintTranslate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
(this+src).dispatch (c);
|
||||
}
|
||||
|
||||
template <template<typename> class Var>
|
||||
HB_INTERNAL void PaintRotate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
(this+src).dispatch (c);
|
||||
}
|
||||
|
||||
template <template<typename> class Var>
|
||||
HB_INTERNAL void PaintSkew<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
(this+src).dispatch (c);
|
||||
}
|
||||
|
||||
HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
(this+src).dispatch (c);
|
||||
(this+backdrop).dispatch (c);
|
||||
}
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* HB_OT_COLR_COLRV1_CLOSURE_HH */
|
||||
|
|
@ -39,7 +39,6 @@
|
|||
*/
|
||||
#define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
|
|
@ -74,6 +73,39 @@ struct CPALV1Tail
|
|||
}
|
||||
|
||||
public:
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
unsigned palette_count,
|
||||
unsigned color_count,
|
||||
const void *base,
|
||||
const hb_map_t *color_index_map) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->allocate_size<CPALV1Tail> (static_size);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
|
||||
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
|
||||
if (colorLabelsZ)
|
||||
{
|
||||
c->push ();
|
||||
for (const auto _ : colorLabels)
|
||||
{
|
||||
if (!color_index_map->has (_)) continue;
|
||||
NameID new_color_idx;
|
||||
new_color_idx = color_index_map->get (_);
|
||||
if (!c->copy<NameID> (new_color_idx))
|
||||
{
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
c->add_link (out->colorLabelsZ, c->pop_pack ());
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c,
|
||||
const void *base,
|
||||
unsigned int palette_count,
|
||||
|
|
@ -87,15 +119,15 @@ struct CPALV1Tail
|
|||
}
|
||||
|
||||
protected:
|
||||
LNNOffsetTo<UnsizedArrayOf<HBUINT32>>
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT32>>
|
||||
paletteFlagsZ; /* Offset from the beginning of CPAL table to
|
||||
* the Palette Type Array. Set to 0 if no array
|
||||
* is provided. */
|
||||
LNNOffsetTo<UnsizedArrayOf<NameID>>
|
||||
NNOffset32To<UnsizedArrayOf<NameID>>
|
||||
paletteLabelsZ; /* Offset from the beginning of CPAL table to
|
||||
* the palette labels array. Set to 0 if no
|
||||
* array is provided. */
|
||||
LNNOffsetTo<UnsizedArrayOf<NameID>>
|
||||
NNOffset32To<UnsizedArrayOf<NameID>>
|
||||
colorLabelsZ; /* Offset from the beginning of CPAL table to
|
||||
* the color labels array. Set to 0
|
||||
* if no array is provided. */
|
||||
|
|
@ -157,6 +189,84 @@ struct CPAL
|
|||
}
|
||||
|
||||
public:
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const hb_array_t<const BGRAColor> &color_records,
|
||||
const hb_array_t<const HBUINT16> &color_record_indices,
|
||||
const hb_map_t &color_record_index_map,
|
||||
const hb_set_t &retained_color_record_indices) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
for (const auto idx : color_record_indices)
|
||||
{
|
||||
HBUINT16 new_idx;
|
||||
if (idx == 0) new_idx = 0;
|
||||
else new_idx = color_record_index_map.get (idx);
|
||||
if (!c->copy<HBUINT16> (new_idx)) return_trace (false);
|
||||
}
|
||||
|
||||
c->push ();
|
||||
for (const auto _ : retained_color_record_indices.iter ())
|
||||
{
|
||||
if (!c->copy<BGRAColor> (color_records[_]))
|
||||
{
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
c->add_link (colorRecordsZ, c->pop_pack ());
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_map_t *color_index_map = c->plan->colr_palettes;
|
||||
if (color_index_map->is_empty ()) return_trace (false);
|
||||
|
||||
hb_set_t retained_color_indices;
|
||||
for (const auto _ : color_index_map->keys ())
|
||||
{
|
||||
if (_ == 0xFFFF) continue;
|
||||
retained_color_indices.add (_);
|
||||
}
|
||||
if (retained_color_indices.is_empty ()) return_trace (false);
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
out->version = version;
|
||||
out->numColors = retained_color_indices.get_population ();
|
||||
out->numPalettes = numPalettes;
|
||||
|
||||
const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
|
||||
hb_map_t color_record_index_map;
|
||||
hb_set_t retained_color_record_indices;
|
||||
|
||||
unsigned record_count = 0;
|
||||
for (const auto first_color_record_idx : colorRecordIndices)
|
||||
{
|
||||
for (unsigned retained_color_idx : retained_color_indices.iter ())
|
||||
{
|
||||
unsigned color_record_idx = first_color_record_idx + retained_color_idx;
|
||||
if (color_record_index_map.has (color_record_idx)) continue;
|
||||
color_record_index_map.set (color_record_idx, record_count);
|
||||
retained_color_record_indices.add (color_record_idx);
|
||||
record_count++;
|
||||
}
|
||||
}
|
||||
|
||||
out->numColorRecords = record_count;
|
||||
const hb_array_t<const BGRAColor> color_records = (this+colorRecordsZ).as_array (numColorRecords);
|
||||
if (!out->serialize (c->serializer, color_records, colorRecordIndices, color_record_index_map, retained_color_record_indices))
|
||||
return_trace (false);
|
||||
|
||||
if (version == 1)
|
||||
return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map));
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -173,7 +283,7 @@ struct CPAL
|
|||
HBUINT16 numPalettes; /* Number of palettes in the table. */
|
||||
HBUINT16 numColorRecords; /* Total number of color records, combined for
|
||||
* all palettes. */
|
||||
LNNOffsetTo<UnsizedArrayOf<BGRAColor>>
|
||||
NNOffset32To<UnsizedArrayOf<BGRAColor>>
|
||||
colorRecordsZ; /* Offset from the beginning of CPAL table to
|
||||
* the first ColorRecord. */
|
||||
UnsizedArrayOf<HBUINT16>
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ struct SBIXStrike
|
|||
auto* out = c->serializer->start_embed<SBIXStrike> ();
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (unlikely (!c->serializer->extend (*out, num_output_glyphs + 1))) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false);
|
||||
out->ppem = ppem;
|
||||
out->resolution = resolution;
|
||||
HBUINT32 head;
|
||||
|
|
@ -185,7 +185,7 @@ struct SBIXStrike
|
|||
HBUINT16 resolution; /* The device pixel density (in PPI) for which this
|
||||
* strike was designed. (E.g., 96 PPI, 192 PPI.) */
|
||||
protected:
|
||||
UnsizedArrayOf<LOffsetTo<SBIXGlyph>>
|
||||
UnsizedArrayOf<Offset32To<SBIXGlyph>>
|
||||
imageOffsetsZ; /* Offset from the beginning of the strike data header
|
||||
* to bitmap data for an individual glyph ID. */
|
||||
public:
|
||||
|
|
@ -352,11 +352,11 @@ struct sbix
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
auto *out = c->serializer->start_embed<LOffsetLArrayOf<SBIXStrike>> ();
|
||||
auto *out = c->serializer->start_embed<Array32OfOffset32To<SBIXStrike>> ();
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
hb_vector_t<LOffsetTo<SBIXStrike>*> new_strikes;
|
||||
hb_vector_t<Offset32To<SBIXStrike>*> new_strikes;
|
||||
hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
|
||||
for (int i = strikes.len - 1; i >= 0; --i)
|
||||
{
|
||||
|
|
@ -400,7 +400,7 @@ struct sbix
|
|||
HBUINT16 version; /* Table version number — set to 1 */
|
||||
HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines.
|
||||
* Bits 2 to 15: reserved (set to 0). */
|
||||
LOffsetLArrayOf<SBIXStrike>
|
||||
Array32OfOffset32To<SBIXStrike>
|
||||
strikes; /* Offsets from the beginning of the 'sbix'
|
||||
* table to data for each individual bitmap strike. */
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ struct SVGDocumentIndexEntry
|
|||
* this index entry. */
|
||||
HBUINT16 endGlyphID; /* The last glyph ID in the range described by
|
||||
* this index entry. Must be >= startGlyphID. */
|
||||
LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT8>>
|
||||
svgDoc; /* Offset from the beginning of the SVG Document Index
|
||||
* to an SVG document. Must be non-zero. */
|
||||
HBUINT32 svgDocLength; /* Length of the SVG document.
|
||||
|
|
@ -107,7 +107,7 @@ struct SVG
|
|||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version (starting at 0). */
|
||||
LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry>>
|
||||
Offset32To<SortedArray16Of<SVGDocumentIndexEntry>>
|
||||
svgDocEntries; /* Offset (relative to the start of the SVG table) to the
|
||||
* SVG Documents Index. Must be non-zero. */
|
||||
/* Array of SVG Document Index Entries. */
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
/* This lists font tables that the hb_face_t will contain and lazily
|
||||
* load. Don't add a table unless it's used though. This is not
|
||||
* exactly free. */
|
||||
* exactly zero-cost. */
|
||||
|
||||
/* v--- Add new tables in the right place here. */
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ struct gasp
|
|||
|
||||
protected:
|
||||
HBUINT16 version; /* Version number (set to 1) */
|
||||
ArrayOf<GaspRange>
|
||||
Array16Of<GaspRange>
|
||||
gaspRanges; /* Number of records to follow
|
||||
* Sorted by ppem */
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ namespace OT {
|
|||
*/
|
||||
#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
|
||||
|
||||
#ifndef HB_MAX_COMPOSITE_OPERATIONS
|
||||
#define HB_MAX_COMPOSITE_OPERATIONS 100000
|
||||
#endif
|
||||
|
||||
|
||||
struct loca
|
||||
{
|
||||
|
|
@ -98,7 +102,7 @@ struct glyf
|
|||
unsigned num_offsets = padded_offsets.len () + 1;
|
||||
bool use_short_loca = max_offset < 0x1FFFF;
|
||||
unsigned entry_size = use_short_loca ? 2 : 4;
|
||||
char *loca_prime_data = (char *) calloc (entry_size, num_offsets);
|
||||
char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
|
||||
|
||||
if (unlikely (!loca_prime_data)) return false;
|
||||
|
||||
|
|
@ -115,7 +119,7 @@ struct glyf
|
|||
entry_size * num_offsets,
|
||||
HB_MEMORY_MODE_WRITABLE,
|
||||
loca_prime_data,
|
||||
free);
|
||||
hb_free);
|
||||
|
||||
bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
|
||||
&& _add_head_and_set_loca_version (plan, use_short_loca);
|
||||
|
|
@ -209,10 +213,15 @@ struct glyf
|
|||
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
|
||||
return subset_glyph;
|
||||
|
||||
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
|
||||
if (plan->drop_hints) subset_glyph.drop_hints_bytes ();
|
||||
else subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||
|
||||
if (new_gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||
subset_glyph.source_glyph = Glyph ();
|
||||
else
|
||||
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
subset_glyph.drop_hints_bytes ();
|
||||
else
|
||||
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||
return subset_glyph;
|
||||
})
|
||||
| hb_sink (glyphs)
|
||||
|
|
@ -281,6 +290,11 @@ struct glyf
|
|||
hb_codepoint_t get_glyph_index () const { return glyphIndex; }
|
||||
|
||||
void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
|
||||
void set_overlaps_flag ()
|
||||
{
|
||||
flags = (uint16_t) flags | OVERLAP_COMPOUND;
|
||||
}
|
||||
|
||||
bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
|
||||
|
||||
bool has_more () const { return flags & MORE_COMPONENTS; }
|
||||
|
|
@ -383,9 +397,12 @@ struct glyf
|
|||
{
|
||||
typedef const CompositeGlyphChain *__item_t__;
|
||||
composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
|
||||
glyph (glyph_), current (current_)
|
||||
{ if (!check_range (current)) current = nullptr; }
|
||||
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr) {}
|
||||
glyph (glyph_), current (nullptr), current_size (0)
|
||||
{
|
||||
set_next (current_);
|
||||
}
|
||||
|
||||
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
|
||||
|
||||
const CompositeGlyphChain &__item__ () const { return *current; }
|
||||
bool __more__ () const { return current; }
|
||||
|
|
@ -393,23 +410,36 @@ struct glyf
|
|||
{
|
||||
if (!current->has_more ()) { current = nullptr; return; }
|
||||
|
||||
const CompositeGlyphChain *possible = &StructAfter<CompositeGlyphChain,
|
||||
CompositeGlyphChain> (*current);
|
||||
if (!check_range (possible)) { current = nullptr; return; }
|
||||
current = possible;
|
||||
set_next (&StructAtOffset<CompositeGlyphChain> (current, current_size));
|
||||
}
|
||||
bool operator != (const composite_iter_t& o) const
|
||||
{ return glyph != o.glyph || current != o.current; }
|
||||
|
||||
bool check_range (const CompositeGlyphChain *composite) const
|
||||
|
||||
void set_next (const CompositeGlyphChain *composite)
|
||||
{
|
||||
return glyph.check_range (composite, CompositeGlyphChain::min_size)
|
||||
&& glyph.check_range (composite, composite->get_size ());
|
||||
if (!glyph.check_range (composite, CompositeGlyphChain::min_size))
|
||||
{
|
||||
current = nullptr;
|
||||
current_size = 0;
|
||||
return;
|
||||
}
|
||||
unsigned size = composite->get_size ();
|
||||
if (!glyph.check_range (composite, size))
|
||||
{
|
||||
current = nullptr;
|
||||
current_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
current = composite;
|
||||
current_size = size;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_bytes_t glyph;
|
||||
__item_t__ current;
|
||||
unsigned current_size;
|
||||
};
|
||||
|
||||
enum phantom_point_index_t
|
||||
|
|
@ -427,14 +457,14 @@ struct glyf
|
|||
{
|
||||
enum simple_glyph_flag_t
|
||||
{
|
||||
FLAG_ON_CURVE = 0x01,
|
||||
FLAG_X_SHORT = 0x02,
|
||||
FLAG_Y_SHORT = 0x04,
|
||||
FLAG_REPEAT = 0x08,
|
||||
FLAG_X_SAME = 0x10,
|
||||
FLAG_Y_SAME = 0x20,
|
||||
FLAG_RESERVED1 = 0x40,
|
||||
FLAG_RESERVED2 = 0x80
|
||||
FLAG_ON_CURVE = 0x01,
|
||||
FLAG_X_SHORT = 0x02,
|
||||
FLAG_Y_SHORT = 0x04,
|
||||
FLAG_REPEAT = 0x08,
|
||||
FLAG_X_SAME = 0x10,
|
||||
FLAG_Y_SAME = 0x20,
|
||||
FLAG_OVERLAP_SIMPLE = 0x40,
|
||||
FLAG_RESERVED2 = 0x80
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -495,8 +525,8 @@ struct glyf
|
|||
const Glyph trim_padding () const
|
||||
{
|
||||
/* based on FontTools _g_l_y_f.py::trim */
|
||||
const char *glyph = bytes.arrayZ;
|
||||
const char *glyph_end = glyph + bytes.length;
|
||||
const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
|
||||
const uint8_t *glyph_end = glyph + bytes.length;
|
||||
/* simple glyph w/contours, possibly trimmable */
|
||||
glyph += instruction_len_offset ();
|
||||
|
||||
|
|
@ -553,6 +583,17 @@ struct glyf
|
|||
dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
|
||||
}
|
||||
|
||||
void set_overlaps_flag ()
|
||||
{
|
||||
if (unlikely (!header.numberOfContours)) return;
|
||||
|
||||
unsigned flags_offset = length (instructions_length ());
|
||||
if (unlikely (length (flags_offset + 1) > bytes.length)) return;
|
||||
|
||||
HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
|
||||
first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
|
||||
}
|
||||
|
||||
static bool read_points (const HBUINT8 *&p /* IN/OUT */,
|
||||
contour_point_vector_t &points_ /* IN/OUT */,
|
||||
const hb_bytes_t &bytes,
|
||||
|
|
@ -666,6 +707,12 @@ struct glyf
|
|||
/* Chop instructions off the end */
|
||||
void drop_hints_bytes (hb_bytes_t &dest_start) const
|
||||
{ dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
|
||||
|
||||
void set_overlaps_flag ()
|
||||
{
|
||||
const_cast<CompositeGlyphChain &> (StructAfter<CompositeGlyphChain, GlyphHeader> (header))
|
||||
.set_overlaps_flag ();
|
||||
}
|
||||
};
|
||||
|
||||
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
|
||||
|
|
@ -695,6 +742,15 @@ struct glyf
|
|||
}
|
||||
}
|
||||
|
||||
void set_overlaps_flag ()
|
||||
{
|
||||
switch (type) {
|
||||
case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
|
||||
case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
|
||||
{
|
||||
switch (type) {
|
||||
|
|
@ -886,7 +942,7 @@ struct glyf
|
|||
{
|
||||
if (gid >= num_glyphs) return false;
|
||||
|
||||
/* Making this alloc free is not that easy
|
||||
/* Making this allocfree is not that easy
|
||||
https://github.com/harfbuzz/harfbuzz/issues/2095
|
||||
mostly because of gvar handling in VF fonts,
|
||||
perhaps a separate path for non-VF fonts can be considered */
|
||||
|
|
@ -1045,18 +1101,28 @@ struct glyf
|
|||
return needs_padding_removal ? glyph.trim_padding () : glyph;
|
||||
}
|
||||
|
||||
void
|
||||
add_gid_and_children (hb_codepoint_t gid, hb_set_t *gids_to_retain,
|
||||
unsigned int depth = 0) const
|
||||
unsigned
|
||||
add_gid_and_children (hb_codepoint_t gid,
|
||||
hb_set_t *gids_to_retain,
|
||||
unsigned depth = 0,
|
||||
unsigned operation_count = 0) const
|
||||
{
|
||||
if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return;
|
||||
if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
|
||||
if (unlikely (operation_count++ > HB_MAX_COMPOSITE_OPERATIONS)) return operation_count;
|
||||
/* Check if is already visited */
|
||||
if (gids_to_retain->has (gid)) return;
|
||||
if (gids_to_retain->has (gid)) return operation_count;
|
||||
|
||||
gids_to_retain->add (gid);
|
||||
|
||||
for (auto &item : glyph_for_gid (gid).get_composite_iterator ())
|
||||
add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth);
|
||||
auto it = glyph_for_gid (gid).get_composite_iterator ();
|
||||
while (it)
|
||||
{
|
||||
auto item = *(it++);
|
||||
operation_count +=
|
||||
add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
|
||||
}
|
||||
|
||||
return operation_count;
|
||||
}
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
|
|
@ -1230,7 +1296,11 @@ struct glyf
|
|||
const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
|
||||
}
|
||||
|
||||
if (plan->drop_hints) Glyph (dest_glyph).drop_hints ();
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
Glyph (dest_glyph).drop_hints ();
|
||||
|
||||
if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
|
||||
Glyph (dest_glyph).set_overlaps_flag ();
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ struct DeviceRecord
|
|||
|
||||
unsigned length = it.len ();
|
||||
|
||||
if (unlikely (!c->extend (*this, length))) return_trace (false);
|
||||
if (unlikely (!c->extend (this, length))) return_trace (false);
|
||||
|
||||
this->pixelSize = pixelSize;
|
||||
this->maxWidth =
|
||||
|
|
@ -110,7 +110,7 @@ struct hdmx
|
|||
for (const hb_item_type<Iterator>& _ : +it)
|
||||
c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
|
||||
|
||||
return_trace (c->successful);
|
||||
return_trace (c->successful ());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ struct hmtxvmtx
|
|||
|
||||
_mtx.fini ();
|
||||
|
||||
if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ()))
|
||||
if (unlikely (c->serializer->in_error ()))
|
||||
return_trace (false);
|
||||
|
||||
// Amend header num hmetrics
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ struct BaseCoordFormat3
|
|||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 3 */
|
||||
FWORD coordinate; /* X or Y value, in design units */
|
||||
OffsetTo<Device>
|
||||
Offset16To<Device>
|
||||
deviceTable; /* Offset to Device table for X or
|
||||
* Y value, from beginning of
|
||||
* BaseCoord table (may be NULL). */
|
||||
|
|
@ -173,11 +173,11 @@ struct FeatMinMaxRecord
|
|||
protected:
|
||||
Tag tag; /* 4-byte feature identification tag--must
|
||||
* match feature tag in FeatureList */
|
||||
OffsetTo<BaseCoord>
|
||||
Offset16To<BaseCoord>
|
||||
minCoord; /* Offset to BaseCoord table that defines
|
||||
* the minimum extent value, from beginning
|
||||
* of MinMax table (may be NULL) */
|
||||
OffsetTo<BaseCoord>
|
||||
Offset16To<BaseCoord>
|
||||
maxCoord; /* Offset to BaseCoord table that defines
|
||||
* the maximum extent value, from beginning
|
||||
* of MinMax table (may be NULL) */
|
||||
|
|
@ -212,15 +212,15 @@ struct MinMax
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<BaseCoord>
|
||||
Offset16To<BaseCoord>
|
||||
minCoord; /* Offset to BaseCoord table that defines
|
||||
* minimum extent value, from the beginning
|
||||
* of MinMax table (may be NULL) */
|
||||
OffsetTo<BaseCoord>
|
||||
Offset16To<BaseCoord>
|
||||
maxCoord; /* Offset to BaseCoord table that defines
|
||||
* maximum extent value, from the beginning
|
||||
* of MinMax table (may be NULL) */
|
||||
SortedArrayOf<FeatMinMaxRecord>
|
||||
SortedArray16Of<FeatMinMaxRecord>
|
||||
featMinMaxRecords;
|
||||
/* Array of FeatMinMaxRecords, in alphabetical
|
||||
* order by featureTableTag */
|
||||
|
|
@ -247,7 +247,7 @@ struct BaseValues
|
|||
Index defaultIndex; /* Index number of default baseline for this
|
||||
* script — equals index position of baseline tag
|
||||
* in baselineTags array of the BaseTagList */
|
||||
OffsetArrayOf<BaseCoord>
|
||||
Array16OfOffset16To<BaseCoord>
|
||||
baseCoords; /* Number of BaseCoord tables defined — should equal
|
||||
* baseTagCount in the BaseTagList
|
||||
*
|
||||
|
|
@ -275,7 +275,7 @@ struct BaseLangSysRecord
|
|||
|
||||
protected:
|
||||
Tag baseLangSysTag; /* 4-byte language system identification tag */
|
||||
OffsetTo<MinMax>
|
||||
Offset16To<MinMax>
|
||||
minMax; /* Offset to MinMax table, from beginning
|
||||
* of BaseScript table */
|
||||
public:
|
||||
|
|
@ -305,13 +305,13 @@ struct BaseScript
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<BaseValues>
|
||||
Offset16To<BaseValues>
|
||||
baseValues; /* Offset to BaseValues table, from beginning
|
||||
* of BaseScript table (may be NULL) */
|
||||
OffsetTo<MinMax>
|
||||
Offset16To<MinMax>
|
||||
defaultMinMax; /* Offset to MinMax table, from beginning of
|
||||
* BaseScript table (may be NULL) */
|
||||
SortedArrayOf<BaseLangSysRecord>
|
||||
SortedArray16Of<BaseLangSysRecord>
|
||||
baseLangSysRecords;
|
||||
/* Number of BaseLangSysRecords
|
||||
* defined — may be zero (0) */
|
||||
|
|
@ -339,7 +339,7 @@ struct BaseScriptRecord
|
|||
|
||||
protected:
|
||||
Tag baseScriptTag; /* 4-byte script identification tag */
|
||||
OffsetTo<BaseScript>
|
||||
Offset16To<BaseScript>
|
||||
baseScript; /* Offset to BaseScript table, from beginning
|
||||
* of BaseScriptList */
|
||||
|
||||
|
|
@ -364,7 +364,7 @@ struct BaseScriptList
|
|||
}
|
||||
|
||||
protected:
|
||||
SortedArrayOf<BaseScriptRecord>
|
||||
SortedArray16Of<BaseScriptRecord>
|
||||
baseScriptRecords;
|
||||
|
||||
public:
|
||||
|
|
@ -426,12 +426,12 @@ struct Axis
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<SortedArrayOf<Tag>>
|
||||
Offset16To<SortedArray16Of<Tag>>
|
||||
baseTagList; /* Offset to BaseTagList table, from beginning
|
||||
* of Axis table (may be NULL)
|
||||
* Array of 4-byte baseline identification tags — must
|
||||
* be in alphabetical order */
|
||||
OffsetTo<BaseScriptList>
|
||||
Offset16To<BaseScriptList>
|
||||
baseScriptList; /* Offset to BaseScriptList table, from beginning
|
||||
* of Axis table
|
||||
* Array of BaseScriptRecords, in alphabetical order
|
||||
|
|
@ -501,11 +501,11 @@ struct BASE
|
|||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version of the BASE table */
|
||||
OffsetTo<Axis>hAxis; /* Offset to horizontal Axis table, from beginning
|
||||
Offset16To<Axis>hAxis; /* Offset to horizontal Axis table, from beginning
|
||||
* of BASE table (may be NULL) */
|
||||
OffsetTo<Axis>vAxis; /* Offset to vertical Axis table, from beginning
|
||||
Offset16To<Axis>vAxis; /* Offset to vertical Axis table, from beginning
|
||||
* of BASE table (may be NULL) */
|
||||
LOffsetTo<VariationStore>
|
||||
Offset32To<VariationStore>
|
||||
varStore; /* Offset to the table of Item Variation
|
||||
* Store--from beginning of BASE
|
||||
* header (may be NULL). Introduced
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -42,7 +42,7 @@ namespace OT {
|
|||
*/
|
||||
|
||||
/* Array of contour point indices--in increasing numerical order */
|
||||
struct AttachPoint : ArrayOf<HBUINT16>
|
||||
struct AttachPoint : Array16Of<HBUINT16>
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
|
|
@ -98,8 +98,7 @@ struct AttachList
|
|||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
out->coverage.serialize (c->serializer, out)
|
||||
.serialize (c->serializer, new_coverage.iter ());
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
|
||||
|
|
@ -110,10 +109,10 @@ struct AttachList
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<Coverage>
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table -- from
|
||||
* beginning of AttachList table */
|
||||
OffsetArrayOf<AttachPoint>
|
||||
Array16OfOffset16To<AttachPoint>
|
||||
attachPoint; /* Array of AttachPoint tables
|
||||
* in Coverage Index order */
|
||||
public:
|
||||
|
|
@ -220,7 +219,7 @@ struct CaretValueFormat3
|
|||
protected:
|
||||
HBUINT16 caretValueFormat; /* Format identifier--format = 3 */
|
||||
FWORD coordinate; /* X or Y value, in design units */
|
||||
OffsetTo<Device>
|
||||
Offset16To<Device>
|
||||
deviceTable; /* Offset to Device table for X or Y
|
||||
* value--from beginning of CaretValue
|
||||
* table */
|
||||
|
|
@ -329,7 +328,7 @@ struct LigGlyph
|
|||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
for (const OffsetTo<CaretValue>& offset : carets.iter ())
|
||||
for (const Offset16To<CaretValue>& offset : carets.iter ())
|
||||
(this+offset).collect_variation_indices (c->layout_variation_indices);
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +339,7 @@ struct LigGlyph
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetArrayOf<CaretValue>
|
||||
Array16OfOffset16To<CaretValue>
|
||||
carets; /* Offset array of CaretValue tables
|
||||
* --from beginning of LigGlyph table
|
||||
* --in increasing coordinate order */
|
||||
|
|
@ -386,8 +385,7 @@ struct LigCaretList
|
|||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
out->coverage.serialize (c->serializer, out)
|
||||
.serialize (c->serializer, new_coverage.iter ());
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
|
||||
|
|
@ -408,10 +406,10 @@ struct LigCaretList
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<Coverage>
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of LigCaretList table */
|
||||
OffsetArrayOf<LigGlyph>
|
||||
Array16OfOffset16To<LigGlyph>
|
||||
ligGlyph; /* Array of LigGlyph tables
|
||||
* in Coverage Index order */
|
||||
public:
|
||||
|
|
@ -432,7 +430,7 @@ struct MarkGlyphSetsFormat1
|
|||
out->format = format;
|
||||
|
||||
bool ret = true;
|
||||
for (const LOffsetTo<Coverage>& offset : coverage.iter ())
|
||||
for (const Offset32To<Coverage>& offset : coverage.iter ())
|
||||
{
|
||||
auto *o = out->coverage.serialize_append (c->serializer);
|
||||
if (unlikely (!o))
|
||||
|
|
@ -460,7 +458,7 @@ struct MarkGlyphSetsFormat1
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
ArrayOf<LOffsetTo<Coverage>>
|
||||
Array16Of<Offset32To<Coverage>>
|
||||
coverage; /* Array of long offsets to mark set
|
||||
* coverage tables */
|
||||
public:
|
||||
|
|
@ -643,10 +641,10 @@ struct GDEF
|
|||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this);
|
||||
bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
|
||||
bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
|
||||
bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
|
||||
bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this);
|
||||
bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
|
||||
|
||||
bool subset_markglyphsetsdef = true;
|
||||
if (version.to_int () >= 0x00010002u)
|
||||
|
|
@ -687,28 +685,28 @@ struct GDEF
|
|||
protected:
|
||||
FixedVersion<>version; /* Version of the GDEF table--currently
|
||||
* 0x00010003u */
|
||||
OffsetTo<ClassDef>
|
||||
Offset16To<ClassDef>
|
||||
glyphClassDef; /* Offset to class definition table
|
||||
* for glyph type--from beginning of
|
||||
* GDEF header (may be Null) */
|
||||
OffsetTo<AttachList>
|
||||
Offset16To<AttachList>
|
||||
attachList; /* Offset to list of glyphs with
|
||||
* attachment points--from beginning
|
||||
* of GDEF header (may be Null) */
|
||||
OffsetTo<LigCaretList>
|
||||
Offset16To<LigCaretList>
|
||||
ligCaretList; /* Offset to list of positioning points
|
||||
* for ligature carets--from beginning
|
||||
* of GDEF header (may be Null) */
|
||||
OffsetTo<ClassDef>
|
||||
Offset16To<ClassDef>
|
||||
markAttachClassDef; /* Offset to class definition table for
|
||||
* mark attachment type--from beginning
|
||||
* of GDEF header (may be Null) */
|
||||
OffsetTo<MarkGlyphSets>
|
||||
Offset16To<MarkGlyphSets>
|
||||
markGlyphSetsDef; /* Offset to the table of mark set
|
||||
* definitions--from beginning of GDEF
|
||||
* header (may be NULL). Introduced
|
||||
* in version 0x00010002. */
|
||||
LOffsetTo<VariationStore>
|
||||
Offset32To<VariationStore>
|
||||
varStore; /* Offset to the table of Item Variation
|
||||
* Store--from beginning of GDEF
|
||||
* header (may be NULL). Introduced
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -46,14 +46,19 @@ struct SingleSubstFormat1
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
unsigned d = deltaGlyphID;
|
||||
|
||||
+ hb_iter (this+coverage)
|
||||
| hb_filter (*c->glyphs)
|
||||
| hb_filter (c->parent_active_glyphs ())
|
||||
| hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
|
||||
| hb_sink (c->output)
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
|
@ -95,9 +100,9 @@ struct SingleSubstFormat1
|
|||
unsigned delta)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
|
||||
c->check_assign (deltaGlyphID, delta);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
|
||||
c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +138,7 @@ struct SingleSubstFormat1
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
HBUINT16 deltaGlyphID; /* Add to original GlyphID to get
|
||||
|
|
@ -147,13 +152,17 @@ struct SingleSubstFormat2
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_filter (*c->glyphs, hb_first)
|
||||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_sink (c->output)
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
|
@ -200,9 +209,9 @@ struct SingleSubstFormat2
|
|||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
|
||||
if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
|
||||
if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
@ -233,10 +242,10 @@ struct SingleSubstFormat2
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
OffsetTo<Coverage>
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
ArrayOf<HBGlyphID>
|
||||
Array16Of<HBGlyphID>
|
||||
substitute; /* Array of substitute
|
||||
* GlyphIDs--ordered by Coverage Index */
|
||||
public:
|
||||
|
|
@ -334,9 +343,14 @@ struct Sequence
|
|||
|
||||
unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
|
||||
unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
|
||||
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
/* If is attached to a ligature, don't disturb that.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/3069 */
|
||||
if (!lig_id)
|
||||
_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
|
||||
c->output_glyph_for_component (substitute.arrayZ[i], klass);
|
||||
}
|
||||
c->buffer->skip_glyph ();
|
||||
|
|
@ -377,7 +391,7 @@ struct Sequence
|
|||
}
|
||||
|
||||
protected:
|
||||
ArrayOf<HBGlyphID>
|
||||
Array16Of<HBGlyphID>
|
||||
substitute; /* String of GlyphIDs to substitute */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, substitute);
|
||||
|
|
@ -388,10 +402,13 @@ struct MultipleSubstFormat1
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, sequence)
|
||||
| hb_filter (*c->glyphs, hb_first)
|
||||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const Sequence &_) { _.closure (c); })
|
||||
|
|
@ -431,17 +448,17 @@ struct MultipleSubstFormat1
|
|||
hb_array_t<const HBGlyphID> substitute_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < glyphs.length; i++)
|
||||
{
|
||||
unsigned int substitute_len = substitute_len_list[i];
|
||||
if (unlikely (!sequence[i].serialize (c, this)
|
||||
.serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
|
||||
if (unlikely (!sequence[i]
|
||||
.serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
|
||||
return_trace (false);
|
||||
substitute_glyphs_list += substitute_len;
|
||||
}
|
||||
return_trace (coverage.serialize (c, this).serialize (c, glyphs));
|
||||
return_trace (coverage.serialize_serialize (c, glyphs));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
|
|
@ -462,8 +479,7 @@ struct MultipleSubstFormat1
|
|||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
out->coverage.serialize (c->serializer, out)
|
||||
.serialize (c->serializer, new_coverage.iter ());
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
|
||||
|
|
@ -475,10 +491,10 @@ struct MultipleSubstFormat1
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
OffsetArrayOf<Sequence>
|
||||
Array16OfOffset16To<Sequence>
|
||||
sequence; /* Array of Sequence tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
|
|
@ -547,7 +563,12 @@ struct AlternateSet
|
|||
|
||||
/* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
|
||||
if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
|
||||
{
|
||||
/* Maybe we can do better than unsafe-to-break all; but since we are
|
||||
* changing random state, it would be hard to track that. Good 'nough. */
|
||||
c->buffer->unsafe_to_break_all ();
|
||||
alt_index = c->random_number () % count + 1;
|
||||
}
|
||||
|
||||
if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
|
||||
|
||||
|
|
@ -603,7 +624,7 @@ struct AlternateSet
|
|||
}
|
||||
|
||||
protected:
|
||||
ArrayOf<HBGlyphID>
|
||||
Array16Of<HBGlyphID>
|
||||
alternates; /* Array of alternate GlyphIDs--in
|
||||
* arbitrary order */
|
||||
public:
|
||||
|
|
@ -615,14 +636,18 @@ struct AlternateSubstFormat1
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, alternateSet)
|
||||
| hb_filter (c->glyphs, hb_first)
|
||||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
|
@ -666,17 +691,17 @@ struct AlternateSubstFormat1
|
|||
hb_array_t<const HBGlyphID> alternate_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < glyphs.length; i++)
|
||||
{
|
||||
unsigned int alternate_len = alternate_len_list[i];
|
||||
if (unlikely (!alternateSet[i].serialize (c, this)
|
||||
.serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
|
||||
if (unlikely (!alternateSet[i]
|
||||
.serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
|
||||
return_trace (false);
|
||||
alternate_glyphs_list += alternate_len;
|
||||
}
|
||||
return_trace (coverage.serialize (c, this).serialize (c, glyphs));
|
||||
return_trace (coverage.serialize_serialize (c, glyphs));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
|
|
@ -697,8 +722,7 @@ struct AlternateSubstFormat1
|
|||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
out->coverage.serialize (c->serializer, out)
|
||||
.serialize (c->serializer, new_coverage.iter ());
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
|
||||
|
|
@ -710,10 +734,10 @@ struct AlternateSubstFormat1
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
OffsetArrayOf<AlternateSet>
|
||||
Array16OfOffset16To<AlternateSet>
|
||||
alternateSet; /* Array of AlternateSet tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
|
|
@ -831,7 +855,7 @@ struct Ligature
|
|||
Iterator components /* Starting from second */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
ligGlyph = ligature;
|
||||
if (unlikely (!component.serialize (c, components))) return_trace (false);
|
||||
return_trace (true);
|
||||
|
|
@ -930,15 +954,14 @@ struct LigatureSet
|
|||
hb_array_t<const HBGlyphID> &component_list /* Starting from second for each ligature */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < ligatures.length; i++)
|
||||
{
|
||||
unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
|
||||
if (unlikely (!ligature[i].serialize (c, this)
|
||||
.serialize (c,
|
||||
ligatures[i],
|
||||
component_list.sub_array (0, component_count))))
|
||||
if (unlikely (!ligature[i].serialize_serialize (c,
|
||||
ligatures[i],
|
||||
component_list.sub_array (0, component_count))))
|
||||
return_trace (false);
|
||||
component_list += component_count;
|
||||
}
|
||||
|
|
@ -965,7 +988,7 @@ struct LigatureSet
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetArrayOf<Ligature>
|
||||
Array16OfOffset16To<Ligature>
|
||||
ligature; /* Array LigatureSet tables
|
||||
* ordered by preference */
|
||||
public:
|
||||
|
|
@ -980,20 +1003,24 @@ struct LigatureSubstFormat1
|
|||
+ hb_zip (this+coverage, ligatureSet)
|
||||
| hb_filter (*glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map ([this, glyphs] (const OffsetTo<LigatureSet> &_)
|
||||
| hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
|
||||
{ return (this+_).intersects (glyphs); })
|
||||
| hb_any
|
||||
;
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, ligatureSet)
|
||||
| hb_filter (*c->glyphs, hb_first)
|
||||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
|
@ -1039,20 +1066,20 @@ struct LigatureSubstFormat1
|
|||
hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < first_glyphs.length; i++)
|
||||
{
|
||||
unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
|
||||
if (unlikely (!ligatureSet[i].serialize (c, this)
|
||||
.serialize (c,
|
||||
ligatures_list.sub_array (0, ligature_count),
|
||||
component_count_list.sub_array (0, ligature_count),
|
||||
component_list))) return_trace (false);
|
||||
if (unlikely (!ligatureSet[i]
|
||||
.serialize_serialize (c,
|
||||
ligatures_list.sub_array (0, ligature_count),
|
||||
component_count_list.sub_array (0, ligature_count),
|
||||
component_list))) return_trace (false);
|
||||
ligatures_list += ligature_count;
|
||||
component_count_list += ligature_count;
|
||||
}
|
||||
return_trace (coverage.serialize (c, this).serialize (c, first_glyphs));
|
||||
return_trace (coverage.serialize_serialize (c, first_glyphs));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
|
|
@ -1073,8 +1100,7 @@ struct LigatureSubstFormat1
|
|||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
out->coverage.serialize (c->serializer, out)
|
||||
.serialize (c->serializer, new_coverage.iter ());
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
|
||||
|
|
@ -1086,10 +1112,10 @@ struct LigatureSubstFormat1
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
OffsetArrayOf<LigatureSet>
|
||||
Array16OfOffset16To<LigatureSet>
|
||||
ligatureSet; /* Array LigatureSet tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
|
|
@ -1157,7 +1183,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
if (!(this+coverage).intersects (glyphs))
|
||||
return false;
|
||||
|
||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
|
||||
unsigned int count;
|
||||
|
||||
|
|
@ -1174,15 +1200,18 @@ struct ReverseChainSingleSubstFormat1
|
|||
return true;
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
if (!intersects (c->glyphs)) return;
|
||||
|
||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
|
||||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
|
||||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_filter (*c->glyphs, hb_first)
|
||||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_sink (c->output)
|
||||
;
|
||||
|
|
@ -1200,12 +1229,12 @@ struct ReverseChainSingleSubstFormat1
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
|
||||
|
||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
count = lookahead.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
|
||||
|
||||
const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
count = substitute.len;
|
||||
c->output->add_array (substitute.arrayZ, substitute.len);
|
||||
}
|
||||
|
|
@ -1224,8 +1253,8 @@ struct ReverseChainSingleSubstFormat1
|
|||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
|
||||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
|
||||
if (unlikely (index >= substitute.len)) return_trace (false);
|
||||
|
||||
|
|
@ -1250,11 +1279,80 @@ struct ReverseChainSingleSubstFormat1
|
|||
return_trace (false);
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
|
||||
|
||||
if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
|
||||
return_trace (false);
|
||||
|
||||
for (auto& offset : it) {
|
||||
auto *o = out->serialize_append (c->serializer);
|
||||
if (unlikely (!o) || !o->serialize_subset (c, offset, this))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
|
||||
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
|
||||
hb_requires (hb_is_iterator (BacktrackIterator)),
|
||||
hb_requires (hb_is_iterator (LookaheadIterator))>
|
||||
bool serialize (hb_subset_context_t *c,
|
||||
Iterator coverage_subst_iter,
|
||||
BacktrackIterator backtrack_iter,
|
||||
LookaheadIterator lookahead_iter) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->check_success (out))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
|
||||
|
||||
if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
|
||||
if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
|
||||
|
||||
auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID>> ();
|
||||
auto substitutes =
|
||||
+ coverage_subst_iter
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
auto glyphs =
|
||||
+ coverage_subst_iter
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs)))
|
||||
return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
// TODO(subset)
|
||||
return_trace (false);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (glyphset, hb_second)
|
||||
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t
|
||||
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
|
||||
;
|
||||
|
||||
return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
|
@ -1262,27 +1360,27 @@ struct ReverseChainSingleSubstFormat1
|
|||
TRACE_SANITIZE (this);
|
||||
if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
|
||||
return_trace (false);
|
||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
if (!lookahead.sanitize (c, this))
|
||||
return_trace (false);
|
||||
const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
return_trace (substitute.sanitize (c));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of table */
|
||||
OffsetArrayOf<Coverage>
|
||||
Array16OfOffset16To<Coverage>
|
||||
backtrack; /* Array of coverage tables
|
||||
* in backtracking sequence, in glyph
|
||||
* sequence order */
|
||||
OffsetArrayOf<Coverage>
|
||||
Array16OfOffset16To<Coverage>
|
||||
lookaheadX; /* Array of coverage tables
|
||||
* in lookahead sequence, in glyph
|
||||
* sequence order */
|
||||
ArrayOf<HBGlyphID>
|
||||
Array16Of<HBGlyphID>
|
||||
substituteX; /* Array of substitute
|
||||
* GlyphIDs--ordered by Coverage Index */
|
||||
public:
|
||||
|
|
@ -1388,6 +1486,12 @@ struct SubstLookup : Lookup
|
|||
return lookup_type_is_reverse (type);
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{
|
||||
hb_have_non_1to1_context_t c;
|
||||
return dispatch (&c);
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
|
@ -1455,10 +1559,6 @@ struct SubstLookup : Lookup
|
|||
|
||||
static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
|
||||
|
||||
SubTable& serialize_subtable (hb_serialize_context_t *c,
|
||||
unsigned int i)
|
||||
{ return get_subtables<SubTable> ()[i].serialize (c, this); }
|
||||
|
||||
bool serialize_single (hb_serialize_context_t *c,
|
||||
uint32_t lookup_props,
|
||||
hb_sorted_array_t<const HBGlyphID> glyphs,
|
||||
|
|
@ -1466,8 +1566,13 @@ struct SubstLookup : Lookup
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
|
||||
return_trace (serialize_subtable (c, 0).u.single.
|
||||
serialize (c, hb_zip (glyphs, substitutes)));
|
||||
if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
|
||||
{
|
||||
c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
|
||||
return_trace (true);
|
||||
}
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
bool serialize_multiple (hb_serialize_context_t *c,
|
||||
|
|
@ -1478,11 +1583,17 @@ struct SubstLookup : Lookup
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
|
||||
return_trace (serialize_subtable (c, 0).u.multiple.
|
||||
serialize (c,
|
||||
glyphs,
|
||||
substitute_len_list,
|
||||
substitute_glyphs_list));
|
||||
if (c->push<SubTable> ()->u.multiple.
|
||||
serialize (c,
|
||||
glyphs,
|
||||
substitute_len_list,
|
||||
substitute_glyphs_list))
|
||||
{
|
||||
c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
|
||||
return_trace (true);
|
||||
}
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
bool serialize_alternate (hb_serialize_context_t *c,
|
||||
|
|
@ -1493,11 +1604,18 @@ struct SubstLookup : Lookup
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
|
||||
return_trace (serialize_subtable (c, 0).u.alternate.
|
||||
serialize (c,
|
||||
glyphs,
|
||||
alternate_len_list,
|
||||
alternate_glyphs_list));
|
||||
|
||||
if (c->push<SubTable> ()->u.alternate.
|
||||
serialize (c,
|
||||
glyphs,
|
||||
alternate_len_list,
|
||||
alternate_glyphs_list))
|
||||
{
|
||||
c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
|
||||
return_trace (true);
|
||||
}
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
bool serialize_ligature (hb_serialize_context_t *c,
|
||||
|
|
@ -1510,24 +1628,32 @@ struct SubstLookup : Lookup
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
|
||||
return_trace (serialize_subtable (c, 0).u.ligature.
|
||||
serialize (c,
|
||||
first_glyphs,
|
||||
ligature_per_first_glyph_count_list,
|
||||
ligatures_list,
|
||||
component_count_list,
|
||||
component_list));
|
||||
if (c->push<SubTable> ()->u.ligature.
|
||||
serialize (c,
|
||||
first_glyphs,
|
||||
ligature_per_first_glyph_count_list,
|
||||
ligatures_list,
|
||||
component_count_list,
|
||||
component_list))
|
||||
{
|
||||
c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
|
||||
return_trace (true);
|
||||
}
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
template <typename context_t>
|
||||
static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
|
||||
|
||||
static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
|
||||
static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
|
||||
|
||||
static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
|
||||
{
|
||||
if (!c->should_visit_lookup (lookup_index))
|
||||
return hb_empty_t ();
|
||||
|
||||
hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
|
||||
hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
|
||||
|
||||
/* While in theory we should flush here, it will cause timeouts because a recursive
|
||||
* lookup can keep growing the glyph set. Skip, and outer loop will retry up to
|
||||
|
|
@ -1564,7 +1690,7 @@ struct GSUB : GSUBGPOS
|
|||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_features);
|
||||
hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
|
||||
return GSUBGPOS::subset<SubstLookup> (&l);
|
||||
}
|
||||
|
||||
|
|
@ -1600,6 +1726,14 @@ template <typename context_t>
|
|||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
/*static*/ typename hb_closure_context_t::return_t SubstLookup::closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
|
||||
{
|
||||
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
|
||||
if (l.may_have_non_1to1 ())
|
||||
hb_set_add_range (covered_seq_indices, seq_index, end_index);
|
||||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
/*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
|
||||
{
|
||||
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -45,7 +45,7 @@ typedef IndexArray JstfModList;
|
|||
* JstfMax -- Justification Maximum Table
|
||||
*/
|
||||
|
||||
typedef OffsetListOf<PosLookup> JstfMax;
|
||||
typedef List16OfOffset16To<PosLookup> JstfMax;
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -71,43 +71,43 @@ struct JstfPriority
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<JstfModList>
|
||||
Offset16To<JstfModList>
|
||||
shrinkageEnableGSUB; /* Offset to Shrinkage Enable GSUB
|
||||
* JstfModList table--from beginning of
|
||||
* JstfPriority table--may be NULL */
|
||||
OffsetTo<JstfModList>
|
||||
Offset16To<JstfModList>
|
||||
shrinkageDisableGSUB; /* Offset to Shrinkage Disable GSUB
|
||||
* JstfModList table--from beginning of
|
||||
* JstfPriority table--may be NULL */
|
||||
OffsetTo<JstfModList>
|
||||
Offset16To<JstfModList>
|
||||
shrinkageEnableGPOS; /* Offset to Shrinkage Enable GPOS
|
||||
* JstfModList table--from beginning of
|
||||
* JstfPriority table--may be NULL */
|
||||
OffsetTo<JstfModList>
|
||||
Offset16To<JstfModList>
|
||||
shrinkageDisableGPOS; /* Offset to Shrinkage Disable GPOS
|
||||
* JstfModList table--from beginning of
|
||||
* JstfPriority table--may be NULL */
|
||||
OffsetTo<JstfMax>
|
||||
Offset16To<JstfMax>
|
||||
shrinkageJstfMax; /* Offset to Shrinkage JstfMax table--
|
||||
* from beginning of JstfPriority table
|
||||
* --may be NULL */
|
||||
OffsetTo<JstfModList>
|
||||
Offset16To<JstfModList>
|
||||
extensionEnableGSUB; /* Offset to Extension Enable GSUB
|
||||
* JstfModList table--from beginning of
|
||||
* JstfPriority table--may be NULL */
|
||||
OffsetTo<JstfModList>
|
||||
Offset16To<JstfModList>
|
||||
extensionDisableGSUB; /* Offset to Extension Disable GSUB
|
||||
* JstfModList table--from beginning of
|
||||
* JstfPriority table--may be NULL */
|
||||
OffsetTo<JstfModList>
|
||||
Offset16To<JstfModList>
|
||||
extensionEnableGPOS; /* Offset to Extension Enable GPOS
|
||||
* JstfModList table--from beginning of
|
||||
* JstfPriority table--may be NULL */
|
||||
OffsetTo<JstfModList>
|
||||
Offset16To<JstfModList>
|
||||
extensionDisableGPOS; /* Offset to Extension Disable GPOS
|
||||
* JstfModList table--from beginning of
|
||||
* JstfPriority table--may be NULL */
|
||||
OffsetTo<JstfMax>
|
||||
Offset16To<JstfMax>
|
||||
extensionJstfMax; /* Offset to Extension JstfMax table--
|
||||
* from beginning of JstfPriority table
|
||||
* --may be NULL */
|
||||
|
|
@ -121,13 +121,13 @@ struct JstfPriority
|
|||
* JstfLangSys -- Justification Language System Table
|
||||
*/
|
||||
|
||||
struct JstfLangSys : OffsetListOf<JstfPriority>
|
||||
struct JstfLangSys : List16OfOffset16To<JstfPriority>
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c,
|
||||
const Record_sanitize_closure_t * = nullptr) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (OffsetListOf<JstfPriority>::sanitize (c));
|
||||
return_trace (List16OfOffset16To<JstfPriority>::sanitize (c));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ struct JstfLangSys : OffsetListOf<JstfPriority>
|
|||
* ExtenderGlyphs -- Extender Glyph Table
|
||||
*/
|
||||
|
||||
typedef SortedArrayOf<HBGlyphID> ExtenderGlyphs;
|
||||
typedef SortedArray16Of<HBGlyphID> ExtenderGlyphs;
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -174,10 +174,10 @@ struct JstfScript
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<ExtenderGlyphs>
|
||||
Offset16To<ExtenderGlyphs>
|
||||
extenderGlyphs; /* Offset to ExtenderGlyph table--from beginning
|
||||
* of JstfScript table-may be NULL */
|
||||
OffsetTo<JstfLangSys>
|
||||
Offset16To<JstfLangSys>
|
||||
defaultLangSys; /* Offset to DefaultJstfLangSys table--from
|
||||
* beginning of JstfScript table--may be Null */
|
||||
RecordArrayOf<JstfLangSys>
|
||||
|
|
|
|||
|
|
@ -131,7 +131,9 @@ hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
|
|||
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
|
||||
|
||||
if (!buffer->message (font, "start table kern")) return;
|
||||
kern.apply (&c);
|
||||
(void) buffer->message (font, "end table kern");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -144,7 +146,7 @@ bool
|
|||
OT::GDEF::is_blocklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const
|
||||
{
|
||||
#ifdef HB_NO_OT_LAYOUT_BLACKLIST
|
||||
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
|
||||
return false;
|
||||
#endif
|
||||
/* The ugly business of blocklisting individual fonts' tables happen here!
|
||||
|
|
@ -331,6 +333,8 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face,
|
|||
*
|
||||
* Useful if the client program wishes to cache the list.
|
||||
*
|
||||
* Return value: Total number of attachment points for @glyph.
|
||||
*
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_layout_get_attach_points (hb_face_t *face,
|
||||
|
|
@ -357,6 +361,8 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
|
|||
* Fetches a list of the caret positions defined for a ligature glyph in the GDEF
|
||||
* table of the font. The list returned will begin at the offset provided.
|
||||
*
|
||||
* Return value: Total number of ligature caret positions for @glyph.
|
||||
*
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_layout_get_ligature_carets (hb_font_t *font,
|
||||
|
|
@ -379,7 +385,7 @@ bool
|
|||
OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
|
||||
hb_face_t *face) const
|
||||
{
|
||||
#ifdef HB_NO_OT_LAYOUT_BLACKLIST
|
||||
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
|
||||
return false;
|
||||
#endif
|
||||
return false;
|
||||
|
|
@ -389,7 +395,7 @@ bool
|
|||
OT::GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
|
||||
hb_face_t *face HB_UNUSED) const
|
||||
{
|
||||
#ifdef HB_NO_OT_LAYOUT_BLACKLIST
|
||||
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
|
||||
return false;
|
||||
#endif
|
||||
return false;
|
||||
|
|
@ -419,6 +425,8 @@ get_gsubgpos_table (hb_face_t *face,
|
|||
* Fetches a list of all scripts enumerated in the specified face's GSUB table
|
||||
* or GPOS table. The list returned will begin at the offset provided.
|
||||
*
|
||||
* Return value: Total number of script tags.
|
||||
*
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_layout_table_get_script_tags (hb_face_t *face,
|
||||
|
|
@ -585,6 +593,8 @@ hb_ot_layout_table_select_script (hb_face_t *face,
|
|||
*
|
||||
* Fetches a list of all feature tags in the given face's GSUB or GPOS table.
|
||||
*
|
||||
* Return value: Total number of feature tags.
|
||||
*
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_layout_table_get_feature_tags (hb_face_t *face,
|
||||
|
|
@ -647,6 +657,8 @@ hb_ot_layout_table_find_feature (hb_face_t *face,
|
|||
* Fetches a list of language tags in the given face's GSUB or GPOS table, underneath
|
||||
* the specified script index. The list returned will begin at the offset provided.
|
||||
*
|
||||
* Return value: Total number of language tags.
|
||||
*
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_layout_script_get_language_tags (hb_face_t *face,
|
||||
|
|
@ -818,6 +830,8 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face,
|
|||
* Fetches a list of all features in the specified face's GSUB table
|
||||
* or GPOS table, underneath the specified script and language. The list
|
||||
* returned will begin at the offset provided.
|
||||
*
|
||||
* Return value: Total number of features.
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
|
||||
|
|
@ -850,6 +864,7 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
|
|||
* or GPOS table, underneath the specified script and language. The list
|
||||
* returned will begin at the offset provided.
|
||||
*
|
||||
* Return value: Total number of feature tags.
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_layout_language_get_feature_tags (hb_face_t *face,
|
||||
|
|
@ -932,6 +947,8 @@ hb_ot_layout_language_find_feature (hb_face_t *face,
|
|||
* the specified face's GSUB table or GPOS table. The list returned will
|
||||
* begin at the offset provided.
|
||||
*
|
||||
* Return value: Total number of lookups.
|
||||
*
|
||||
* Since: 0.9.7
|
||||
**/
|
||||
unsigned int
|
||||
|
|
@ -960,6 +977,8 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face,
|
|||
* Fetches the total number of lookups enumerated in the specified
|
||||
* face's GSUB table or GPOS table.
|
||||
*
|
||||
* Return value: Total number of lookups.
|
||||
*
|
||||
* Since: 0.9.22
|
||||
**/
|
||||
unsigned int
|
||||
|
|
@ -974,10 +993,46 @@ struct hb_collect_features_context_t
|
|||
{
|
||||
hb_collect_features_context_t (hb_face_t *face,
|
||||
hb_tag_t table_tag,
|
||||
hb_set_t *feature_indexes_)
|
||||
hb_set_t *feature_indices_,
|
||||
const hb_tag_t *features)
|
||||
|
||||
: g (get_gsubgpos_table (face, table_tag)),
|
||||
feature_indexes (feature_indexes_),
|
||||
script_count (0),langsys_count (0), feature_index_count (0) {}
|
||||
feature_indices (feature_indices_),
|
||||
has_feature_filter (false),
|
||||
script_count (0),langsys_count (0), feature_index_count (0)
|
||||
{
|
||||
compute_feature_filter (features);
|
||||
}
|
||||
|
||||
void compute_feature_filter (const hb_tag_t *features)
|
||||
{
|
||||
if (features == nullptr)
|
||||
{
|
||||
has_feature_filter = false;
|
||||
return;
|
||||
}
|
||||
|
||||
has_feature_filter = true;
|
||||
for (; *features; features++)
|
||||
{
|
||||
hb_tag_t tag = *features;
|
||||
unsigned index;
|
||||
g.find_feature_index (tag, &index);
|
||||
if (index == OT::Index::NOT_FOUND_INDEX) continue;
|
||||
|
||||
feature_indices_filter.add(index);
|
||||
for (int i = (int) index - 1; i >= 0; i--)
|
||||
{
|
||||
if (g.get_feature_tag (i) != tag) break;
|
||||
feature_indices_filter.add(i);
|
||||
}
|
||||
for (unsigned i = index + 1; i < g.get_feature_count (); i++)
|
||||
{
|
||||
if (g.get_feature_tag (i) != tag) break;
|
||||
feature_indices_filter.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool visited (const OT::Script &s)
|
||||
{
|
||||
|
|
@ -1026,7 +1081,9 @@ struct hb_collect_features_context_t
|
|||
|
||||
public:
|
||||
const OT::GSUBGPOS &g;
|
||||
hb_set_t *feature_indexes;
|
||||
hb_set_t *feature_indices;
|
||||
hb_set_t feature_indices_filter;
|
||||
bool has_feature_filter;
|
||||
|
||||
private:
|
||||
hb_set_t visited_script;
|
||||
|
|
@ -1038,37 +1095,31 @@ struct hb_collect_features_context_t
|
|||
|
||||
static void
|
||||
langsys_collect_features (hb_collect_features_context_t *c,
|
||||
const OT::LangSys &l,
|
||||
const hb_tag_t *features)
|
||||
const OT::LangSys &l)
|
||||
{
|
||||
if (c->visited (l)) return;
|
||||
|
||||
if (!features)
|
||||
if (!c->has_feature_filter)
|
||||
{
|
||||
/* All features. */
|
||||
if (l.has_required_feature () && !c->visited_feature_indices (1))
|
||||
c->feature_indexes->add (l.get_required_feature_index ());
|
||||
c->feature_indices->add (l.get_required_feature_index ());
|
||||
|
||||
// TODO(garretrieger): filter out indices >= feature count?
|
||||
if (!c->visited_feature_indices (l.featureIndex.len))
|
||||
l.add_feature_indexes_to (c->feature_indexes);
|
||||
l.add_feature_indexes_to (c->feature_indices);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ugh. Any faster way? */
|
||||
for (; *features; features++)
|
||||
if (c->feature_indices_filter.is_empty()) return;
|
||||
unsigned int num_features = l.get_feature_count ();
|
||||
for (unsigned int i = 0; i < num_features; i++)
|
||||
{
|
||||
hb_tag_t feature_tag = *features;
|
||||
unsigned int num_features = l.get_feature_count ();
|
||||
for (unsigned int i = 0; i < num_features; i++)
|
||||
{
|
||||
unsigned int feature_index = l.get_feature_index (i);
|
||||
unsigned int feature_index = l.get_feature_index (i);
|
||||
if (!c->feature_indices_filter.has (feature_index)) continue;
|
||||
|
||||
if (feature_tag == c->g.get_feature_tag (feature_index))
|
||||
{
|
||||
c->feature_indexes->add (feature_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->feature_indices->add (feature_index);
|
||||
c->feature_indices_filter.del (feature_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1076,8 +1127,7 @@ langsys_collect_features (hb_collect_features_context_t *c,
|
|||
static void
|
||||
script_collect_features (hb_collect_features_context_t *c,
|
||||
const OT::Script &s,
|
||||
const hb_tag_t *languages,
|
||||
const hb_tag_t *features)
|
||||
const hb_tag_t *languages)
|
||||
{
|
||||
if (c->visited (s)) return;
|
||||
|
||||
|
|
@ -1086,14 +1136,13 @@ script_collect_features (hb_collect_features_context_t *c,
|
|||
/* All languages. */
|
||||
if (s.has_default_lang_sys ())
|
||||
langsys_collect_features (c,
|
||||
s.get_default_lang_sys (),
|
||||
features);
|
||||
s.get_default_lang_sys ());
|
||||
|
||||
|
||||
unsigned int count = s.get_lang_sys_count ();
|
||||
for (unsigned int language_index = 0; language_index < count; language_index++)
|
||||
langsys_collect_features (c,
|
||||
s.get_lang_sys (language_index),
|
||||
features);
|
||||
s.get_lang_sys (language_index));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1102,8 +1151,8 @@ script_collect_features (hb_collect_features_context_t *c,
|
|||
unsigned int language_index;
|
||||
if (s.find_lang_sys_index (*languages, &language_index))
|
||||
langsys_collect_features (c,
|
||||
s.get_lang_sys (language_index),
|
||||
features);
|
||||
s.get_lang_sys (language_index));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1134,7 +1183,7 @@ hb_ot_layout_collect_features (hb_face_t *face,
|
|||
const hb_tag_t *features,
|
||||
hb_set_t *feature_indexes /* OUT */)
|
||||
{
|
||||
hb_collect_features_context_t c (face, table_tag, feature_indexes);
|
||||
hb_collect_features_context_t c (face, table_tag, feature_indexes, features);
|
||||
if (!scripts)
|
||||
{
|
||||
/* All scripts. */
|
||||
|
|
@ -1142,8 +1191,7 @@ hb_ot_layout_collect_features (hb_face_t *face,
|
|||
for (unsigned int script_index = 0; script_index < count; script_index++)
|
||||
script_collect_features (&c,
|
||||
c.g.get_script (script_index),
|
||||
languages,
|
||||
features);
|
||||
languages);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1153,8 +1201,7 @@ hb_ot_layout_collect_features (hb_face_t *face,
|
|||
if (c.g.find_script_index (*scripts, &script_index))
|
||||
script_collect_features (&c,
|
||||
c.g.get_script (script_index),
|
||||
languages,
|
||||
features);
|
||||
languages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1262,6 +1309,8 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
|
|||
* Fetches a list of feature variations in the specified face's GSUB table
|
||||
* or GPOS table, at the specified variation coordinates.
|
||||
*
|
||||
* Return value: %true if feature variations were found, %false otherwise.
|
||||
*
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_ot_layout_table_find_feature_variations (hb_face_t *face,
|
||||
|
|
@ -1291,6 +1340,8 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face,
|
|||
* the specified face's GSUB table or GPOS table, enabled at the specified
|
||||
* variations index. The list returned will begin at the offset provided.
|
||||
*
|
||||
* Return value: Total number of lookups.
|
||||
*
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
|
||||
|
|
@ -1337,7 +1388,8 @@ hb_ot_layout_has_substitution (hb_face_t *face)
|
|||
* @lookup_index: The index of the lookup to query
|
||||
* @glyphs: The sequence of glyphs to query for substitution
|
||||
* @glyphs_length: The length of the glyph sequence
|
||||
* @zero_context: #hb_bool_t indicating whether substitutions should be context-free
|
||||
* @zero_context: #hb_bool_t indicating whether pre-/post-context are disallowed
|
||||
* in substitutions
|
||||
*
|
||||
* Tests whether a specified lookup in the specified face would
|
||||
* trigger a substitution on the given glyph sequence.
|
||||
|
|
@ -1443,12 +1495,17 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
|
|||
unsigned int lookup_index,
|
||||
hb_set_t *glyphs /* OUT */)
|
||||
{
|
||||
hb_map_t done_lookups;
|
||||
OT::hb_closure_context_t c (face, glyphs, &done_lookups);
|
||||
hb_set_t cur_intersected_glyphs;
|
||||
hb_map_t done_lookups_glyph_count;
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
|
||||
OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
|
||||
|
||||
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
|
||||
|
||||
l.closure (&c, lookup_index);
|
||||
|
||||
for (auto _ : done_lookups_glyph_set.iter ())
|
||||
hb_set_destroy (_.second);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1467,8 +1524,10 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
|
|||
const hb_set_t *lookups,
|
||||
hb_set_t *glyphs /* OUT */)
|
||||
{
|
||||
hb_map_t done_lookups;
|
||||
OT::hb_closure_context_t c (face, glyphs, &done_lookups);
|
||||
hb_set_t cur_intersected_glyphs;
|
||||
hb_map_t done_lookups_glyph_count;
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
|
||||
OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
|
||||
const OT::GSUB& gsub = *face->table.GSUB->table;
|
||||
|
||||
unsigned int iteration_count = 0;
|
||||
|
|
@ -1488,6 +1547,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
|
|||
}
|
||||
} while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
|
||||
glyphs_length != glyphs->get_population ());
|
||||
|
||||
for (auto _ : done_lookups_glyph_set.iter ())
|
||||
hb_set_destroy (_.second);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1824,27 +1886,20 @@ apply_string (OT::hb_ot_apply_context_t *c,
|
|||
if (likely (!lookup.is_reverse ()))
|
||||
{
|
||||
/* in/out forward substitution/positioning */
|
||||
if (Proxy::table_index == 0u)
|
||||
if (!Proxy::inplace)
|
||||
buffer->clear_output ();
|
||||
buffer->idx = 0;
|
||||
|
||||
bool ret;
|
||||
ret = apply_forward (c, accel);
|
||||
if (ret)
|
||||
{
|
||||
if (!Proxy::inplace)
|
||||
buffer->swap_buffers ();
|
||||
else
|
||||
assert (!buffer->has_separate_output ());
|
||||
}
|
||||
buffer->idx = 0;
|
||||
apply_forward (c, accel);
|
||||
|
||||
if (!Proxy::inplace)
|
||||
buffer->swap_buffers ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* in-place backward substitution/positioning */
|
||||
if (Proxy::table_index == 0u)
|
||||
buffer->remove_output ();
|
||||
assert (!buffer->have_output);
|
||||
buffer->idx = buffer->len - 1;
|
||||
|
||||
apply_backward (c, accel);
|
||||
}
|
||||
}
|
||||
|
|
@ -1860,7 +1915,8 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
OT::hb_ot_apply_context_t c (table_index, font, buffer);
|
||||
c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
|
||||
|
||||
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) {
|
||||
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++)
|
||||
{
|
||||
const stage_map_t *stage = &stages[table_index][stage_index];
|
||||
for (; i < stage->last_lookup; i++)
|
||||
{
|
||||
|
|
@ -1870,11 +1926,8 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
c.set_lookup_mask (lookups[table_index][i].mask);
|
||||
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
|
||||
c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
|
||||
if (lookups[table_index][i].random)
|
||||
{
|
||||
c.set_random (true);
|
||||
buffer->unsafe_to_break_all ();
|
||||
}
|
||||
c.set_random (lookups[table_index][i].random);
|
||||
|
||||
apply_string<Proxy> (&c,
|
||||
proxy.table.get_lookup (lookup_index),
|
||||
proxy.accels[lookup_index]);
|
||||
|
|
@ -1882,10 +1935,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
}
|
||||
|
||||
if (stage->pause_func)
|
||||
{
|
||||
buffer->clear_output ();
|
||||
stage->pause_func (plan, font, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1925,7 +1975,7 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
|
|||
*
|
||||
* Fetches a baseline value from the face.
|
||||
*
|
||||
* Return value: if found baseline value in the font.
|
||||
* Return value: %true if found baseline value in the font.
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
|
|
@ -1984,7 +2034,7 @@ struct hb_get_glyph_alternates_dispatch_t :
|
|||
*
|
||||
* Fetches alternates of a glyph from a given GSUB lookup index.
|
||||
*
|
||||
* Return value: total number of alternates found in the specific lookup index for the given glyph id.
|
||||
* Return value: Total number of alternates found in the specific lookup index for the given glyph id.
|
||||
*
|
||||
* Since: 2.6.8
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -314,7 +314,6 @@ _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
|
|||
hb_unicode_funcs_t::NOT_SPACE;
|
||||
}
|
||||
|
||||
static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
|
||||
static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info);
|
||||
|
||||
static inline bool
|
||||
|
|
@ -328,7 +327,7 @@ _hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
|
|||
{
|
||||
return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
|
||||
== UPROPS_MASK_IGNORABLE) &&
|
||||
!_hb_glyph_info_ligated (info);
|
||||
!_hb_glyph_info_substituted (info);
|
||||
}
|
||||
static inline void
|
||||
_hb_glyph_info_unhide (hb_glyph_info_t *info)
|
||||
|
|
|
|||
|
|
@ -150,9 +150,8 @@ void
|
|||
hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
||||
const hb_ot_shape_plan_key_t &key)
|
||||
{
|
||||
static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
|
||||
unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1;
|
||||
unsigned int global_bit_shift = hb_popcount (HB_GLYPH_FLAG_DEFINED);
|
||||
unsigned int global_bit_shift = 8 * sizeof (hb_mask_t) - 1;
|
||||
unsigned int global_bit_mask = 1u << global_bit_shift;
|
||||
|
||||
m.global_mask = global_bit_mask;
|
||||
|
||||
|
|
@ -205,7 +204,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
|
||||
|
||||
/* Allocate bits now */
|
||||
unsigned int next_bit = global_bit_shift + 1;
|
||||
static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
|
||||
unsigned int next_bit = hb_popcount (HB_GLYPH_FLAG_DEFINED) + 1;
|
||||
|
||||
for (unsigned int i = 0; i < feature_infos.length; i++)
|
||||
{
|
||||
|
|
@ -220,7 +220,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
/* Limit bits per feature. */
|
||||
bits_needed = hb_min (HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
|
||||
|
||||
if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
|
||||
if (!info->max_value || next_bit + bits_needed >= global_bit_shift)
|
||||
continue; /* Feature disabled, or not enough bits. */
|
||||
|
||||
|
||||
|
|
@ -274,7 +274,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
}
|
||||
map->_1_mask = (1u << map->shift) & map->mask;
|
||||
map->needs_fallback = !found;
|
||||
|
||||
}
|
||||
feature_infos.shrink (0); /* Done with these */
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ struct MathValueRecord
|
|||
|
||||
protected:
|
||||
HBINT16 value; /* The X or Y value in design units */
|
||||
OffsetTo<Device> deviceTable; /* Offset to the device table - from the
|
||||
Offset16To<Device> deviceTable; /* Offset to the device table - from the
|
||||
* beginning of parent table. May be NULL.
|
||||
* Suggested format for device table is 1. */
|
||||
|
||||
|
|
@ -181,11 +181,11 @@ struct MathItalicsCorrectionInfo
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<Coverage> coverage; /* Offset to Coverage table -
|
||||
Offset16To<Coverage> coverage; /* Offset to Coverage table -
|
||||
* from the beginning of
|
||||
* MathItalicsCorrectionInfo
|
||||
* table. */
|
||||
ArrayOf<MathValueRecord> italicsCorrection; /* Array of MathValueRecords
|
||||
Array16Of<MathValueRecord> italicsCorrection; /* Array of MathValueRecords
|
||||
* defining italics correction
|
||||
* values for each
|
||||
* covered glyph. */
|
||||
|
|
@ -214,11 +214,11 @@ struct MathTopAccentAttachment
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<Coverage> topAccentCoverage; /* Offset to Coverage table -
|
||||
Offset16To<Coverage> topAccentCoverage; /* Offset to Coverage table -
|
||||
* from the beginning of
|
||||
* MathTopAccentAttachment
|
||||
* table. */
|
||||
ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
|
||||
Array16Of<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
|
||||
* defining top accent
|
||||
* attachment points for each
|
||||
* covered glyph. */
|
||||
|
|
@ -320,7 +320,7 @@ struct MathKernInfoRecord
|
|||
protected:
|
||||
/* Offset to MathKern table for each corner -
|
||||
* from the beginning of MathKernInfo table. May be NULL. */
|
||||
OffsetTo<MathKern> mathKern[4];
|
||||
Offset16To<MathKern> mathKern[4];
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
|
|
@ -346,12 +346,12 @@ struct MathKernInfo
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<Coverage>
|
||||
Offset16To<Coverage>
|
||||
mathKernCoverage;
|
||||
/* Offset to Coverage table -
|
||||
* from the beginning of the
|
||||
* MathKernInfo table. */
|
||||
ArrayOf<MathKernInfoRecord>
|
||||
Array16Of<MathKernInfoRecord>
|
||||
mathKernInfoRecords;
|
||||
/* Array of MathKernInfoRecords,
|
||||
* per-glyph information for
|
||||
|
|
@ -395,22 +395,22 @@ struct MathGlyphInfo
|
|||
protected:
|
||||
/* Offset to MathItalicsCorrectionInfo table -
|
||||
* from the beginning of MathGlyphInfo table. */
|
||||
OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
|
||||
Offset16To<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
|
||||
|
||||
/* Offset to MathTopAccentAttachment table -
|
||||
* from the beginning of MathGlyphInfo table. */
|
||||
OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
|
||||
Offset16To<MathTopAccentAttachment> mathTopAccentAttachment;
|
||||
|
||||
/* Offset to coverage table for Extended Shape glyphs -
|
||||
* from the beginning of MathGlyphInfo table. When the left or right glyph of
|
||||
* a box is an extended shape variant, the (ink) box (and not the default
|
||||
* position defined by values in MathConstants table) should be used for
|
||||
* vertical positioning purposes. May be NULL.. */
|
||||
OffsetTo<Coverage> extendedShapeCoverage;
|
||||
Offset16To<Coverage> extendedShapeCoverage;
|
||||
|
||||
/* Offset to MathKernInfo table -
|
||||
* from the beginning of MathGlyphInfo table. */
|
||||
OffsetTo<MathKernInfo> mathKernInfo;
|
||||
Offset16To<MathKernInfo> mathKernInfo;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
|
|
@ -532,7 +532,7 @@ struct MathGlyphAssembly
|
|||
/* Italics correction of this
|
||||
* MathGlyphAssembly. Should not
|
||||
* depend on the assembly size. */
|
||||
ArrayOf<MathGlyphPartRecord>
|
||||
Array16Of<MathGlyphPartRecord>
|
||||
partRecords; /* Array of part records, from
|
||||
* left to right and bottom to
|
||||
* top. */
|
||||
|
|
@ -572,10 +572,10 @@ struct MathGlyphConstruction
|
|||
protected:
|
||||
/* Offset to MathGlyphAssembly table for this shape - from the beginning of
|
||||
MathGlyphConstruction table. May be NULL. */
|
||||
OffsetTo<MathGlyphAssembly> glyphAssembly;
|
||||
Offset16To<MathGlyphAssembly> glyphAssembly;
|
||||
|
||||
/* MathGlyphVariantRecords for alternative variants of the glyphs. */
|
||||
ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
|
||||
Array16Of<MathGlyphVariantRecord> mathGlyphVariantRecord;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
|
||||
|
|
@ -636,7 +636,7 @@ struct MathVariants
|
|||
{
|
||||
bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
|
||||
unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
|
||||
const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage
|
||||
const Offset16To<Coverage> &coverage = vertical ? vertGlyphCoverage
|
||||
: horizGlyphCoverage;
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (glyph);
|
||||
|
|
@ -653,11 +653,11 @@ struct MathVariants
|
|||
/* Minimum overlap of connecting
|
||||
* glyphs during glyph construction,
|
||||
* in design units. */
|
||||
OffsetTo<Coverage> vertGlyphCoverage;
|
||||
Offset16To<Coverage> vertGlyphCoverage;
|
||||
/* Offset to Coverage table -
|
||||
* from the beginning of MathVariants
|
||||
* table. */
|
||||
OffsetTo<Coverage> horizGlyphCoverage;
|
||||
Offset16To<Coverage> horizGlyphCoverage;
|
||||
/* Offset to Coverage table -
|
||||
* from the beginning of MathVariants
|
||||
* table. */
|
||||
|
|
@ -671,7 +671,7 @@ struct MathVariants
|
|||
/* Array of offsets to MathGlyphConstruction tables - from the beginning of
|
||||
the MathVariants table, for shapes growing in vertical/horizontal
|
||||
direction. */
|
||||
UnsizedArrayOf<OffsetTo<MathGlyphConstruction>>
|
||||
UnsizedArrayOf<Offset16To<MathGlyphConstruction>>
|
||||
glyphConstruction;
|
||||
|
||||
public:
|
||||
|
|
@ -711,11 +711,11 @@ struct MATH
|
|||
protected:
|
||||
FixedVersion<>version; /* Version of the MATH table
|
||||
* initially set to 0x00010000u */
|
||||
OffsetTo<MathConstants>
|
||||
Offset16To<MathConstants>
|
||||
mathConstants; /* MathConstants table */
|
||||
OffsetTo<MathGlyphInfo>
|
||||
Offset16To<MathGlyphInfo>
|
||||
mathGlyphInfo; /* MathGlyphInfo table */
|
||||
OffsetTo<MathVariants>
|
||||
Offset16To<MathVariants>
|
||||
mathVariants; /* MathVariants table */
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ struct maxp
|
|||
maxpV1Tail *dest_v1 = c->serializer->embed<maxpV1Tail> (src_v1);
|
||||
if (unlikely (!dest_v1)) return_trace (false);
|
||||
|
||||
if (c->plan->drop_hints)
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
drop_hint_fields (dest_v1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ struct DataMap
|
|||
|
||||
protected:
|
||||
Tag tag; /* A tag indicating the type of metadata. */
|
||||
LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT8>>
|
||||
dataZ; /* Offset in bytes from the beginning of the
|
||||
* metadata table to the data for this tag. */
|
||||
HBUINT32 dataLength; /* Length of the data. The data is not required to
|
||||
|
|
@ -113,7 +113,7 @@ struct meta
|
|||
* Offset from the beginning of the table to the data.
|
||||
* Per OT specification:
|
||||
* Reserved. Not used; should be set to 0. */
|
||||
LArrayOf<DataMap>
|
||||
Array32Of<DataMap>
|
||||
dataMaps;/* Array of data map records. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (16, dataMaps);
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ struct NameRecord
|
|||
HBUINT16 languageID; /* Language ID. */
|
||||
HBUINT16 nameID; /* Name ID. */
|
||||
HBUINT16 length; /* String length (in bytes). */
|
||||
NNOffsetTo<UnsizedArrayOf<HBUINT8>>
|
||||
NNOffset16To<UnsizedArrayOf<HBUINT8>>
|
||||
offset; /* String offset from start of storage area (in bytes). */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
|
|
@ -214,7 +214,7 @@ struct name
|
|||
this->format = 0;
|
||||
this->count = it.len ();
|
||||
|
||||
NameRecord *name_records = (NameRecord *) calloc (it.len (), NameRecord::static_size);
|
||||
NameRecord *name_records = (NameRecord *) hb_calloc (it.len (), NameRecord::static_size);
|
||||
if (unlikely (!name_records)) return_trace (false);
|
||||
|
||||
hb_array_t<NameRecord> records (name_records, it.len ());
|
||||
|
|
@ -228,9 +228,10 @@ struct name
|
|||
records.qsort ();
|
||||
|
||||
c->copy_all (records, src_string_pool);
|
||||
free (records.arrayZ);
|
||||
hb_free (records.arrayZ);
|
||||
|
||||
if (unlikely (c->ran_out_of_room)) return_trace (false);
|
||||
|
||||
if (unlikely (c->ran_out_of_room ())) return_trace (false);
|
||||
|
||||
this->stringOffset = c->length ();
|
||||
|
||||
|
|
@ -248,7 +249,11 @@ struct name
|
|||
+ nameRecordZ.as_array (count)
|
||||
| hb_filter (c->plan->name_ids, &NameRecord::nameID)
|
||||
| hb_filter (c->plan->name_languages, &NameRecord::languageID)
|
||||
| hb_filter ([&] (const NameRecord& namerecord) { return c->plan->name_legacy || namerecord.isUnicode (); })
|
||||
| hb_filter ([&] (const NameRecord& namerecord) {
|
||||
return
|
||||
(c->plan->flags & HB_SUBSET_FLAGS_NAME_LEGACY)
|
||||
|| namerecord.isUnicode ();
|
||||
})
|
||||
;
|
||||
|
||||
name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset));
|
||||
|
|
@ -357,7 +362,7 @@ struct name
|
|||
/* We only implement format 0 for now. */
|
||||
HBUINT16 format; /* Format selector (=0/1). */
|
||||
HBUINT16 count; /* Number of name records. */
|
||||
NNOffsetTo<UnsizedArrayOf<HBUINT8>>
|
||||
NNOffset16To<UnsizedArrayOf<HBUINT8>>
|
||||
stringOffset; /* Offset to start of string storage (from start of table). */
|
||||
UnsizedArrayOf<NameRecord>
|
||||
nameRecordZ; /* The name records where count is the number of records. */
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-os2-unicode-ranges.hh"
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
|
||||
#include "hb-set.hh"
|
||||
|
||||
|
|
@ -172,33 +171,17 @@ struct OS2
|
|||
TRACE_SUBSET (this);
|
||||
OS2 *os2_prime = c->serializer->embed (this);
|
||||
if (unlikely (!os2_prime)) return_trace (false);
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
|
||||
return_trace (true);
|
||||
|
||||
hb_set_t unicodes;
|
||||
if (!c->plan->glyphs_requested->is_empty ())
|
||||
{
|
||||
hb_map_t unicode_glyphid_map;
|
||||
|
||||
OT::cmap::accelerator_t cmap;
|
||||
cmap.init (c->plan->source);
|
||||
cmap.collect_mapping (&unicodes, &unicode_glyphid_map);
|
||||
cmap.fini ();
|
||||
|
||||
hb_set_set (&unicodes, c->plan->unicodes);
|
||||
|
||||
+ unicode_glyphid_map.iter ()
|
||||
| hb_filter (c->plan->glyphs_requested, hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_sink (unicodes)
|
||||
;
|
||||
}
|
||||
/* when --gids option is not used, no need to do collect_mapping that is
|
||||
* iterating all codepoints in each subtable, which is not efficient */
|
||||
uint16_t min_cp, max_cp;
|
||||
find_min_and_max_codepoint (unicodes.is_empty () ? c->plan->unicodes : &unicodes, &min_cp, &max_cp);
|
||||
find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
|
||||
os2_prime->usFirstCharIndex = min_cp;
|
||||
os2_prime->usLastCharIndex = max_cp;
|
||||
|
||||
_update_unicode_ranges (unicodes.is_empty () ? c->plan->unicodes : &unicodes, os2_prime->ulUnicodeRange);
|
||||
_update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright © 2021 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_POST_TABLE_V2SUBSET_HH
|
||||
#define HB_OT_POST_TABLE_V2SUBSET_HH
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-post-table.hh"
|
||||
|
||||
/*
|
||||
* post -- PostScript
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/post
|
||||
*/
|
||||
|
||||
namespace OT {
|
||||
template<typename Iterator>
|
||||
HB_INTERNAL bool postV2Tail::serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
const void* _post) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->start_embed (this);
|
||||
if (unlikely (!c->check_success (out))) return_trace (false);
|
||||
if (!out->glyphNameIndex.serialize (c, + it
|
||||
| hb_map (hb_second)))
|
||||
return_trace (false);
|
||||
|
||||
hb_set_t copied_indices;
|
||||
for (const auto& _ : + it )
|
||||
{
|
||||
unsigned glyph_id = _.first;
|
||||
unsigned new_index = _.second;
|
||||
|
||||
if (new_index < 258) continue;
|
||||
if (copied_indices.has (new_index)) continue;
|
||||
copied_indices.add (new_index);
|
||||
|
||||
hb_bytes_t s = reinterpret_cast<const post::accelerator_t*> (_post)->find_glyph_name (glyph_id);
|
||||
HBUINT8 *o = c->allocate_size<HBUINT8> (HBUINT8::static_size * (s.length + 1));
|
||||
if (unlikely (!o)) return_trace (false);
|
||||
if (!c->check_assign (o[0], s.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
|
||||
memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
|
||||
unsigned num_glyphs = c->plan->num_output_glyphs ();
|
||||
hb_map_t old_new_index_map, old_gid_new_index_map;
|
||||
unsigned i = 0;
|
||||
|
||||
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
|
||||
unsigned old_index = glyphNameIndex[old_gid];
|
||||
|
||||
unsigned new_index;
|
||||
if (old_index <= 257) new_index = old_index;
|
||||
else if (old_new_index_map.has (old_index)) new_index = old_new_index_map.get (old_index);
|
||||
else
|
||||
{
|
||||
new_index = 258 + i;
|
||||
old_new_index_map.set (old_index, new_index);
|
||||
i++;
|
||||
}
|
||||
old_gid_new_index_map.set (old_gid, new_index);
|
||||
}
|
||||
|
||||
auto index_iter =
|
||||
+ hb_range (num_glyphs)
|
||||
| hb_map (reverse_glyph_map)
|
||||
| hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
|
||||
{
|
||||
unsigned new_index = old_gid_new_index_map.get (old_gid);
|
||||
return hb_pair_t<unsigned, unsigned> (old_gid, new_index);
|
||||
})
|
||||
;
|
||||
|
||||
post::accelerator_t _post;
|
||||
_post.init (c->plan->source);
|
||||
bool ret = serialize (c->serializer, index_iter, &_post);
|
||||
_post.fini ();
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
} /* namespace OT */
|
||||
#endif /* HB_OT_POST_TABLE_V2SUBSET_HH */
|
||||
|
|
@ -55,8 +55,15 @@ struct postV2Tail
|
|||
return_trace (glyphNameIndex.sanitize (c));
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
const void* _post) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const;
|
||||
|
||||
protected:
|
||||
ArrayOf<HBUINT16> glyphNameIndex; /* This is not an offset, but is the
|
||||
Array16Of<HBUINT16> glyphNameIndex; /* This is not an offset, but is the
|
||||
* ordinal number of the glyph in 'post'
|
||||
* string tables. */
|
||||
/*UnsizedArrayOf<HBUINT8>
|
||||
|
|
@ -71,13 +78,18 @@ struct post
|
|||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
|
||||
|
||||
void serialize (hb_serialize_context_t *c) const
|
||||
bool serialize (hb_serialize_context_t *c, bool glyph_names) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
post *post_prime = c->allocate_min<post> ();
|
||||
if (unlikely (!post_prime)) return;
|
||||
if (unlikely (!post_prime)) return_trace (false);
|
||||
|
||||
memcpy (post_prime, this, post::min_size);
|
||||
post_prime->version.major = 3; // Version 3 does not have any glyph names.
|
||||
if (!glyph_names)
|
||||
return_trace (c->check_assign (post_prime->version.major, 3,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW)); // Version 3 does not have any glyph names.
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
|
|
@ -86,13 +98,19 @@ struct post
|
|||
post *post_prime = c->serializer->start_embed<post> ();
|
||||
if (unlikely (!post_prime)) return_trace (false);
|
||||
|
||||
serialize (c->serializer);
|
||||
bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
|
||||
if (!serialize (c->serializer, glyph_names))
|
||||
return_trace (false);
|
||||
|
||||
if (glyph_names && version.major == 2)
|
||||
return_trace (v2X.subset (c));
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
friend struct postV2Tail;
|
||||
void init (hb_face_t *face)
|
||||
{
|
||||
index_to_offset.init ();
|
||||
|
|
@ -117,7 +135,7 @@ struct post
|
|||
void fini ()
|
||||
{
|
||||
index_to_offset.fini ();
|
||||
free (gids_sorted_by_name.get ());
|
||||
hb_free (gids_sorted_by_name.get ());
|
||||
table.destroy ();
|
||||
}
|
||||
|
||||
|
|
@ -148,7 +166,7 @@ struct post
|
|||
|
||||
if (unlikely (!gids))
|
||||
{
|
||||
gids = (uint16_t *) malloc (count * sizeof (gids[0]));
|
||||
gids = (uint16_t *) hb_malloc (count * sizeof (gids[0]));
|
||||
if (unlikely (!gids))
|
||||
return false; /* Anything better?! */
|
||||
|
||||
|
|
@ -158,7 +176,7 @@ struct post
|
|||
|
||||
if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
|
||||
{
|
||||
free (gids);
|
||||
hb_free (gids);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
@ -236,7 +254,7 @@ struct post
|
|||
|
||||
private:
|
||||
uint32_t version;
|
||||
const ArrayOf<HBUINT16> *glyphNameIndex;
|
||||
const Array16Of<HBUINT16> *glyphNameIndex;
|
||||
hb_vector_t<uint32_t> index_to_offset;
|
||||
const uint8_t *pool;
|
||||
hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
|
||||
|
|
|
|||
|
|
@ -208,11 +208,11 @@ struct ManifestLookup
|
|||
{
|
||||
public:
|
||||
OT::Tag tag;
|
||||
OT::OffsetTo<OT::SubstLookup> lookupOffset;
|
||||
OT::Offset16To<OT::SubstLookup> lookupOffset;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
typedef OT::ArrayOf<ManifestLookup> Manifest;
|
||||
typedef OT::Array16Of<ManifestLookup> Manifest;
|
||||
|
||||
static bool
|
||||
arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED,
|
||||
|
|
@ -290,7 +290,7 @@ static arabic_fallback_plan_t *
|
|||
arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font)
|
||||
{
|
||||
arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
|
||||
arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_calloc (1, sizeof (arabic_fallback_plan_t));
|
||||
if (unlikely (!fallback_plan))
|
||||
return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
|
||||
|
||||
|
|
@ -308,7 +308,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
|
|||
return fallback_plan;
|
||||
|
||||
assert (fallback_plan->num_lookups == 0);
|
||||
free (fallback_plan);
|
||||
hb_free (fallback_plan);
|
||||
return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
|
||||
}
|
||||
|
||||
|
|
@ -323,10 +323,10 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
|
|||
{
|
||||
fallback_plan->accel_array[i].fini ();
|
||||
if (fallback_plan->free_lookups)
|
||||
free (fallback_plan->lookup_array[i]);
|
||||
hb_free (fallback_plan->lookup_array[i]);
|
||||
}
|
||||
|
||||
free (fallback_plan);
|
||||
hb_free (fallback_plan);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ struct arabic_shape_plan_t
|
|||
void *
|
||||
data_create_arabic (const hb_ot_shape_plan_t *plan)
|
||||
{
|
||||
arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t));
|
||||
arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) hb_calloc (1, sizeof (arabic_shape_plan_t));
|
||||
if (unlikely (!arabic_plan))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -282,7 +282,7 @@ data_destroy_arabic (void *data)
|
|||
|
||||
arabic_fallback_plan_destroy (arabic_plan->fallback_plan);
|
||||
|
||||
free (data);
|
||||
hb_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ struct hangul_shape_plan_t
|
|||
static void *
|
||||
data_create_hangul (const hb_ot_shape_plan_t *plan)
|
||||
{
|
||||
hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) calloc (1, sizeof (hangul_shape_plan_t));
|
||||
hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) hb_calloc (1, sizeof (hangul_shape_plan_t));
|
||||
if (unlikely (!hangul_plan))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ data_create_hangul (const hb_ot_shape_plan_t *plan)
|
|||
static void
|
||||
data_destroy_hangul (void *data)
|
||||
{
|
||||
free (data);
|
||||
hb_free (data);
|
||||
}
|
||||
|
||||
/* Constants for algorithmic hangul syllable [de]composition. */
|
||||
|
|
|
|||
|
|
@ -106,7 +106,8 @@ indic_features[] =
|
|||
{
|
||||
/*
|
||||
* Basic features.
|
||||
* These features are applied in order, one at a time, after initial_reordering.
|
||||
* These features are applied in order, one at a time, after initial_reordering,
|
||||
* constrained to the syllable.
|
||||
*/
|
||||
{HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
|
||||
{HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
|
||||
|
|
@ -121,8 +122,8 @@ indic_features[] =
|
|||
{HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
|
||||
/*
|
||||
* Other features.
|
||||
* These features are applied all at once, after final_reordering
|
||||
* but before clearing syllables.
|
||||
* These features are applied all at once, after final_reordering, constrained
|
||||
* to the syllable.
|
||||
* Default Bengali font in Windows for example has intermixed
|
||||
* lookups for init,pres,abvs,blws features.
|
||||
*/
|
||||
|
|
@ -257,7 +258,7 @@ struct indic_shape_plan_t
|
|||
static void *
|
||||
data_create_indic (const hb_ot_shape_plan_t *plan)
|
||||
{
|
||||
indic_shape_plan_t *indic_plan = (indic_shape_plan_t *) calloc (1, sizeof (indic_shape_plan_t));
|
||||
indic_shape_plan_t *indic_plan = (indic_shape_plan_t *) hb_calloc (1, sizeof (indic_shape_plan_t));
|
||||
if (unlikely (!indic_plan))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -300,7 +301,7 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
|
|||
static void
|
||||
data_destroy_indic (void *data)
|
||||
{
|
||||
free (data);
|
||||
hb_free (data);
|
||||
}
|
||||
|
||||
static indic_position_t
|
||||
|
|
@ -960,7 +961,8 @@ initial_reordering_indic (const hb_ot_shape_plan_t *plan,
|
|||
hb_syllabic_insert_dotted_circles (font, buffer,
|
||||
indic_broken_cluster,
|
||||
OT_DOTTEDCIRCLE,
|
||||
OT_Repha);
|
||||
OT_Repha,
|
||||
POS_END);
|
||||
|
||||
foreach_syllable (buffer, start, end)
|
||||
initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ khmer_features[] =
|
|||
{
|
||||
/*
|
||||
* Basic features.
|
||||
* These features are applied in order, one at a time, after reordering.
|
||||
* These features are applied all at once, before reordering, constrained
|
||||
* to the syllable.
|
||||
*/
|
||||
{HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
|
||||
{HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
|
||||
|
|
@ -147,7 +148,7 @@ struct khmer_shape_plan_t
|
|||
static void *
|
||||
data_create_khmer (const hb_ot_shape_plan_t *plan)
|
||||
{
|
||||
khmer_shape_plan_t *khmer_plan = (khmer_shape_plan_t *) calloc (1, sizeof (khmer_shape_plan_t));
|
||||
khmer_shape_plan_t *khmer_plan = (khmer_shape_plan_t *) hb_calloc (1, sizeof (khmer_shape_plan_t));
|
||||
if (unlikely (!khmer_plan))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -161,7 +162,7 @@ data_create_khmer (const hb_ot_shape_plan_t *plan)
|
|||
static void
|
||||
data_destroy_khmer (void *data)
|
||||
{
|
||||
free (data);
|
||||
hb_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ myanmar_basic_features[] =
|
|||
{
|
||||
/*
|
||||
* Basic features.
|
||||
* These features are applied in order, one at a time, after reordering.
|
||||
* These features are applied in order, one at a time, after reordering,
|
||||
* constrained to the syllable.
|
||||
*/
|
||||
HB_TAG('r','p','h','f'),
|
||||
HB_TAG('p','r','e','f'),
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
|
|||
hb_buffer_t *buffer,
|
||||
unsigned int broken_syllable_type,
|
||||
unsigned int dottedcircle_category,
|
||||
int repha_category)
|
||||
int repha_category,
|
||||
int dottedcircle_position)
|
||||
{
|
||||
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
|
||||
return;
|
||||
|
|
@ -61,6 +62,8 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
|
|||
hb_glyph_info_t dottedcircle = {0};
|
||||
dottedcircle.codepoint = 0x25CCu;
|
||||
dottedcircle.complex_var_u8_category() = dottedcircle_category;
|
||||
if (dottedcircle_position != -1)
|
||||
dottedcircle.complex_var_u8_auxiliary() = dottedcircle_position;
|
||||
dottedcircle.codepoint = dottedcircle_glyph;
|
||||
|
||||
buffer->clear_output ();
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
|
|||
hb_buffer_t *buffer,
|
||||
unsigned int broken_syllable_type,
|
||||
unsigned int dottedcircle_category,
|
||||
int repha_category = -1);
|
||||
int repha_category = -1,
|
||||
int dottedcircle_position = -1);
|
||||
|
||||
|
||||
#endif /* HB_OT_SHAPE_COMPLEX_SYLLABIC_HH */
|
||||
|
|
|
|||
|
|
@ -375,7 +375,9 @@ hb_iter_with_fallback_t<machine_index_t<Iter>,
|
|||
typename Iter::item_t>
|
||||
{
|
||||
machine_index_t (const Iter& it) : it (it) {}
|
||||
machine_index_t (const machine_index_t& o) : it (o.it) {}
|
||||
machine_index_t (const machine_index_t& o) :
|
||||
hb_iter_with_fallback_t<machine_index_t<Iter>, typename Iter::item_t>(o),
|
||||
it (o.it) {}
|
||||
|
||||
static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
|
||||
static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ use_basic_features[] =
|
|||
{
|
||||
/*
|
||||
* Basic features.
|
||||
* These features are applied all at once, before reordering.
|
||||
* These features are applied all at once, before reordering, constrained
|
||||
* to the syllable.
|
||||
*/
|
||||
HB_TAG('r','k','r','f'),
|
||||
HB_TAG('a','b','v','f'),
|
||||
|
|
@ -154,7 +155,7 @@ struct use_shape_plan_t
|
|||
static void *
|
||||
data_create_use (const hb_ot_shape_plan_t *plan)
|
||||
{
|
||||
use_shape_plan_t *use_plan = (use_shape_plan_t *) calloc (1, sizeof (use_shape_plan_t));
|
||||
use_shape_plan_t *use_plan = (use_shape_plan_t *) hb_calloc (1, sizeof (use_shape_plan_t));
|
||||
if (unlikely (!use_plan))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -165,7 +166,7 @@ data_create_use (const hb_ot_shape_plan_t *plan)
|
|||
use_plan->arabic_plan = (arabic_shape_plan_t *) data_create_arabic (plan);
|
||||
if (unlikely (!use_plan->arabic_plan))
|
||||
{
|
||||
free (use_plan);
|
||||
hb_free (use_plan);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -181,7 +182,7 @@ data_destroy_use (void *data)
|
|||
if (use_plan->arabic_plan)
|
||||
data_destroy_arabic (use_plan->arabic_plan);
|
||||
|
||||
free (data);
|
||||
hb_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ recategorize_combining_class (hb_codepoint_t u,
|
|||
case HB_MODIFIED_COMBINING_CLASS_CCC15: /* tsere */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC16: /* segol */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC17: /* patah */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats & qamats qatan */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC20: /* qubuts */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC22: /* meteg */
|
||||
return HB_UNICODE_COMBINING_CLASS_BELOW;
|
||||
|
|
@ -104,7 +104,7 @@ recategorize_combining_class (hb_codepoint_t u,
|
|||
return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC25: /* sin dot */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam & holam haser for vav */
|
||||
return HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC26: /* point varika */
|
||||
|
|
|
|||
|
|
@ -149,13 +149,15 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
* Decide who does positioning. GPOS, kerx, kern, or fallback.
|
||||
*/
|
||||
|
||||
if (0)
|
||||
bool has_gsub = hb_ot_layout_has_substitution (face);
|
||||
bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
|
||||
if (false)
|
||||
;
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
else if (hb_aat_layout_has_positioning (face))
|
||||
else if (hb_aat_layout_has_positioning (face) && !(has_gsub && has_gpos))
|
||||
plan.apply_kerx = true;
|
||||
#endif
|
||||
else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face))
|
||||
else if (!apply_morx && has_gpos)
|
||||
plan.apply_gpos = true;
|
||||
|
||||
if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos))
|
||||
|
|
@ -172,6 +174,8 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
#endif
|
||||
}
|
||||
|
||||
plan.apply_fallback_kern = !(plan.apply_gpos || plan.apply_kerx || plan.apply_kern);
|
||||
|
||||
plan.zero_marks = script_zero_marks &&
|
||||
!plan.apply_kerx &&
|
||||
(!plan.apply_kern
|
||||
|
|
@ -193,6 +197,12 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
script_fallback_mark_positioning;
|
||||
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
/* If we're using morx shaping, we cancel mark position adjustment because
|
||||
Apple Color Emoji assumes this will NOT be done when forming emoji sequences;
|
||||
https://github.com/harfbuzz/harfbuzz/issues/2967. */
|
||||
if (plan.apply_morx)
|
||||
plan.adjust_mark_positioning_when_zeroing = false;
|
||||
|
||||
/* Currently we always apply trak. */
|
||||
plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
|
||||
#endif
|
||||
|
|
@ -266,11 +276,12 @@ hb_ot_shape_plan_t::position (hb_font_t *font,
|
|||
else if (this->apply_kerx)
|
||||
hb_aat_layout_position (this, font, buffer);
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_OT_KERN
|
||||
else if (this->apply_kern)
|
||||
if (this->apply_kern)
|
||||
hb_ot_layout_kern (this, font, buffer);
|
||||
#endif
|
||||
else
|
||||
else if (this->apply_fallback_kern)
|
||||
_hb_ot_shape_fallback_kern (this, font, buffer);
|
||||
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
|
|
@ -363,6 +374,10 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
|
|||
map->add_feature (horizontal_features[i]);
|
||||
else
|
||||
{
|
||||
/* We only apply `vert` feature. See:
|
||||
* https://github.com/harfbuzz/harfbuzz/commit/d71c0df2d17f4590d5611239577a6cb532c26528
|
||||
* https://lists.freedesktop.org/archives/harfbuzz/2013-August/003490.html */
|
||||
|
||||
/* We really want to find a 'vert' feature if there's any in the font, no
|
||||
* matter which script/langsys it is listed (or not) under.
|
||||
* See various bugs referenced from:
|
||||
|
|
@ -478,6 +493,14 @@ hb_set_unicode_props (hb_buffer_t *buffer)
|
|||
if (unlikely (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL &&
|
||||
hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F3FBu, 0x1F3FFu)))
|
||||
{
|
||||
_hb_glyph_info_set_continuation (&info[i]);
|
||||
}
|
||||
/* Regional_Indicators are hairy as hell...
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/2265 */
|
||||
else if (unlikely (i && hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F1E6u, 0x1F1FFu)))
|
||||
{
|
||||
if (hb_in_range<hb_codepoint_t> (info[i - 1].codepoint, 0x1F1E6u, 0x1F1FFu) &&
|
||||
!_hb_glyph_info_is_continuation (&info[i - 1]))
|
||||
_hb_glyph_info_set_continuation (&info[i]);
|
||||
}
|
||||
#ifndef HB_NO_EMOJI_SEQUENCES
|
||||
|
|
@ -535,6 +558,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
|||
info.cluster = buffer->cur().cluster;
|
||||
info.mask = buffer->cur().mask;
|
||||
(void) buffer->output_info (info);
|
||||
|
||||
buffer->swap_buffers ();
|
||||
}
|
||||
|
||||
|
|
@ -558,6 +582,36 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
|
|||
hb_direction_t direction = buffer->props.direction;
|
||||
hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script);
|
||||
|
||||
/* Numeric runs in natively-RTL scripts are actually native-LTR, so we reset
|
||||
* the horiz_dir if the run contains at least one decimal-number char, and no
|
||||
* letter chars (ideally we should be checking for chars with strong
|
||||
* directionality but hb-unicode currently lacks bidi categories).
|
||||
*
|
||||
* This allows digit sequences in Arabic etc to be shaped in "native"
|
||||
* direction, so that features like ligatures will work as intended.
|
||||
*
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/501
|
||||
*/
|
||||
if (unlikely (horiz_dir == HB_DIRECTION_RTL && direction == HB_DIRECTION_LTR))
|
||||
{
|
||||
bool found_number = false, found_letter = false;
|
||||
const auto* info = buffer->info;
|
||||
const auto count = buffer->len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
auto gc = _hb_glyph_info_get_general_category (&info[i]);
|
||||
if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
|
||||
found_number = true;
|
||||
else if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc))
|
||||
{
|
||||
found_letter = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found_number && !found_letter)
|
||||
horiz_dir = HB_DIRECTION_LTR;
|
||||
}
|
||||
|
||||
/* TODO vertical:
|
||||
* The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
|
||||
* Ogham fonts are supposed to be implemented BTT or not. Need to research that
|
||||
|
|
@ -1111,8 +1165,6 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
|
|||
|
||||
_hb_buffer_allocate_unicode_vars (c->buffer);
|
||||
|
||||
c->buffer->clear_output ();
|
||||
|
||||
hb_ot_shape_initialize_masks (c);
|
||||
hb_set_unicode_props (c->buffer);
|
||||
hb_insert_dotted_circle (c->buffer, c->font);
|
||||
|
|
@ -1122,7 +1174,8 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
|
|||
hb_ensure_native_direction (c->buffer);
|
||||
|
||||
if (c->plan->shaper->preprocess_text &&
|
||||
c->buffer->message(c->font, "start preprocess-text")) {
|
||||
c->buffer->message(c->font, "start preprocess-text"))
|
||||
{
|
||||
c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
|
||||
(void) c->buffer->message(c->font, "end preprocess-text");
|
||||
}
|
||||
|
|
@ -1164,7 +1217,7 @@ _hb_ot_shape (hb_shape_plan_t *shape_plan,
|
|||
* @lookup_indexes: (out): The #hb_set_t set of lookups returned
|
||||
*
|
||||
* Computes the complete set of GSUB or GPOS lookups that are applicable
|
||||
* under a given @shape_plan.
|
||||
* under a given @shape_plan.
|
||||
*
|
||||
* Since: 0.9.7
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ struct hb_ot_shape_plan_t
|
|||
#else
|
||||
static constexpr bool apply_kern = false;
|
||||
#endif
|
||||
bool apply_fallback_kern : 1;
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
bool apply_kerx : 1;
|
||||
bool apply_morx : 1;
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ struct STAT
|
|||
unsigned int axis_index;
|
||||
if (!get_design_axes ().lfind (tag, &axis_index)) return false;
|
||||
|
||||
hb_array_t<const OffsetTo<AxisValue>> axis_values = get_axis_value_offsets ();
|
||||
hb_array_t<const Offset16To<AxisValue>> axis_values = get_axis_value_offsets ();
|
||||
for (unsigned int i = 0; i < axis_values.length; i++)
|
||||
{
|
||||
const AxisValue& axis_value = this+axis_values[i];
|
||||
|
|
@ -359,7 +359,7 @@ struct STAT
|
|||
hb_array_t<const StatAxisRecord> const get_design_axes () const
|
||||
{ return (this+designAxesOffset).as_array (designAxisCount); }
|
||||
|
||||
hb_array_t<const OffsetTo<AxisValue>> const get_axis_value_offsets () const
|
||||
hb_array_t<const Offset16To<AxisValue>> const get_axis_value_offsets () const
|
||||
{ return (this+offsetToAxisValueOffsets).as_array (axisValueCount); }
|
||||
|
||||
|
||||
|
|
@ -373,7 +373,7 @@ struct STAT
|
|||
* in the 'fvar' table. In all fonts, must
|
||||
* be greater than zero if axisValueCount
|
||||
* is greater than zero. */
|
||||
LNNOffsetTo<UnsizedArrayOf<StatAxisRecord>>
|
||||
NNOffset32To<UnsizedArrayOf<StatAxisRecord>>
|
||||
designAxesOffset;
|
||||
/* Offset in bytes from the beginning of
|
||||
* the STAT table to the start of the design
|
||||
|
|
@ -381,7 +381,7 @@ struct STAT
|
|||
* set to zero; if designAxisCount is greater
|
||||
* than zero, must be greater than zero. */
|
||||
HBUINT16 axisValueCount; /* The number of axis value tables. */
|
||||
LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue>>>
|
||||
NNOffset32To<UnsizedArrayOf<Offset16To<AxisValue>>>
|
||||
offsetToAxisValueOffsets;
|
||||
/* Offset in bytes from the beginning of
|
||||
* the STAT table to the start of the design
|
||||
|
|
|
|||
|
|
@ -522,7 +522,7 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag,
|
|||
unsigned char *buf;
|
||||
const char *lang_str = hb_language_to_string (*language);
|
||||
size_t len = strlen (lang_str);
|
||||
buf = (unsigned char *) malloc (len + 16);
|
||||
buf = (unsigned char *) hb_malloc (len + 16);
|
||||
if (unlikely (!buf))
|
||||
{
|
||||
*language = nullptr;
|
||||
|
|
@ -544,7 +544,7 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag,
|
|||
for (shift = 28; shift >= 0; shift -= 4)
|
||||
buf[len++] = TOHEX (script_tag >> shift);
|
||||
*language = hb_language_from_string ((char *) buf, len);
|
||||
free (buf);
|
||||
hb_free (buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ struct AxisValueMap
|
|||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
struct SegmentMaps : ArrayOf<AxisValueMap>
|
||||
struct SegmentMaps : Array16Of<AxisValueMap>
|
||||
{
|
||||
int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -142,11 +142,13 @@ struct AxisRecord
|
|||
max = hb_max (default_, maxValue / 65536.f);
|
||||
}
|
||||
|
||||
protected:
|
||||
public:
|
||||
Tag axisTag; /* Tag identifying the design variation for the axis. */
|
||||
protected:
|
||||
HBFixed minValue; /* The minimum coordinate value for the axis. */
|
||||
HBFixed defaultValue; /* The default coordinate value for the axis. */
|
||||
HBFixed maxValue; /* The maximum coordinate value for the axis. */
|
||||
public:
|
||||
HBUINT16 flags; /* Axis flags. */
|
||||
NameID axisNameID; /* The name ID for entries in the 'name' table that
|
||||
* provide a display name for this axis. */
|
||||
|
|
@ -214,7 +216,6 @@ struct fvar
|
|||
return axes.lfind (tag, axis_index) && (axes[*axis_index].get_axis_deprecated (info), true);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
find_axis_info (hb_tag_t tag, hb_ot_var_axis_info_t *info) const
|
||||
{
|
||||
|
|
@ -289,7 +290,7 @@ struct fvar
|
|||
;
|
||||
}
|
||||
|
||||
protected:
|
||||
public:
|
||||
hb_array_t<const AxisRecord> get_axes () const
|
||||
{ return hb_array (&(this+firstAxis), axisCount); }
|
||||
|
||||
|
|
@ -303,7 +304,7 @@ struct fvar
|
|||
protected:
|
||||
FixedVersion<>version; /* Version of the fvar table
|
||||
* initially set to 0x00010000u */
|
||||
OffsetTo<AxisRecord>
|
||||
Offset16To<AxisRecord>
|
||||
firstAxis; /* Offset in bytes from the beginning of the table
|
||||
* to the start of the AxisRecord array. */
|
||||
HBUINT16 reserved; /* This field is permanently reserved. Set to 2. */
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ struct GlyphVariationData
|
|||
* low 12 bits are the number of tuple variation tables
|
||||
* for this glyph. The number of tuple variation tables
|
||||
* can be any number between 1 and 4095. */
|
||||
OffsetTo<HBUINT8>
|
||||
Offset16To<HBUINT8>
|
||||
data; /* Offset from the start of the GlyphVariationData table
|
||||
* to the serialized data. */
|
||||
/* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
|
||||
|
|
@ -419,7 +419,9 @@ struct gvar
|
|||
out->glyphCount = num_glyphs;
|
||||
|
||||
unsigned int subset_data_size = 0;
|
||||
for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
|
||||
for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
|
||||
gid < num_glyphs;
|
||||
gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid;
|
||||
if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue;
|
||||
|
|
@ -449,7 +451,9 @@ struct gvar
|
|||
out->dataZ = subset_data - (char *) out;
|
||||
|
||||
unsigned int glyph_offset = 0;
|
||||
for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
|
||||
for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
|
||||
gid < num_glyphs;
|
||||
gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid;
|
||||
hb_bytes_t var_data_bytes = c->plan->old_gid_for_new_gid (gid, &old_gid)
|
||||
|
|
@ -676,7 +680,7 @@ no_more_gaps:
|
|||
* can be referenced within glyph variation data tables for
|
||||
* multiple glyphs, as opposed to other tuple records stored
|
||||
* directly within a glyph variation data table. */
|
||||
LNNOffsetTo<UnsizedArrayOf<F2DOT14>>
|
||||
NNOffset32To<UnsizedArrayOf<F2DOT14>>
|
||||
sharedTuples; /* Offset from the start of this table to the shared tuple records.
|
||||
* Array of tuple records shared across all glyph variation data tables. */
|
||||
HBUINT16 glyphCount; /* The number of glyphs in this font. This must match the number of
|
||||
|
|
@ -684,7 +688,7 @@ no_more_gaps:
|
|||
HBUINT16 flags; /* Bit-field that gives the format of the offset array that follows.
|
||||
* If bit 0 is clear, the offsets are uint16; if bit 0 is set, the
|
||||
* offsets are uint32. */
|
||||
LOffsetTo<GlyphVariationData>
|
||||
Offset32To<GlyphVariationData>
|
||||
dataZ; /* Offset from the start of this table to the array of
|
||||
* GlyphVariationData tables. */
|
||||
UnsizedArrayOf<HBUINT8>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue