Merge branch 'master' into cff-subset

This commit is contained in:
Michiharu Ariza 2018-09-11 09:46:37 -07:00
commit 45e564a519
58 changed files with 1354 additions and 1179 deletions

19
NEWS
View File

@ -1,3 +1,22 @@
Overview of changes leading to 1.9.0
Monday, September 10, 2018
====================================
- Added 'cmap' API to hb_face_t.
- Face-builder API.
- hb-ot-font re-creation should be much leaner now, as the
font tables it uses are cached on hb_face_t now.
- Internal source header file name changes:
hb-*-private.hh is renamed to hb-*.hh.
New API:
+HB_UNICODE_MAX
+hb_face_collect_unicodes()
+hb_face_collect_variation_selectors()
+hb_face_collect_variation_unicodes()
+hb_face_builder_create()
+hb_face_builder_add_table()
Overview of changes leading to 1.8.8
Tuesday, August 14, 2018
====================================

View File

@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
[1.8.8],
[1.9.0],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])

View File

@ -582,6 +582,8 @@ hb_set_union
<SECTION>
<FILE>hb-shape</FILE>
HB_FEATURE_GLOBAL_END
HB_FEATURE_GLOBAL_START
hb_feature_t
hb_feature_from_string
hb_feature_to_string

View File

@ -7,6 +7,7 @@ HB_BASE_sources = \
hb-buffer.hh \
hb-buffer-serialize.cc \
hb-buffer.cc \
hb-cache.hh \
hb-common.cc \
hb-debug.hh \
hb-dsalgs.hh \

View File

@ -67,11 +67,11 @@ struct BinSearchArrayOf
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= header.nUnits)) return Null(Type);
return StructAtOffset<Type> (bytesZ, i * header.unitSize);
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
}
inline Type& operator [] (unsigned int i)
{
return StructAtOffset<Type> (bytesZ, i * header.unitSize);
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
}
inline unsigned int get_size (void) const
{ return header.static_size + header.nUnits * header.unitSize; }
@ -88,7 +88,7 @@ struct BinSearchArrayOf
* pointed to do have a simple sanitize(), ie. they do not
* reference other structs via offsets.
*/
(void) (false && StructAtOffset<Type> (bytesZ, 0).sanitize (c));
(void) (false && StructAtOffset<Type> (&bytesZ, 0).sanitize (c));
return_trace (true);
}
@ -111,7 +111,7 @@ struct BinSearchArrayOf
while (min <= max)
{
int mid = (min + max) / 2;
const Type *p = (const Type *) (((const char *) bytesZ) + (mid * size));
const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
int c = p->cmp (key);
if (c < 0)
max = mid - 1;
@ -129,12 +129,12 @@ struct BinSearchArrayOf
TRACE_SANITIZE (this);
return_trace (header.sanitize (c) &&
Type::static_size >= header.unitSize &&
c->check_array (bytesZ, header.unitSize, header.nUnits));
c->check_array (bytesZ.arrayZ, header.nUnits, header.unitSize));
}
protected:
BinSearchHeader header;
HBUINT8 bytesZ[VAR];
BinSearchHeader header;
UnsizedArrayOf<HBUINT8> bytesZ;
public:
DEFINE_SIZE_ARRAY (10, bytesZ);
};
@ -480,8 +480,8 @@ struct StateTable
while (state < num_states)
{
if (unlikely (!c->check_array (states,
states[0].static_size * nClasses,
num_states)))
num_states,
states[0].static_size * nClasses)))
return_trace (false);
{ /* Sweep new states. */
const HBUINT16 *stop = &states[num_states * nClasses];
@ -490,9 +490,7 @@ struct StateTable
state = num_states;
}
if (unlikely (!c->check_array (entries,
entries[0].static_size,
num_entries)))
if (unlikely (!c->check_array (entries, num_entries)))
return_trace (false);
{ /* Sweep new entries. */
const Entry<Extra> *stop = &entries[num_entries];

View File

@ -619,7 +619,7 @@ struct Chain
{
inline void apply (hb_aat_apply_context_t *c) const
{
const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (featureZ, featureZ[0].static_size * featureCount);
const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount);
unsigned int count = subtableCount;
for (unsigned int i = 0; i < count; i++)
{
@ -648,10 +648,10 @@ struct Chain
!c->check_range (this, length))
return_trace (false);
if (!c->check_array (featureZ, featureZ[0].static_size, featureCount))
if (!c->check_array (featureZ.arrayZ, featureCount))
return_trace (false);
const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (featureZ, featureZ[0].static_size * featureCount);
const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount);
unsigned int count = subtableCount;
for (unsigned int i = 0; i < count; i++)
{
@ -669,8 +669,8 @@ struct Chain
HBUINT32 featureCount; /* Number of feature subtable entries. */
HBUINT32 subtableCount; /* The number of subtables in the chain. */
Feature featureZ[VAR]; /* Features. */
/*ChainSubtable subtableX[VAR];*//* Subtables. */
UnsizedArrayOf<Feature> featureZ; /* Features. */
/*ChainSubtable firstSubtable;*//* Subtables. */
/*subtableGlyphCoverageArray*/ /* Only if major == 3. */
public:
@ -689,7 +689,7 @@ struct morx
inline void apply (hb_aat_apply_context_t *c) const
{
c->set_lookup_index (0);
const Chain *chain = chainsZ;
const Chain *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
@ -706,7 +706,7 @@ struct morx
!chainCount.sanitize (c))
return_trace (false);
const Chain *chain = chainsZ;
const Chain *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
@ -723,7 +723,7 @@ struct morx
* 1 for mort, 2 or 3 for morx. */
HBUINT32 chainCount; /* Number of metamorphosis chains contained in this
* table. */
Chain chainsZ[VAR]; /* Chains. */
Chain firstChain; /* Chains. */
public:
DEFINE_SIZE_MIN (8);

View File

@ -98,7 +98,7 @@ static inline void _hb_memory_barrier (void)
{
#if !defined(MemoryBarrier)
/* MinGW has a convoluted history of supporting MemoryBarrier. */
long dummy = 0;
LONG dummy = 0;
InterlockedExchange (&dummy, 1);
#else
MemoryBarrier ();
@ -106,7 +106,8 @@ static inline void _hb_memory_barrier (void)
}
#define _hb_memory_barrier() _hb_memory_barrier ()
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((unsigned *) (AI), (V))
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((LONG *) (AI), (V))
static_assert ((sizeof (LONG) == sizeof (int)), "");
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))

View File

@ -119,7 +119,7 @@ struct hb_buffer_t
/* Text before / after the main buffer contents.
* Always in Unicode, and ordered outward.
* Index 0 is for "pre-context", 1 for "post-context". */
static const unsigned int CONTEXT_LENGTH = 5;
enum { CONTEXT_LENGTH = 5 };
hb_codepoint_t context[2][CONTEXT_LENGTH];
unsigned int context_len[2];

75
src/hb-cache.hh Normal file
View File

@ -0,0 +1,75 @@
/*
* Copyright © 2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_CACHE_HH
#define HB_CACHE_HH
#include "hb.hh"
/* Implements a lock-free cache for int->int functions. */
template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
struct hb_cache_t
{
static_assert ((key_bits >= cache_bits), "");
static_assert ((key_bits + value_bits - cache_bits <= 8 * sizeof (unsigned int)), "");
inline void init (void) { clear (); }
inline void fini (void) {}
inline void clear (void)
{ memset (values, 255, sizeof (values)); }
inline bool get (unsigned int key, unsigned int *value) const
{
unsigned int k = key & ((1u<<cache_bits)-1);
unsigned int v = values[k].get_relaxed ();
if ((v >> value_bits) != (key >> cache_bits))
return false;
*value = v & ((1u<<value_bits)-1);
return true;
}
inline bool set (unsigned int key, unsigned int value)
{
if (unlikely ((key >> key_bits) || (value >> value_bits)))
return false; /* Overflows */
unsigned int k = key & ((1u<<cache_bits)-1);
unsigned int v = ((key>>cache_bits)<<value_bits) | value;
values[k].set_relaxed (v);
return true;
}
private:
hb_atomic_int_t values[1u<<cache_bits];
};
typedef hb_cache_t<21, 16, 8> hb_cmap_cache_t;
typedef hb_cache_t<16, 24, 8> hb_advance_cache_t;
#endif /* HB_CACHE_HH */

View File

@ -877,8 +877,8 @@ parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
bool has_start;
feature->start = 0;
feature->end = (unsigned int) -1;
feature->start = HB_FEATURE_GLOBAL_START;
feature->end = HB_FEATURE_GLOBAL_END;
if (!parse_char (pp, end, '['))
return true;

View File

@ -379,6 +379,19 @@ typedef void (*hb_destroy_func_t) (void *user_data);
/* Font features and variations. */
/**
* HB_FEATURE_GLOBAL_START
*
* Since: REPLACEME
*/
#define HB_FEATURE_GLOBAL_START 0
/**
* HB_FEATURE_GLOBAL_END
*
* Since: REPLACEME
*/
#define HB_FEATURE_GLOBAL_END ((unsigned int) -1)
typedef struct hb_feature_t {
hb_tag_t tag;
uint32_t value;

View File

@ -67,7 +67,10 @@ hb_options (void)
u.i = _hb_options.get_relaxed ();
if (unlikely (!u.i))
{
_hb_options_init ();
u.i = _hb_options.get_relaxed ();
}
return u.opts;
}

View File

@ -29,6 +29,8 @@
#include "hb.hh"
#include "hb-null.hh"
/* Void! For when we need a expression-type of void. */
typedef const struct _hb_void_t *hb_void_t;
@ -507,6 +509,24 @@ struct hb_auto_t : Type
void fini (void) {}
};
template <typename T>
struct hb_array_t
{
inline hb_array_t (void) : arrayZ (nullptr), len (0) {}
inline hb_array_t (const T *array_, unsigned int len_) : arrayZ (array_), len (len_) {}
inline const T& operator [] (unsigned int i) const
{
if (unlikely (i >= len)) return Null(T);
return arrayZ[i];
}
inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
const T *arrayZ;
unsigned int len;
};
struct hb_bytes_t
{
inline hb_bytes_t (void) : bytes (nullptr), len (0) {}

View File

@ -163,11 +163,12 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
return hb_blob_reference (data->blob);
const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
unsigned int base_offset;
const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
return blob;
}
@ -526,7 +527,7 @@ hb_face_get_table_tags (const hb_face_t *face,
* @face: font face.
* @out: set to add Unicode characters covered by @face to.
*
* Since: REPLACEME
* Since: 1.9.0
*/
void
hb_face_collect_unicodes (hb_face_t *face,
@ -543,7 +544,7 @@ hb_face_collect_unicodes (hb_face_t *face,
*
*
*
* Since: REPLACEME
* Since: 1.9.0
*/
void
hb_face_collect_variation_selectors (hb_face_t *face,
@ -560,7 +561,7 @@ hb_face_collect_variation_selectors (hb_face_t *face,
*
*
*
* Since: REPLACEME
* Since: 1.9.0
*/
void
hb_face_collect_variation_unicodes (hb_face_t *face,
@ -684,7 +685,7 @@ _hb_face_builder_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data
*
* Return value: (transfer full) New face.
*
* Since: REPLACEME
* Since: 1.9.0
**/
hb_face_t *
hb_face_builder_create (void)
@ -703,7 +704,7 @@ hb_face_builder_create (void)
* Add table for @tag with data provided by @blob to the face. @face must
* be created using hb_face_builder_create().
*
* Since: REPLACEME
* Since: 1.9.0
**/
hb_bool_t
hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)

View File

@ -33,6 +33,7 @@
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-cache.hh"
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
@ -68,6 +69,9 @@ struct hb_ft_font_t
int load_flags;
bool symbol; /* Whether selected cmap is symbol cmap. */
bool unref; /* Whether to destroy ft_face when done. */
mutable int cached_x_scale;
mutable hb_advance_cache_t advance_cache;
};
static hb_ft_font_t *
@ -84,6 +88,9 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
ft_font->cached_x_scale = 0;
ft_font->advance_cache.init ();
return ft_font;
}
@ -98,6 +105,8 @@ _hb_ft_font_destroy (void *data)
{
hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
ft_font->advance_cache.fini ();
if (ft_font->unref)
_hb_ft_face_destroy (ft_font->ft_face);
@ -227,6 +236,46 @@ hb_ft_get_glyph_h_advance (hb_font_t *font,
return (v + (1<<9)) >> 10;
}
static void
hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
FT_Face ft_face = ft_font->ft_face;
int load_flags = ft_font->load_flags;
int mult = font->x_scale < 0 ? -1 : +1;
if (font->x_scale != ft_font->cached_x_scale)
{
ft_font->advance_cache.clear ();
ft_font->cached_x_scale = font->x_scale;
}
for (unsigned int i = 0; i < count; i++)
{
FT_Fixed v = 0;
hb_codepoint_t glyph = *first_glyph;
unsigned int cv;
if (ft_font->advance_cache.get (glyph, &cv))
v = cv;
else
{
FT_Get_Advance (ft_face, glyph, load_flags, &v);
ft_font->advance_cache.set (glyph, v);
}
*first_advance = (v * mult + (1<<9)) >> 10;
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
}
}
static hb_position_t
hb_ft_get_glyph_v_advance (hb_font_t *font,
void *font_data,
@ -432,6 +481,7 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);

View File

@ -99,8 +99,8 @@ static inline Type& StructAfter(TObject &X)
#define DEFINE_SIZE_STATIC(size) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
static const unsigned int static_size = (size); \
static const unsigned int min_size = (size); \
enum { static_size = (size) }; \
enum { min_size = (size) }; \
inline unsigned int get_size (void) const { return (size); }
#define DEFINE_SIZE_UNION(size, _member) \
@ -114,7 +114,7 @@ static inline Type& StructAfter(TObject &X)
#define DEFINE_SIZE_ARRAY(size, array) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof (array[0])); \
DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
static const unsigned int min_size = (size); \
enum { min_size = (size) }; \
#define DEFINE_SIZE_ARRAY_SIZED(size, array) \
DEFINE_SIZE_ARRAY(size, array); \
@ -133,7 +133,7 @@ static inline Type& StructAfter(TObject &X)
template <typename Context, typename Return, unsigned int MaxDebugDepth>
struct hb_dispatch_context_t
{
static const unsigned int max_debug_depth = MaxDebugDepth;
enum { max_debug_depth = MaxDebugDepth };
typedef Return return_t;
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format) { return true; }
@ -296,7 +296,8 @@ struct hb_sanitize_context_t :
return likely (ok);
}
inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
template <typename T>
inline bool check_array (const T *base, unsigned int len, unsigned int record_size = T::static_size) const
{
const char *p = (const char *) base;
bool overflows = hb_unsigned_mul_overflows (len, record_size);

View File

@ -115,7 +115,7 @@ typedef struct OffsetTable
* table list. */
int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
if (table_index)
*table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i;
*table_index = i == -1 ? (unsigned) Index::NOT_FOUND_INDEX : (unsigned) i;
return i != -1;
}
inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
@ -300,7 +300,7 @@ struct ResourceRefItem
HBINT16 id; /* Resource ID, is really should be signed? */
HBINT16 nameOffset; /* Offset from beginning of resource name list
* to resource name, minus means there is no */
* to resource name, minus means there is none. */
HBUINT8 attr; /* Resource attributes */
HBUINT24 dataOffset; /* Offset from beginning of resource data to
* data for this resource */
@ -318,15 +318,9 @@ struct ResourceTypeItem
return_trace (likely (c->check_struct (this)));
}
inline unsigned int get_resource_count () const
{
return numRes + 1;
}
inline unsigned int get_resource_count () const { return numRes + 1; }
inline bool is_sfnt () const
{
return type == HB_TAG ('s','f','n','t');
}
inline bool is_sfnt () const { return type == HB_TAG ('s','f','n','t'); }
inline const ResourceRefItem& get_ref_item (const void *base,
unsigned int i) const
@ -335,11 +329,11 @@ struct ResourceTypeItem
}
protected:
Tag type; /* Resource type */
HBUINT16 numRes; /* Number of resource this type in map minus 1 */
Tag type; /* Resource type. */
HBUINT16 numRes; /* Number of resources minus 1. */
OffsetTo<UnsizedArrayOf<ResourceRefItem> >
refList; /* Offset from beginning of resource type list
* to reference list for this type */
* to reference item list for this type. */
public:
DEFINE_SIZE_STATIC (8);
};
@ -428,14 +422,19 @@ struct ResourceForkHeader
return StructAtOffset<LArrayOf<HBUINT8> > (this, offset);
}
inline const OpenTypeFontFace& get_face (unsigned int idx) const
inline const OpenTypeFontFace& get_face (unsigned int idx, unsigned int *base_offset = nullptr) const
{
const ResourceMap &resource_map = this+map;
for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
{
const ResourceTypeItem& type = resource_map.get_type (i);
if (type.is_sfnt () && idx < type.get_resource_count ())
return (OpenTypeFontFace&) get_data (type, idx).arrayZ;
{
const OpenTypeFontFace &face = (OpenTypeFontFace&) get_data (type, idx).arrayZ;
if (base_offset)
*base_offset = (const char *) &face - (const char *) this;
return face;
}
}
return Null (OpenTypeFontFace);
}
@ -485,7 +484,7 @@ struct OpenTypeFontFile
{
enum {
CFFTag = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
TTCTag = HB_TAG ('t','t','c','f'), /* TrueType Collection */
DFontTag = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
TrueTag = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
@ -502,12 +501,14 @@ struct OpenTypeFontFile
case Typ1Tag:
case TrueTypeTag: return 1;
case TTCTag: return u.ttcHeader.get_face_count ();
// case DFontTag: return u.rfHeader.get_face_count ();
case DFontTag: return u.rfHeader.get_face_count ();
default: return 0;
}
}
inline const OpenTypeFontFace& get_face (unsigned int i) const
inline const OpenTypeFontFace& get_face (unsigned int i, unsigned int *base_offset = nullptr) const
{
if (base_offset)
*base_offset = 0;
switch (u.tag) {
/* Note: for non-collection SFNT data we ignore index. This is because
* Apple dfont container is a container of SFNT's. So each SFNT is a
@ -517,7 +518,7 @@ struct OpenTypeFontFile
case Typ1Tag:
case TrueTypeTag: return u.fontFace;
case TTCTag: return u.ttcHeader.get_face (i);
// case DFontTag: return u.rfHeader.get_face (i);
case DFontTag: return u.rfHeader.get_face (i, base_offset);
default: return Null(OpenTypeFontFace);
}
}
@ -544,7 +545,7 @@ struct OpenTypeFontFile
case Typ1Tag:
case TrueTypeTag: return_trace (u.fontFace.sanitize (c));
case TTCTag: return_trace (u.ttcHeader.sanitize (c));
// case DFontTag: return_trace (u.rfHeader.sanitize (c));
case DFontTag: return_trace (u.rfHeader.sanitize (c));
default: return_trace (true);
}
}

View File

@ -150,7 +150,7 @@ typedef HBUINT16 NameID;
/* Script/language-system/feature index */
struct Index : HBUINT16 {
static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
enum { NOT_FOUND_INDEX = 0xFFFFu };
};
DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
@ -299,7 +299,6 @@ static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset)
* Array Types
*/
/* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */
template <typename Type>
struct UnsizedArrayOf
{
@ -345,11 +344,11 @@ struct UnsizedArrayOf
inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count));
return_trace (c->check_array (arrayZ, count));
}
public:
Type arrayZ[VAR];
Type arrayZ[VAR];
public:
DEFINE_SIZE_ARRAY (0, arrayZ);
};
@ -487,12 +486,12 @@ struct ArrayOf
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (len.sanitize (c) && c->check_array (arrayZ, Type::static_size, len));
return_trace (len.sanitize (c) && c->check_array (arrayZ, len));
}
public:
LenType len;
Type arrayZ[VAR];
LenType len;
Type arrayZ[VAR];
public:
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
@ -596,12 +595,12 @@ struct HeadlessArrayOf
{
TRACE_SANITIZE (this);
return_trace (len.sanitize (c) &&
(!len || c->check_array (arrayZ, Type::static_size, len - 1)));
(!len || c->check_array (arrayZ, len - 1)));
}
public:
LenType len;
Type arrayZ[VAR];
LenType len;
Type arrayZ[VAR];
public:
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};

View File

@ -231,7 +231,7 @@ struct CmapSubtableFormat4
inline void init (const CmapSubtableFormat4 *subtable)
{
segCount = subtable->segCountX2 / 2;
endCount = subtable->values;
endCount = subtable->values.arrayZ;
startCount = endCount + segCount + 1;
idDelta = startCount + segCount;
idRangeOffset = idDelta + segCount;
@ -369,7 +369,8 @@ struct CmapSubtableFormat4
HBUINT16 entrySelector; /* log2(searchRange/2) */
HBUINT16 rangeShift; /* 2 x segCount - searchRange */
HBUINT16 values[VAR];
UnsizedArrayOf<HBUINT16>
values;
#if 0
HBUINT16 endCount[segCount]; /* End characterCode for each segment,
* last=0xFFFFu. */
@ -377,7 +378,8 @@ struct CmapSubtableFormat4
HBUINT16 startCount[segCount]; /* Start character code for each segment. */
HBINT16 idDelta[segCount]; /* Delta for all character codes in segment. */
HBUINT16 idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
HBUINT16 glyphIdArray[VAR]; /* Glyph index array (arbitrary length) */
UnsizedArrayOf<HBUINT16>
glyphIdArray; /* Glyph index array (arbitrary length) */
#endif
public:

View File

@ -128,7 +128,7 @@ struct IndexSubtableFormat1Or3
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
c->check_array (offsetArrayZ.arrayZ, glyph_count + 1));
}
bool get_image_data (unsigned int idx,
@ -144,7 +144,8 @@ struct IndexSubtableFormat1Or3
}
IndexSubtableHeader header;
Offset<OffsetType> offsetArrayZ[VAR];
UnsizedArrayOf<Offset<OffsetType> >
offsetArrayZ;
public:
DEFINE_SIZE_ARRAY(8, offsetArrayZ);
};
@ -240,7 +241,7 @@ struct IndexSubtableArray
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count)))
if (unlikely (!c->check_array (indexSubtablesZ.arrayZ, count)))
return_trace (false);
for (unsigned int i = 0; i < count; i++)
if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
@ -255,15 +256,14 @@ struct IndexSubtableArray
{
unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex)
return &indexSubtablesZ[i];
}
}
return nullptr;
}
protected:
IndexSubtableRecord indexSubtablesZ[VAR];
UnsizedArrayOf<IndexSubtableRecord> indexSubtablesZ;
public:
DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
};
@ -527,8 +527,8 @@ struct CBDT
protected:
FixedVersion<> version;
HBUINT8 dataZ[VAR];
FixedVersion<> version;
UnsizedArrayOf<HBUINT8> dataZ;
public:
DEFINE_SIZE_ARRAY(4, dataZ);
};

View File

@ -48,10 +48,9 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
return ot_font->cmap.get_relaxed()->get_nominal_glyph (unicode, glyph);
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
return ot_face->cmap.get_relaxed()->get_nominal_glyph (unicode, glyph);
}
static hb_bool_t
@ -62,8 +61,8 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
return ot_font->cmap.get_relaxed ()->get_variation_glyph (unicode, variation_selector, glyph);
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
return ot_face->cmap.get_relaxed ()->get_variation_glyph (unicode, variation_selector, glyph);
}
static hb_position_t
@ -72,8 +71,28 @@ hb_ot_get_glyph_h_advance (hb_font_t *font,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
return font->em_scale_x (ot_font->hmtx.get_relaxed ()->get_advance (glyph, font));
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
return font->em_scale_x (ot_face->hmtx.get_relaxed ()->get_advance (glyph, font));
}
static void
hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx.get_relaxed ();
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font));
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
}
}
static hb_position_t
@ -82,8 +101,28 @@ hb_ot_get_glyph_v_advance (hb_font_t *font,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
return font->em_scale_y (-(int) ot_font->vmtx.get_relaxed ()->get_advance (glyph, font));
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
return font->em_scale_y (-(int) ot_face->vmtx.get_relaxed ()->get_advance (glyph, font));
}
static void
hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx.get_relaxed ();
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
}
}
static hb_position_t
@ -93,8 +132,8 @@ hb_ot_get_glyph_h_kerning (hb_font_t *font,
hb_codepoint_t right_glyph,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph));
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
return font->em_scale_x (ot_face->kern->get_h_kerning (left_glyph, right_glyph));
}
static hb_bool_t
@ -104,10 +143,10 @@ hb_ot_get_glyph_extents (hb_font_t *font,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
bool ret = ot_font->glyf->get_extents (glyph, extents);
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
bool ret = ot_face->glyf->get_extents (glyph, extents);
if (!ret)
ret = ot_font->CBDT->get_extents (glyph, extents);
ret = ot_face->CBDT->get_extents (glyph, extents);
// TODO Hook up side-bearings variations.
extents->x_bearing = font->em_scale_x (extents->x_bearing);
extents->y_bearing = font->em_scale_y (extents->y_bearing);
@ -123,8 +162,8 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
char *name, unsigned int size,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
return ot_font->post->get_glyph_name (glyph, name, size);
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
return ot_face->post->get_glyph_name (glyph, name, size);
}
static hb_bool_t
@ -134,8 +173,8 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
return ot_font->post->get_glyph_from_name (name, len, glyph);
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
return ot_face->post->get_glyph_from_name (name, len, glyph);
}
static hb_bool_t
@ -144,12 +183,12 @@ hb_ot_get_font_h_extents (hb_font_t *font,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
metrics->ascender = font->em_scale_y (ot_font->hmtx.get_relaxed ()->ascender);
metrics->descender = font->em_scale_y (ot_font->hmtx.get_relaxed ()->descender);
metrics->line_gap = font->em_scale_y (ot_font->hmtx.get_relaxed ()->line_gap);
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
metrics->ascender = font->em_scale_y (ot_face->hmtx.get_relaxed ()->ascender);
metrics->descender = font->em_scale_y (ot_face->hmtx.get_relaxed ()->descender);
metrics->line_gap = font->em_scale_y (ot_face->hmtx.get_relaxed ()->line_gap);
// TODO Hook up variations.
return ot_font->hmtx.get_relaxed ()->has_font_extents;
return ot_face->hmtx.get_relaxed ()->has_font_extents;
}
static hb_bool_t
@ -158,19 +197,19 @@ hb_ot_get_font_v_extents (hb_font_t *font,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data;
metrics->ascender = font->em_scale_x (ot_font->vmtx.get_relaxed ()->ascender);
metrics->descender = font->em_scale_x (ot_font->vmtx.get_relaxed ()->descender);
metrics->line_gap = font->em_scale_x (ot_font->vmtx.get_relaxed ()->line_gap);
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
metrics->ascender = font->em_scale_x (ot_face->vmtx.get_relaxed ()->ascender);
metrics->descender = font->em_scale_x (ot_face->vmtx.get_relaxed ()->descender);
metrics->line_gap = font->em_scale_x (ot_face->vmtx.get_relaxed ()->line_gap);
// TODO Hook up variations.
return ot_font->vmtx.get_relaxed ()->has_font_extents;
return ot_face->vmtx.get_relaxed ()->has_font_extents;
}
#ifdef HB_USE_ATEXIT
static void free_static_ot_funcs (void);
#endif
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
static struct hb_ot_face_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_face_funcs_lazy_loader_t>
{
static inline hb_font_funcs_t *create (void)
{
@ -181,7 +220,9 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr);
hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
//hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr);
@ -225,15 +266,15 @@ void
hb_ot_font_set_funcs (hb_font_t *font)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (font->face))) return;
hb_ot_face_data_t *ot_font = hb_ot_face_data (font->face);
hb_ot_face_data_t *ot_face = hb_ot_face_data (font->face);
/* Load them lazies. We access them with get_relaxed() for performance. */
ot_font->cmap.get ();
ot_font->hmtx.get ();
ot_font->vmtx.get ();
ot_face->cmap.get ();
ot_face->hmtx.get ();
ot_face->vmtx.get ();
hb_font_set_funcs (font,
_hb_ot_get_font_funcs (),
ot_font,
ot_face,
nullptr);
}

View File

@ -54,7 +54,7 @@ struct loca
}
protected:
HBUINT8 dataZ[VAR]; /* Location data. */
UnsizedArrayOf<HBUINT8> dataZ; /* Location data. */
DEFINE_SIZE_ARRAY (0, dataZ);
};
@ -375,13 +375,13 @@ struct glyf
if (short_offset)
{
const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ;
const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
*start_offset = 2 * offsets[glyph];
*end_offset = 2 * offsets[glyph + 1];
}
else
{
const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ;
const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
*start_offset = offsets[glyph];
*end_offset = offsets[glyph + 1];
@ -418,7 +418,7 @@ struct glyf
} while (composite_it.move_to_next());
if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
*instruction_start = ((char *) last - (char *) glyf_table->dataZ) + last->get_size();
*instruction_start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size();
else
*instruction_start = end_offset;
*instruction_end = end_offset;
@ -483,7 +483,7 @@ struct glyf
};
protected:
HBUINT8 dataZ[VAR]; /* Glyphs data. */
UnsizedArrayOf<HBUINT8> dataZ; /* Glyphs data. */
DEFINE_SIZE_ARRAY (0, dataZ);
};

View File

@ -66,7 +66,7 @@ struct DeviceRecord
if (unlikely (i >= len())) return nullptr;
hb_codepoint_t gid = this->subset_plan->glyphs [i];
const HBUINT8* width = &(this->source_device_record->widths[gid]);
const HBUINT8* width = &(this->source_device_record->widthsZ[gid]);
if (width < ((const HBUINT8 *) this->source_device_record) + size_device_record)
return width;
@ -77,11 +77,7 @@ struct DeviceRecord
static inline unsigned int get_size (unsigned int count)
{
unsigned int raw_size = min_size + count * HBUINT8::static_size;
if (raw_size % 4)
/* Align to 32 bits */
return raw_size + (4 - (raw_size % 4));
return raw_size;
return hb_ceil_to_4 (min_size + count * HBUINT8::static_size);
}
inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
@ -107,7 +103,7 @@ struct DeviceRecord
DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
return_trace (false);
}
widths[i].set (*width);
widthsZ[i].set (*width);
}
return_trace (true);
@ -120,11 +116,11 @@ struct DeviceRecord
c->check_range (this, size_device_record)));
}
HBUINT8 pixel_size; /* Pixel size for following widths (as ppem). */
HBUINT8 max_width; /* Maximum width. */
HBUINT8 widths[VAR]; /* Array of widths (numGlyphs is from the 'maxp' table). */
HBUINT8 pixel_size; /* Pixel size for following widths (as ppem). */
HBUINT8 max_width; /* Maximum width. */
UnsizedArrayOf<HBUINT8> widthsZ; /* Array of widths (numGlyphs is from the 'maxp' table). */
public:
DEFINE_SIZE_ARRAY (2, widths);
DEFINE_SIZE_ARRAY (2, widthsZ);
};
@ -140,7 +136,7 @@ struct hdmx
inline const DeviceRecord& operator [] (unsigned int i) const
{
if (unlikely (i >= num_records)) return Null(DeviceRecord);
return StructAtOffset<DeviceRecord> (this->data, i * size_device_record);
return StructAtOffset<DeviceRecord> (&this->dataZ, i * size_device_record);
}
inline bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
@ -211,12 +207,12 @@ struct hdmx
}
protected:
HBUINT16 version; /* Table version number (0) */
HBUINT16 num_records; /* Number of device records. */
HBUINT32 size_device_record; /* Size of a device record, 32-bit aligned. */
HBUINT8 data[VAR]; /* Array of device records. */
HBUINT16 version; /* Table version number (0) */
HBUINT16 num_records; /* Number of device records. */
HBUINT32 size_device_record; /* Size of a device record, 32-bit aligned. */
UnsizedArrayOf<HBUINT8> dataZ; /* Array of device records. */
public:
DEFINE_SIZE_ARRAY (8, data);
DEFINE_SIZE_ARRAY (8, dataZ);
};
} /* namespace OT */

View File

@ -262,7 +262,7 @@ struct hmtxvmtx
return default_advance;
}
return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance;
return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance;
}
inline unsigned int get_advance (hb_codepoint_t glyph,
@ -295,7 +295,7 @@ struct hmtxvmtx
};
protected:
LongMetric longMetric[VAR]; /* Paired advance width and leading
UnsizedArrayOf<LongMetric>longMetricZ;/* Paired advance width and leading
* bearing values for each glyph. The
* value numOfHMetrics comes from
* the 'hhea' table. If the font is
@ -303,7 +303,7 @@ struct hmtxvmtx
* be in the array, but that entry is
* required. The last entry applies to
* all subsequent glyphs. */
/*FWORD leadingBearingX[VAR];*/ /* Here the advance is assumed
/*UnsizedArrayOf<FWORD> leadingBearingX;*//* Here the advance is assumed
* to be the same as the advance
* for the last entry above. The
* number of entries in this array is
@ -317,7 +317,7 @@ struct hmtxvmtx
* font to vary the side bearing
* values for each glyph. */
public:
DEFINE_SIZE_ARRAY (0, longMetric);
DEFINE_SIZE_ARRAY (0, longMetricZ);
};
struct hmtx : hmtxvmtx<hmtx, hhea> {

View File

@ -208,7 +208,7 @@ struct KernSubTableWrapper
TRACE_SANITIZE (this);
return_trace (c->check_struct (thiz()) &&
thiz()->length >= T::min_size &&
c->check_array (thiz(), 1, thiz()->length) &&
c->check_array (thiz(), thiz()->length, 1) &&
thiz()->subtable.sanitize (c, thiz()->format));
}
};
@ -222,7 +222,7 @@ struct KernTable
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
{
int v = 0;
const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (&thiz()->dataZ);
unsigned int count = thiz()->nTables;
for (unsigned int i = 0; i < count; i++)
{
@ -241,7 +241,7 @@ struct KernTable
thiz()->version != T::VERSION))
return_trace (false);
const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (&thiz()->dataZ);
unsigned int count = thiz()->nTables;
for (unsigned int i = 0; i < count; i++)
{
@ -287,11 +287,11 @@ struct KernOT : KernTable<KernOT>
};
protected:
HBUINT16 version; /* Version--0x0000u */
HBUINT16 nTables; /* Number of subtables in the kerning table. */
HBUINT8 data[VAR];
HBUINT16 version; /* Version--0x0000u */
HBUINT16 nTables; /* Number of subtables in the kerning table. */
UnsizedArrayOf<HBUINT8> dataZ;
public:
DEFINE_SIZE_ARRAY (4, data);
DEFINE_SIZE_ARRAY (4, dataZ);
};
struct KernAAT : KernTable<KernAAT>
@ -327,11 +327,11 @@ struct KernAAT : KernTable<KernAAT>
};
protected:
HBUINT32 version; /* Version--0x00010000u */
HBUINT32 nTables; /* Number of subtables in the kerning table. */
HBUINT8 data[VAR];
HBUINT32 version; /* Version--0x00010000u */
HBUINT32 nTables; /* Number of subtables in the kerning table. */
UnsizedArrayOf<HBUINT8> dataZ;
public:
DEFINE_SIZE_ARRAY (8, data);
DEFINE_SIZE_ARRAY (8, dataZ);
};
struct kern

View File

@ -1545,14 +1545,14 @@ struct VarData
regionIndices.sanitize(c) &&
shortCount <= regionIndices.len &&
c->check_array (&StructAfter<HBUINT8> (regionIndices),
get_row_size (), itemCount));
itemCount, get_row_size ()));
}
protected:
HBUINT16 itemCount;
HBUINT16 shortCount;
ArrayOf<HBUINT16> regionIndices;
HBUINT8 bytesX[VAR];
UnsizedArrayOf<HBUINT8>bytesX;
public:
DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
};
@ -1749,7 +1749,7 @@ struct FeatureVariationRecord
struct FeatureVariations
{
static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu;
enum { NOT_FOUND_INDEX = 0xFFFFFFFFu };
inline bool find_index (const int *coords, unsigned int coord_len,
unsigned int *index) const
@ -1850,7 +1850,7 @@ struct HintingDevice
unsigned int s = ppem_size - startSize;
unsigned int byte = deltaValue[s >> (4 - f)];
unsigned int byte = deltaValueZ[s >> (4 - f)];
unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
@ -1870,9 +1870,10 @@ struct HintingDevice
* 2 Signed 4-bit value, 4 values per uint16
* 3 Signed 8-bit value, 2 values per uint16
*/
HBUINT16 deltaValue[VAR]; /* Array of compressed data */
UnsizedArrayOf<HBUINT16>
deltaValueZ; /* Array of compressed data */
public:
DEFINE_SIZE_ARRAY (6, deltaValue);
DEFINE_SIZE_ARRAY (6, deltaValueZ);
};
struct VariationDevice

View File

@ -199,7 +199,7 @@ struct ValueFormat : HBUINT16
TRACE_SANITIZE (this);
unsigned int len = get_len ();
if (!c->check_array (values, get_size (), count)) return_trace (false);
if (!c->check_array (values, count, get_size ())) return_trace (false);
if (!has_device ()) return_trace (true);
@ -376,7 +376,7 @@ struct AnchorMatrix
if (!c->check_struct (this)) return_trace (false);
if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
unsigned int count = rows * cols;
if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
for (unsigned int i = 0; i < count; i++)
if (!matrixZ[i].sanitize (c, this)) return_trace (false);
return_trace (true);
@ -384,8 +384,8 @@ struct AnchorMatrix
HBUINT16 rows; /* Number of rows */
protected:
OffsetTo<Anchor>
matrixZ[VAR]; /* Matrix of offsets to Anchor tables--
UnsizedArrayOf<OffsetTo<Anchor> >
matrixZ; /* Matrix of offsets to Anchor tables--
* from beginning of AnchorMatrix table */
public:
DEFINE_SIZE_ARRAY (2, matrixZ);
@ -621,7 +621,7 @@ struct PairSet
unsigned int len2 = valueFormats[1].get_len ();
unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
const PairValueRecord *record = &firstPairValueRecord;
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
{
@ -640,7 +640,7 @@ struct PairSet
unsigned int len2 = valueFormats[1].get_len ();
unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
const PairValueRecord *record = &firstPairValueRecord;
c->input->add_array (&record->secondGlyph, len, record_size);
}
@ -654,7 +654,6 @@ struct PairSet
unsigned int len2 = valueFormats[1].get_len ();
unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
unsigned int count = len;
/* Hand-coded bsearch. */
@ -665,7 +664,7 @@ struct PairSet
while (min <= max)
{
int mid = (min + max) / 2;
const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
const PairValueRecord *record = &StructAtOffset<PairValueRecord> (&firstPairValueRecord, record_size * mid);
hb_codepoint_t mid_x = record->secondGlyph;
if (x < mid_x)
max = mid - 1;
@ -698,20 +697,21 @@ struct PairSet
{
TRACE_SANITIZE (this);
if (!(c->check_struct (this)
&& c->check_array (arrayZ, HBUINT16::static_size * closure->stride, len))) return_trace (false);
&& c->check_array (&firstPairValueRecord, len, HBUINT16::static_size * closure->stride))) return_trace (false);
unsigned int count = len;
const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
const PairValueRecord *record = &firstPairValueRecord;
return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
}
protected:
HBUINT16 len; /* Number of PairValueRecords */
HBUINT16 arrayZ[VAR]; /* Array of PairValueRecords--ordered
* by GlyphID of the second glyph */
HBUINT16 len; /* Number of PairValueRecords */
PairValueRecord firstPairValueRecord;
/* Array of PairValueRecords--ordered
* by GlyphID of the second glyph */
public:
DEFINE_SIZE_ARRAY (2, arrayZ);
DEFINE_SIZE_MIN (2);
};
struct PairPosFormat1
@ -869,7 +869,7 @@ struct PairPosFormat2
unsigned int stride = len1 + len2;
unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
return_trace (c->check_array (values, record_size, count) &&
return_trace (c->check_array (values, count, record_size) &&
valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
}

View File

@ -541,6 +541,10 @@ struct AlternateSet
unsigned int shift = hb_ctz (lookup_mask);
unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
/* If alt_index is MAX, randomize feature if it is the rand feature. */
if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
alt_index = c->random_number () % count + 1;
if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
c->replace_glyph (alternates[alt_index - 1]);

View File

@ -33,6 +33,7 @@
#include "hb-buffer.hh"
#include "hb-map.hh"
#include "hb-set.hh"
#include "hb-ot-map.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-layout-gdef-table.hh"
@ -478,9 +479,12 @@ struct hb_ot_apply_context_t :
unsigned int nesting_level_left;
unsigned int debug_depth;
bool has_glyph_classes;
bool auto_zwnj;
bool auto_zwj;
bool has_glyph_classes;
bool random;
uint32_t random_state;
hb_ot_apply_context_t (unsigned int table_index_,
@ -498,13 +502,16 @@ struct hb_ot_apply_context_t :
lookup_props (0),
nesting_level_left (HB_MAX_NESTING_LEVEL),
debug_depth (0),
has_glyph_classes (gdef.has_glyph_classes ()),
auto_zwnj (true),
auto_zwj (true),
has_glyph_classes (gdef.has_glyph_classes ()) {}
random (false),
random_state (1) {}
inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; }
inline void set_random (bool random_) { random = random_; }
inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
inline void set_lookup_props (unsigned int lookup_props_)
@ -514,6 +521,13 @@ struct hb_ot_apply_context_t :
iter_context.init (this, true);
}
inline uint32_t random_number (void)
{
/* http://www.cplusplus.com/reference/random/minstd_rand/ */
random_state = random_state * 48271 % 2147483647;
return random_state;
}
inline bool
match_properties_mark (hb_codepoint_t glyph,
unsigned int glyph_props,
@ -1222,42 +1236,42 @@ struct Rule
inline bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
{
return context_intersects (glyphs,
inputCount, inputZ,
inputCount, inputZ.arrayZ,
lookup_context);
}
inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
{
TRACE_CLOSURE (this);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAtOffset<UnsizedArrayOf<LookupRecord> > (inputZ.arrayZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
context_closure_lookup (c,
inputCount, inputZ,
lookupCount, lookupRecord,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
lookup_context);
}
inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
{
TRACE_COLLECT_GLYPHS (this);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAtOffset<UnsizedArrayOf<LookupRecord> > (inputZ.arrayZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
context_collect_glyphs_lookup (c,
inputCount, inputZ,
lookupCount, lookupRecord,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
lookup_context);
}
inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
{
TRACE_WOULD_APPLY (this);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAtOffset<UnsizedArrayOf<LookupRecord> > (inputZ.arrayZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
return_trace (context_would_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
}
inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAtOffset<UnsizedArrayOf<LookupRecord> > (inputZ.arrayZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
}
public:
@ -1266,8 +1280,8 @@ struct Rule
TRACE_SANITIZE (this);
return_trace (inputCount.sanitize (c) &&
lookupCount.sanitize (c) &&
c->check_range (inputZ,
inputZ[0].static_size * inputCount +
c->check_range (inputZ.arrayZ,
inputZ[0].static_size * (inputCount ? inputCount - 1 : 0) +
LookupRecord::static_size * lookupCount));
}
@ -1276,9 +1290,11 @@ struct Rule
* glyph sequence--includes the first
* glyph */
HBUINT16 lookupCount; /* Number of LookupRecords */
HBUINT16 inputZ[VAR]; /* Array of match inputs--start with
UnsizedArrayOf<HBUINT16>
inputZ; /* Array of match inputs--start with
* second glyph */
/*LookupRecord lookupRecordX[VAR];*/ /* Array of LookupRecords--in
/*UnsizedArrayOf<LookupRecord>
lookupRecordX;*/ /* Array of LookupRecords--in
* design order */
public:
DEFINE_SIZE_ARRAY (4, inputZ);
@ -1595,7 +1611,7 @@ struct ContextFormat3
this
};
return context_intersects (glyphs,
glyphCount, (const HBUINT16 *) (coverageZ + 1),
glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
lookup_context);
}
@ -1605,13 +1621,13 @@ struct ContextFormat3
if (!(this+coverageZ[0]).intersects (c->glyphs))
return;
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ.arrayZ, coverageZ[0].static_size * glyphCount);
struct ContextClosureLookupContext lookup_context = {
{intersects_coverage},
this
};
context_closure_lookup (c,
glyphCount, (const HBUINT16 *) (coverageZ + 1),
glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
lookupCount, lookupRecord,
lookup_context);
}
@ -1621,14 +1637,14 @@ struct ContextFormat3
TRACE_COLLECT_GLYPHS (this);
(this+coverageZ[0]).add_coverage (c->input);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ.arrayZ, coverageZ[0].static_size * glyphCount);
struct ContextCollectGlyphsLookupContext lookup_context = {
{collect_coverage},
this
};
context_collect_glyphs_lookup (c,
glyphCount, (const HBUINT16 *) (coverageZ + 1),
glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
lookupCount, lookupRecord,
lookup_context);
}
@ -1637,12 +1653,12 @@ struct ContextFormat3
{
TRACE_WOULD_APPLY (this);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ.arrayZ, coverageZ[0].static_size * glyphCount);
struct ContextApplyLookupContext lookup_context = {
{match_coverage},
this
};
return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
}
inline const Coverage &get_coverage (void) const
@ -1654,12 +1670,12 @@ struct ContextFormat3
unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ.arrayZ, coverageZ[0].static_size * glyphCount);
struct ContextApplyLookupContext lookup_context = {
{match_coverage},
this
};
return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
}
inline bool subset (hb_subset_context_t *c) const
@ -1675,11 +1691,11 @@ struct ContextFormat3
if (!c->check_struct (this)) return_trace (false);
unsigned int count = glyphCount;
if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false);
if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false);
for (unsigned int i = 0; i < count; i++)
if (!coverageZ[i].sanitize (c, this)) return_trace (false);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ.arrayZ, coverageZ[0].static_size * count);
return_trace (c->check_array (lookupRecord, lookupCount));
}
protected:
@ -1687,10 +1703,11 @@ struct ContextFormat3
HBUINT16 glyphCount; /* Number of glyphs in the input glyph
* sequence */
HBUINT16 lookupCount; /* Number of LookupRecords */
OffsetTo<Coverage>
coverageZ[VAR]; /* Array of offsets to Coverage
UnsizedArrayOf<OffsetTo<Coverage> >
coverageZ; /* Array of offsets to Coverage
* table in glyph sequence order */
/*LookupRecord lookupRecordX[VAR];*/ /* Array of LookupRecords--in
/*UnsizedArrayOf<LookupRecord>
lookupRecordX;*/ /* Array of LookupRecords--in
* design order */
public:
DEFINE_SIZE_ARRAY (6, coverageZ);

View File

@ -1068,7 +1068,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
struct GSUBProxy
{
static const unsigned int table_index = 0;
enum { table_index = 0 };
static const bool inplace = false;
typedef OT::SubstLookup Lookup;
@ -1082,7 +1082,7 @@ struct GSUBProxy
struct GPOSProxy
{
static const unsigned int table_index = 1;
enum { table_index = 1 };
static const bool inplace = true;
typedef OT::PosLookup Lookup;
@ -1268,6 +1268,11 @@ 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 ();
}
apply_string<Proxy> (&c,
proxy.table.get_lookup (lookup_index),
proxy.accels[lookup_index]);

View File

@ -95,7 +95,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
unsigned int variations_index,
hb_mask_t mask,
bool auto_zwnj,
bool auto_zwj)
bool auto_zwj,
bool random)
{
unsigned int lookup_indices[32];
unsigned int offset, len;
@ -122,6 +123,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
lookup->index = lookup_indices[i];
lookup->auto_zwnj = auto_zwnj;
lookup->auto_zwj = auto_zwj;
lookup->random = random;
}
offset += len;
@ -208,8 +210,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
/* Uses the global bit */
bits_needed = 0;
else
/* Limit to 8 bits per feature. */
bits_needed = MIN(8u, hb_bit_storage (info->max_value));
/* Limit bits per feature. */
bits_needed = 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))
continue; /* Feature disabled, or not enough bits. */
@ -252,6 +254,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
map->stage[1] = info->stage[1];
map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ);
map->auto_zwj = !(info->flags & F_MANUAL_ZWJ);
map->random = !!(info->flags & F_RANDOM);
if ((info->flags & F_GLOBAL) && info->max_value == 1) {
/* Uses the global bit */
map->shift = global_bit_shift;
@ -301,7 +304,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
variations_index,
m.features[i].mask,
m.features[i].auto_zwnj,
m.features[i].auto_zwj);
m.features[i].auto_zwj,
m.features[i].random);
/* Sort lookups and merge duplicates */
if (last_num_lookups < m.lookups[table_index].len)

View File

@ -32,6 +32,9 @@
#include "hb-buffer.hh"
#define HB_OT_MAP_MAX_BITS 8u
#define HB_OT_MAP_MAX_VALUE ((1u << HB_OT_MAP_MAX_BITS) - 1u)
struct hb_ot_shape_plan_t;
static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
@ -52,6 +55,7 @@ struct hb_ot_map_t
unsigned int needs_fallback : 1;
unsigned int auto_zwnj : 1;
unsigned int auto_zwj : 1;
unsigned int random : 1;
inline int cmp (const hb_tag_t *tag_) const
{ return *tag_ < tag ? -1 : *tag_ > tag ? 1 : 0; }
@ -61,6 +65,7 @@ struct hb_ot_map_t
unsigned short index;
unsigned short auto_zwnj : 1;
unsigned short auto_zwj : 1;
unsigned short random : 1;
hb_mask_t mask;
static int cmp (const void *pa, const void *pb)
@ -167,7 +172,8 @@ enum hb_ot_map_feature_flags_t {
F_HAS_FALLBACK = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
F_MANUAL_ZWNJ = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
F_MANUAL_ZWJ = 0x0008u, /* Don't skip over ZWJ when matching **input**. */
F_GLOBAL_SEARCH = 0x0010u /* If feature not found in LangSys, look for it in global feature list and pick one. */
F_GLOBAL_SEARCH = 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */
F_RANDOM = 0x0020u /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
};
HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
/* Macro version for where const is desired. */
@ -206,7 +212,8 @@ struct hb_ot_map_builder_t
unsigned int variations_index,
hb_mask_t mask,
bool auto_zwnj = true,
bool auto_zwj = true);
bool auto_zwj = true,
bool random = false);
struct feature_info_t {
hb_tag_t tag;

View File

@ -234,7 +234,7 @@ struct MathKern
TRACE_SANITIZE (this);
unsigned int count = 2 * heightCount + 1;
for (unsigned int i = 0; i < count; i++)
if (!mathValueRecords[i].sanitize (c, this)) return_trace (false);
if (!mathValueRecordsZ.arrayZ[i].sanitize (c, this)) return_trace (false);
return_trace (true);
}
@ -242,16 +242,14 @@ struct MathKern
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
c->check_array (mathValueRecords,
mathValueRecords[0].static_size,
2 * heightCount + 1) &&
c->check_array (mathValueRecordsZ.arrayZ, 2 * heightCount + 1) &&
sanitize_math_value_records (c));
}
inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
{
const MathValueRecord* correctionHeight = mathValueRecords;
const MathValueRecord* kernValue = mathValueRecords + heightCount;
const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ;
const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
int sign = font->y_scale < 0 ? -1 : +1;
/* The description of the MathKern table is a ambiguous, but interpreting
@ -279,18 +277,19 @@ struct MathKern
}
protected:
HBUINT16 heightCount;
MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
* which the kern value changes.
* Sorted by the height value in
* design units (heightCount entries),
* Followed by:
* Array of kern values corresponding
* to heights. (heightCount+1 entries).
*/
HBUINT16 heightCount;
UnsizedArrayOf<MathValueRecord>
mathValueRecordsZ; /* Array of correction heights at
* which the kern value changes.
* Sorted by the height value in
* design units (heightCount entries),
* Followed by:
* Array of kern values corresponding
* to heights. (heightCount+1 entries).
*/
public:
DEFINE_SIZE_ARRAY (2, mathValueRecords);
DEFINE_SIZE_ARRAY (2, mathValueRecordsZ);
};
struct MathKernInfoRecord
@ -588,7 +587,7 @@ struct MathVariants
TRACE_SANITIZE (this);
unsigned int count = vertGlyphCount + horizGlyphCount;
for (unsigned int i = 0; i < count; i++)
if (!glyphConstruction[i].sanitize (c, this)) return_trace (false);
if (!glyphConstruction.arrayZ[i].sanitize (c, this)) return_trace (false);
return_trace (true);
}
@ -598,9 +597,7 @@ struct MathVariants
return_trace (c->check_struct (this) &&
vertGlyphCoverage.sanitize (c, this) &&
horizGlyphCoverage.sanitize (c, this) &&
c->check_array (glyphConstruction,
glyphConstruction[0].static_size,
vertGlyphCount + horizGlyphCount) &&
c->check_array (glyphConstruction.arrayZ, vertGlyphCount + horizGlyphCount) &&
sanitize_offsets (c));
}
@ -670,7 +667,8 @@ struct MathVariants
/* Array of offsets to MathGlyphConstruction tables - from the beginning of
the MathVariants table, for shapes growing in vertical/horizontal
direction. */
OffsetTo<MathGlyphConstruction> glyphConstruction[VAR];
UnsizedArrayOf<OffsetTo<MathGlyphConstruction> >
glyphConstruction;
public:
DEFINE_SIZE_ARRAY (10, glyphConstruction);

View File

@ -136,7 +136,7 @@ struct maxp
FixedVersion<>version; /* Version of the maxp table (0.5 or 1.0),
* 0x00005000u or 0x00010000u. */
HBUINT16 numGlyphs; /* The number of glyphs in the font. */
/*maxpV1Tail v1Tail[VAR]; */
/*maxpV1Tail v1Tail[VAR]; */
public:
DEFINE_SIZE_STATIC (6);
};

View File

@ -91,7 +91,7 @@ struct name
key.encodingID.set (encoding_id);
key.languageID.set (language_id);
key.nameID.set (name_id);
NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), NameRecord::cmp);
NameRecord *match = (NameRecord *) bsearch (&key, nameRecordZ.arrayZ, count, sizeof (nameRecordZ[0]), NameRecord::cmp);
if (!match)
return 0;
@ -102,14 +102,14 @@ struct name
}
inline unsigned int get_size (void) const
{ return min_size + count * nameRecord[0].min_size; }
{ return min_size + count * nameRecordZ[0].min_size; }
inline bool sanitize_records (hb_sanitize_context_t *c) const {
TRACE_SANITIZE (this);
char *string_pool = (char *) this + stringOffset;
unsigned int _count = count;
for (unsigned int i = 0; i < _count; i++)
if (!nameRecord[i].sanitize (c, string_pool)) return_trace (false);
if (!nameRecordZ[i].sanitize (c, string_pool)) return_trace (false);
return_trace (true);
}
@ -118,7 +118,7 @@ struct name
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
likely (format == 0 || format == 1) &&
c->check_array (nameRecord, nameRecord[0].static_size, count) &&
c->check_array (nameRecordZ.arrayZ, count) &&
sanitize_records (c));
}
@ -126,9 +126,10 @@ struct name
HBUINT16 format; /* Format selector (=0/1). */
HBUINT16 count; /* Number of name records. */
Offset16 stringOffset; /* Offset to start of string storage (from start of table). */
NameRecord nameRecord[VAR]; /* The name records where count is the number of records. */
UnsizedArrayOf<NameRecord>
nameRecordZ; /* The name records where count is the number of records. */
public:
DEFINE_SIZE_ARRAY (6, nameRecord);
DEFINE_SIZE_ARRAY (6, nameRecordZ);
};

View File

@ -55,10 +55,11 @@ struct postV2Tail
return_trace (glyphNameIndex.sanitize (c));
}
ArrayOf<HBUINT16>glyphNameIndex; /* This is not an offset, but is the
ArrayOf<HBUINT16> glyphNameIndex; /* This is not an offset, but is the
* ordinal number of the glyph in 'post'
* string tables. */
HBUINT8 namesX[VAR]; /* Glyph names with length bytes [variable]
UnsizedArrayOf<HBUINT8>
namesX; /* Glyph names with length bytes [variable]
* (a Pascal string). */
DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);

File diff suppressed because it is too large Load Diff

View File

@ -69,7 +69,7 @@ syllable_tail = (z?.SM.SM?.ZWNJ?)? A{0,3}?;
halant_group = (z?.H.(ZWJ.N?)?);
final_halant_group = halant_group | H.ZWNJ;
medial_group = CM?;
halant_or_matra_group = (final_halant_group | (H.ZWJ)? matra_group{0,4});
halant_or_matra_group = (final_halant_group | matra_group{0,4});
consonant_syllable = (Repha|CS)? (cn.halant_group){0,4} cn medial_group halant_or_matra_group syllable_tail;

View File

@ -273,6 +273,7 @@ struct indic_shape_plan_t
const indic_config_t *config;
bool is_old_spec;
bool uniscribe_bug_compatible;
mutable hb_atomic_int_t virama_glyph;
would_substitute_feature_t rphf;
@ -298,6 +299,7 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
}
indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
indic_plan->virama_glyph.set_relaxed (-1);
/* Use zero-context would_substitute() matching for new-spec of the main
@ -913,10 +915,12 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
/* We treat placeholder/dotted-circle as if they are consonants, so we
* should just chain. Only if not in compatibility mode that is... */
if (hb_options ().uniscribe_bug_compatible)
if (indic_plan->uniscribe_bug_compatible)
{
/* For dotted-circle, this is what Uniscribe does:
* If dotted-circle is the last glyph, it just does nothing.
@ -1356,7 +1360,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
* Uniscribe doesn't do this.
* TEST: U+0930,U+094D,U+0915,U+094B,U+094D
*/
if (!hb_options ().uniscribe_bug_compatible &&
if (!indic_plan->uniscribe_bug_compatible &&
unlikely (is_halant (info[new_reph_pos]))) {
for (unsigned int i = base + 1; i < new_reph_pos; i++)
if (info[i].indic_category() == OT_M) {
@ -1462,7 +1466,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
/*
* Finish off the clusters and go home!
*/
if (hb_options ().uniscribe_bug_compatible)
if (indic_plan->uniscribe_bug_compatible)
{
switch ((hb_tag_t) plan->props.script)
{

View File

@ -90,10 +90,14 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
break;
}
/* Automatic fractions. */
map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
/* Random! */
map->add_feature (HB_TAG ('r','a','n','d'), HB_OT_MAP_MAX_VALUE, F_GLOBAL | F_RANDOM);
if (planner->shaper->collect_features)
planner->shaper->collect_features (planner);
@ -117,7 +121,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
if (planner->shaper->override_features)
planner->shaper->override_features (planner);
for (unsigned int i = 0; i < num_user_features; i++) {
for (unsigned int i = 0; i < num_user_features; i++)
{
const hb_feature_t *feature = &user_features[i];
map->add_feature (feature->tag, feature->value,
(feature->start == 0 && feature->end == (unsigned int) -1) ?

View File

@ -93,6 +93,7 @@ struct SegmentMaps : ArrayOf<AxisValueMap>
(value - arrayZ[i-1].fromCoord) + denom/2) / denom;
}
public:
DEFINE_SIZE_ARRAY (2, arrayZ);
};
@ -108,7 +109,7 @@ struct avar
c->check_struct (this))))
return_trace (false);
const SegmentMaps *map = axisSegmentMapsZ;
const SegmentMaps *map = axisSegmentMapsZ.arrayZ;
unsigned int count = axisCount;
for (unsigned int i = 0; i < count; i++)
{
@ -124,7 +125,7 @@ struct avar
{
unsigned int count = MIN<unsigned int> (coords_length, axisCount);
const SegmentMaps *map = axisSegmentMapsZ;
const SegmentMaps *map = axisSegmentMapsZ.arrayZ;
for (unsigned int i = 0; i < count; i++)
{
coords[i] = map->map (coords[i]);
@ -139,7 +140,8 @@ struct avar
HBUINT16 axisCount; /* The number of variation axes in the font. This
* must be the same number as axisCount in the
* 'fvar' table. */
SegmentMaps axisSegmentMapsZ[VAR];
UnsizedArrayOf<SegmentMaps>
axisSegmentMapsZ;
public:
DEFINE_SIZE_MIN (8);

View File

@ -46,20 +46,21 @@ struct InstanceRecord
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
c->check_array (coordinates, coordinates[0].static_size, axis_count));
c->check_array (coordinatesZ.arrayZ, axis_count));
}
protected:
NameID subfamilyNameID;/* The name ID for entries in the 'name' table
* that provide subfamily names for this instance. */
HBUINT16 reserved; /* Reserved for future use — set to 0. */
Fixed coordinates[VAR];/* The coordinates array for this instance. */
UnsizedArrayOf<Fixed>
coordinatesZ; /* The coordinates array for this instance. */
//NameID postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
// * table that provide PostScript names for this
// * instance. */
public:
DEFINE_SIZE_ARRAY (4, coordinates);
DEFINE_SIZE_ARRAY (4, coordinatesZ);
};
struct AxisRecord

View File

@ -39,7 +39,7 @@ struct DeltaSetIndexMap
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
c->check_array (mapData, get_width (), mapCount));
c->check_array (mapDataZ.arrayZ, mapCount, get_width ()));
}
unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
@ -55,7 +55,7 @@ struct DeltaSetIndexMap
unsigned int u = 0;
{ /* Fetch it. */
unsigned int w = get_width ();
const HBUINT8 *p = mapData + w * v;
const HBUINT8 *p = mapDataZ.arrayZ + w * v;
for (; w; w--)
u = (u << 8) + *p++;
}
@ -81,10 +81,11 @@ struct DeltaSetIndexMap
HBUINT16 format; /* A packed field that describes the compressed
* representation of delta-set indices. */
HBUINT16 mapCount; /* The number of mapping entries. */
HBUINT8 mapData[VAR]; /* The delta-set index mapping data. */
UnsizedArrayOf<HBUINT8>
mapDataZ; /* The delta-set index mapping data. */
public:
DEFINE_SIZE_ARRAY (4, mapData);
DEFINE_SIZE_ARRAY (4, mapDataZ);
};

View File

@ -68,14 +68,14 @@ struct MVAR
c->check_struct (this) &&
valueRecordSize >= VariationValueRecord::static_size &&
varStore.sanitize (c, this) &&
c->check_array (values, valueRecordSize, valueRecordCount));
c->check_array (valuesZ.arrayZ, valueRecordCount, valueRecordSize));
}
inline float get_var (hb_tag_t tag,
int *coords, unsigned int coord_count) const
{
const VariationValueRecord *record;
record = (VariationValueRecord *) bsearch (&tag, values,
record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ,
valueRecordCount, valueRecordSize,
tag_compare);
if (!record)
@ -101,11 +101,12 @@ protected:
HBUINT16 valueRecordCount;/* The number of value records — may be zero. */
OffsetTo<VariationStore>
varStore; /* Offset to item variation store table. */
HBUINT8 values[VAR]; /* Array of value records. The records must be
UnsizedArrayOf<HBUINT8>
valuesZ; /* Array of value records. The records must be
* in binary order of their valueTag field. */
public:
DEFINE_SIZE_ARRAY (12, values);
DEFINE_SIZE_ARRAY (12, valuesZ);
};
} /* namespace OT */

View File

@ -50,8 +50,8 @@ struct hb_set_digest_lowest_bits_t
{
ASSERT_POD ();
static const unsigned int mask_bytes = sizeof (mask_t);
static const unsigned int mask_bits = sizeof (mask_t) * 8;
enum { mask_bytes = sizeof (mask_t) };
enum { mask_bits = sizeof (mask_t) * 8 };
static const unsigned int num_bits = 0
+ (mask_bytes >= 1 ? 3 : 0)
+ (mask_bytes >= 2 ? 1 : 0)

View File

@ -157,7 +157,7 @@ struct hb_set_t
}
typedef unsigned long long elt_t;
static const unsigned int PAGE_BITS = 512;
enum { PAGE_BITS = 512 };
static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
static inline unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
@ -165,11 +165,11 @@ struct hb_set_t
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
static const unsigned int ELT_MASK = ELT_BITS - 1;
static const unsigned int BITS = sizeof (vector_t) * 8;
static const unsigned int MASK = BITS - 1;
static_assert (PAGE_BITS == BITS, "");
enum { ELT_BITS = sizeof (elt_t) * 8 };
enum { ELT_MASK = ELT_BITS - 1 };
enum { BITS = sizeof (vector_t) * 8 };
enum { MASK = BITS - 1 };
static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }

View File

@ -40,6 +40,11 @@
HB_BEGIN_DECLS
/**
* HB_UNICODE_MAX
*
* Since: 1.9.0
*/
#define HB_UNICODE_MAX 0x10FFFFu

View File

@ -392,7 +392,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
name.stringOffset.set (name.get_size ());
for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
{
OT::NameRecord &record = name.nameRecord[i];
OT::NameRecord &record = name.nameRecordZ[i];
record.platformID.set (3);
record.encodingID.set (1);
record.languageID.set (0x0409u); /* English */

View File

@ -37,10 +37,10 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 1
#define HB_VERSION_MINOR 8
#define HB_VERSION_MICRO 8
#define HB_VERSION_MINOR 9
#define HB_VERSION_MICRO 0
#define HB_VERSION_STRING "1.8.8"
#define HB_VERSION_STRING "1.9.0"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \

View File

@ -6,6 +6,7 @@ TESTS = \
tests/arabic-stch.tests \
tests/automatic-fractions.tests \
tests/cluster.tests \
tests/collections.tests \
tests/color-fonts.tests \
tests/context-matching.tests \
tests/cursive-positioning.tests \
@ -32,6 +33,7 @@ TESTS = \
tests/mongolian-variation-selector.tests \
tests/myanmar-syllable.tests \
tests/none-directional.tests \
tests/rand.tests \
tests/spaces.tests \
tests/simple.tests \
tests/sinhala.tests \

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

View File

@ -0,0 +1,6 @@
../fonts/TestDFONT.dfont:--face-index=0 --font-funcs=ot:U+2026,U+0020,U+002E:[ellipsis=0+723|space=1+250|period=2+241]
../fonts/TestDFONT.dfont:--face-index=1 --font-funcs=ot:U+2026,U+0020,U+002E:[gid0=0+1000|gid0=1+1000|gid0=2+1000]
../fonts/TestDFONT.dfont:--face-index=2 --font-funcs=ot:U+2026,U+0020,U+002E:[gid0=0+1000|gid0=1+1000|gid0=2+1000]
../fonts/TestTTC.ttc:--face-index=0 --font-funcs=ot:U+2026,U+0020,U+002E:[ellipsis=0+723|space=1+250|period=2+241]
../fonts/TestTTC.ttc:--face-index=1 --font-funcs=ot:U+2026,U+0020,U+002E:[ellipsis=0+723|space=1+250|period=2+241]
../fonts/TestTTC.ttc:--face-index=2 --font-funcs=ot:U+2026,U+0020,U+002E:[gid0=0+1000|gid0=1+1000|gid0=2+1000]

View File

@ -0,0 +1,3 @@
../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=-rand:U+0054,U+0055,U+0056:[1=0+560|2=1+602|3=2+602]
../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=rand=2:U+0054,U+0055,U+0056:[5=0+560|8=1+602|11=2+602]
../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names:U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056:[5=0+560|7=1+602|10=2+602|4=3+560|7=4+602|10=5+602|6=6+560|9=7+602|10=8+602|5=9+560|8=10+602|12=11+602]

View File

@ -125,7 +125,7 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts)
}
#endif
cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, font_opts->ft_load_flags);
}
cairo_matrix_t ctm, font_matrix;
cairo_font_options_t *font_options;

View File

@ -419,7 +419,7 @@ shape_options_t::add_options (option_parser_t *parser)
{"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"},
{"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", nullptr},
{"verify", 0, 0, G_OPTION_ARG_NONE, &this->verify, "Perform sanity checks on shaping results", nullptr},
{"num-iterations", 0, 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"},
{"num-iterations", 'n', 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"},
{nullptr}
};
parser->add_group (entries,
@ -556,6 +556,7 @@ font_options_t::add_options (option_parser_t *parser)
{"font-ppem", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_ppem, "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"},
{"font-ptem", 0, 0, G_OPTION_ARG_DOUBLE, &this->ptem, "Set font point-size (default: 0; disabled)", "point-size"},
{"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"},
{"ft-load-flags", 0, 0, G_OPTION_ARG_INT, &this->ft_load_flags, "Set FreeType load-flags (default: 2)", "integer"},
{nullptr}
};
parser->add_group (entries,
@ -717,6 +718,9 @@ font_options_t::get_font (void) const
}
}
set_font_funcs (font);
#ifdef HAVE_FREETYPE
hb_ft_font_set_load_flags (font, ft_load_flags);
#endif
return font;
}

View File

@ -454,6 +454,7 @@ struct font_options_t : option_group_t
face_index = 0;
font_size_x = font_size_y = default_font_size;
font_funcs = nullptr;
ft_load_flags = 2;
blob = nullptr;
font = nullptr;
@ -484,6 +485,7 @@ struct font_options_t : option_group_t
mutable double font_size_x;
mutable double font_size_y;
char *font_funcs;
int ft_load_flags;
private:
mutable hb_font_t *font;