summaryrefslogtreecommitdiff
path: root/Build/source/libs/harfbuzz/harfbuzz-src/src
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2017-01-05 12:31:24 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2017-01-05 12:31:24 +0000
commitcb430d8e1759789183f71068480cbc2911de2b0c (patch)
treee0b1ab7e33690319f17f6dd051261ffe03053760 /Build/source/libs/harfbuzz/harfbuzz-src/src
parent7d12f6c9702c1933ced5c3077b5e20ef4567233a (diff)
harfbuzz 1.4.0
git-svn-id: svn://tug.org/texlive/trunk@42866 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src')
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources1
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc8
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc54
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fallback-shape.cc4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font-private.hh10
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc33
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h5
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc18
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.h3
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type-private.hh7
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common-private.hh497
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh52
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh117
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh82
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos-private.hh36
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc287
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h19
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map-private.hh18
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc111
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math.cc272
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc1
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc1
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hangul.cc1
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hebrew.cc13
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc20
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-private.hh8
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-thai.cc1
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-tibetan.cc1
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use.cc44
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-private.hh6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc70
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh11
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan-private.hh9
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc102
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.h19
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc5
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc4
42 files changed, 1472 insertions, 496 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
index 166793aa443..e7275984249 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
@@ -80,6 +80,7 @@ HB_OT_sources = \
hb-ot-layout-private.hh \
hb-ot-map.cc \
hb-ot-map-private.hh \
+ hb-ot-math.cc \
hb-ot-shape.cc \
hb-ot-shape-complex-arabic.cc \
hb-ot-shape-complex-arabic-fallback.hh \
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc
index 507581bd7b7..e857dfae03f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc
@@ -288,7 +288,9 @@ struct hb_coretext_shaper_shape_plan_data_t {};
hb_coretext_shaper_shape_plan_data_t *
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
- unsigned int num_user_features HB_UNUSED)
+ unsigned int num_user_features HB_UNUSED,
+ const int *coords HB_UNUSED,
+ unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
@@ -1280,7 +1282,9 @@ struct hb_coretext_aat_shaper_shape_plan_data_t {};
hb_coretext_aat_shaper_shape_plan_data_t *
_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
- unsigned int num_user_features HB_UNUSED)
+ unsigned int num_user_features HB_UNUSED,
+ const int *coords HB_UNUSED,
+ unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
index 76482acd3b3..b5c1113b1b1 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
@@ -209,8 +209,8 @@ _hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data
data->fontFile->Release ();
if (data->dwriteFactory) {
if (data->fontFileLoader)
- data->dwriteFactory->UnregisterFontFileLoader(data->fontFileLoader);
- data->dwriteFactory->Release();
+ data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader);
+ data->dwriteFactory->Release ();
}
if (data->fontFileLoader)
delete data->fontFileLoader;
@@ -258,8 +258,10 @@ struct hb_directwrite_shaper_shape_plan_data_t {};
hb_directwrite_shaper_shape_plan_data_t *
_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
- const hb_feature_t *user_features HB_UNUSED,
- unsigned int num_user_features HB_UNUSED)
+ const hb_feature_t *user_features HB_UNUSED,
+ unsigned int num_user_features HB_UNUSED,
+ const int *coords HB_UNUSED,
+ unsigned int num_coords HB_UNUSED)
{
return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
@@ -540,12 +542,13 @@ static inline uint32_t hb_uint32_swap (const uint32_t v)
* shaper
*/
-hb_bool_t
-_hb_directwrite_shape(hb_shape_plan_t *shape_plan,
+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)
+ unsigned int num_features,
+ float lineWidth)
{
hb_face_t *face = font->face;
hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
@@ -726,9 +729,6 @@ retry_getglyphs:
return false;
}
- // TODO: get lineWith from somewhere
- float lineWidth = 0;
-
IDWriteTextAnalyzer1* analyzer1;
analyzer->QueryInterface (&analyzer1);
@@ -898,3 +898,37 @@ retry_getglyphs:
/* 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);
+}
+
+/*
+ * Public [experimental] API
+ */
+
+hb_bool_t
+hb_shape_dwrite_experimental_width(hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ float width)
+{
+ static char *shapers = "directwrite";
+ hb_shape_plan_t *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);
+
+ if (res)
+ buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
+
+ return res;
+}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h
index 0e1b4799dc9..0eb116f4caf 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h
@@ -29,6 +29,10 @@
HB_BEGIN_DECLS
+HB_EXTERN hb_bool_t
+hb_shape_dwrite_experimental_width(hb_font_t *font, hb_buffer_t *buffer,
+ const hb_feature_t *features, unsigned int num_features, float width);
+
HB_END_DECLS
#endif /* HB_DIRECTWRITE_H */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fallback-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fallback-shape.cc
index e2ad2400167..ac6d4b00f55 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fallback-shape.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fallback-shape.cc
@@ -73,7 +73,9 @@ struct hb_fallback_shaper_shape_plan_data_t {};
hb_fallback_shaper_shape_plan_data_t *
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
- unsigned int num_user_features HB_UNUSED)
+ unsigned int num_user_features HB_UNUSED,
+ const int *coords HB_UNUSED,
+ unsigned int num_coords HB_UNUSED)
{
return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font-private.hh
index cda97a68c01..53671d78d23 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font-private.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font-private.hh
@@ -108,6 +108,10 @@ struct hb_font_t {
unsigned int x_ppem;
unsigned int y_ppem;
+ /* Font variation coordinates. */
+ unsigned int num_coords;
+ int *coords;
+
hb_font_funcs_t *klass;
void *user_data;
hb_destroy_func_t destroy;
@@ -120,6 +124,8 @@ struct hb_font_t {
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
+ inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
+ inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
{ return em_scale (v, dir_scale (direction)); }
@@ -531,6 +537,10 @@ struct hb_font_t {
scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
return (hb_position_t) (scaled / upem);
}
+ inline hb_position_t em_scalef (float v, int scale)
+ {
+ return (hb_position_t) (v * scale / face->get_upem ());
+ }
};
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
index 08fcd647588..2935c4b4fd1 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
@@ -1165,6 +1165,8 @@ hb_font_create_sub_font (hb_font_t *parent)
font->x_ppem = parent->x_ppem;
font->y_ppem = parent->y_ppem;
+ /* TODO: copy variation coordinates. */
+
return font;
}
@@ -1194,6 +1196,9 @@ hb_font_get_empty (void)
0, /* x_ppem */
0, /* y_ppem */
+ 0, /* num_coords */
+ NULL, /* coords */
+
const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
NULL, /* user_data */
NULL, /* destroy */
@@ -1248,6 +1253,8 @@ hb_font_destroy (hb_font_t *font)
hb_face_destroy (font->face);
hb_font_funcs_destroy (font->klass);
+ free (font->coords);
+
free (font);
}
@@ -1537,6 +1544,32 @@ hb_font_get_ppem (hb_font_t *font,
}
+void
+hb_font_set_var_coords_normalized (hb_font_t *font,
+ int *coords, /* XXX 2.14 normalized */
+ unsigned int coords_length)
+{
+ if (font->immutable)
+ return;
+
+ /* Skip tail zero entries. */
+ while (coords_length && !coords[coords_length - 1])
+ coords_length--;
+
+ int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : NULL;
+ if (unlikely (coords_length && !copy))
+ return;
+
+ free (font->coords);
+
+ if (coords_length)
+ memcpy (copy, coords, coords_length * sizeof (coords[0]));
+
+ font->coords = copy;
+ font->num_coords = coords_length;
+}
+
+
#ifndef HB_DISABLE_DEPRECATED
/*
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
index 2b6ab50883f..8813286726b 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
@@ -604,6 +604,11 @@ hb_font_get_ppem (hb_font_t *font,
unsigned int *y_ppem);
+HB_EXTERN void
+hb_font_set_var_coords_normalized (hb_font_t *font,
+ int *coords, /* XXX 2.14 normalized */
+ unsigned int coords_length);
+
HB_END_DECLS
#endif /* HB_FONT_H */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
index 2b06c59be38..f127066a6d3 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
@@ -36,6 +36,7 @@
#include "hb-cache-private.hh" // Maybe use in the future?
#include FT_ADVANCES_H
+#include FT_MULTIPLE_MASTERS_H
#include FT_TRUETYPE_TABLES_H
@@ -616,6 +617,23 @@ hb_ft_font_create (FT_Face ft_face,
ft_face->size->metrics.y_ppem);
#endif
+#ifdef HAVE_FT_GET_VAR_BLEND_COORDINATES
+ FT_MM_Var *mm_var = NULL;
+ if (!FT_Get_MM_Var (ft_face, &mm_var))
+ {
+ FT_Fixed coords[mm_var->num_axis];
+ int hbCoords[mm_var->num_axis];
+ if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, coords))
+ {
+ for (int i = 0; i < mm_var->num_axis; ++i)
+ hbCoords[i] = coords[i] >> 2;
+
+ hb_font_set_var_coords_normalized (font, hbCoords, mm_var->num_axis);
+ }
+ }
+ free (mm_var);
+#endif
+
return font;
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc
index e203524754c..2b91b5b6511 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc
@@ -382,6 +382,7 @@ hb_glib_get_unicode_funcs (void)
return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
}
+#if GLIB_CHECK_VERSION(2,31,10)
/**
* hb_glib_blob_create:
*
@@ -398,3 +399,4 @@ hb_glib_blob_create (GBytes *gbytes)
g_bytes_ref (gbytes),
(hb_destroy_func_t) g_bytes_unref);
}
+#endif
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.h
index 12c3e3b3a89..5f04183ba19 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.h
@@ -46,9 +46,10 @@ hb_glib_script_from_script (hb_script_t script);
HB_EXTERN hb_unicode_funcs_t *
hb_glib_get_unicode_funcs (void);
+#if GLIB_CHECK_VERSION(2,31,10)
HB_EXTERN hb_blob_t *
hb_glib_blob_create (GBytes *gbytes);
-
+#endif
HB_END_DECLS
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
index c32318d2799..a2d90db878f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
@@ -195,7 +195,9 @@ struct hb_graphite2_shaper_shape_plan_data_t {};
hb_graphite2_shaper_shape_plan_data_t *
_hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
- unsigned int num_user_features HB_UNUSED)
+ unsigned int num_user_features HB_UNUSED,
+ const int *coords HB_UNUSED,
+ unsigned int num_coords HB_UNUSED)
{
return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type-private.hh
index 66f1c08df45..2cc1fb20d25 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type-private.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type-private.hh
@@ -105,7 +105,7 @@ static inline Type& StructAfter(TObject &X)
inline unsigned int get_size (void) const { return (size); }
#define DEFINE_SIZE_UNION(size, _member) \
- DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \
+ DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
static const unsigned int min_size = (size)
#define DEFINE_SIZE_MIN(size) \
@@ -652,6 +652,7 @@ struct IntType
typedef IntType<int8_t , 1> CHAR; /* 8-bit signed integer. */
typedef IntType<uint8_t , 1> BYTE; /* 8-bit unsigned integer. */
+typedef IntType<int8_t , 1> INT8; /* 8-bit signed integer. */
typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */
typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */
typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */
@@ -951,8 +952,8 @@ struct ArrayOf
};
/* Array of Offset's */
-template <typename Type>
-struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
+template <typename Type, typename OffsetType=USHORT>
+struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {};
/* Array of offsets relative to the beginning of the array itself. */
template <typename Type>
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
index df01bc9fabb..5be055d3447 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
@@ -355,7 +355,11 @@ struct hb_ot_face_cmap_accelerator_t
if (!subtable) subtable = cmap->find_subtable (0, 2);
if (!subtable) subtable = cmap->find_subtable (0, 1);
if (!subtable) subtable = cmap->find_subtable (0, 0);
- if (!subtable)(subtable = cmap->find_subtable (3, 0)) && (symbol = true);
+ if (!subtable)
+ {
+ subtable = cmap->find_subtable (3, 0);
+ if (subtable) symbol = true;
+ }
/* Meh. */
if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common-private.hh
index 34fa1b77367..62ca7a348eb 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common-private.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common-private.hh
@@ -507,7 +507,7 @@ struct Feature
{ return this+featureParams; }
inline bool sanitize (hb_sanitize_context_t *c,
- const Record<Feature>::sanitize_closure_t *closure) const
+ const Record<Feature>::sanitize_closure_t *closure = NULL) const
{
TRACE_SANITIZE (this);
if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
@@ -731,8 +731,8 @@ struct CoverageFormat1
inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
inline bool more (void) { return i < c->glyphArray.len; }
inline void next (void) { i++; }
- inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
- inline uint16_t get_coverage (void) { return i; }
+ inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; }
+ inline unsigned int get_coverage (void) { return i; }
private:
const struct CoverageFormat1 *c;
@@ -829,26 +829,33 @@ struct CoverageFormat2
public:
/* Older compilers need this to be public. */
- struct Iter {
- inline void init (const CoverageFormat2 &c_) {
+ struct Iter
+ {
+ inline void init (const CoverageFormat2 &c_)
+ {
c = &c_;
coverage = 0;
i = 0;
j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
}
inline bool more (void) { return i < c->rangeRecord.len; }
- inline void next (void) {
- coverage++;
- if (j == c->rangeRecord[i].end) {
+ inline void next (void)
+ {
+ if (j >= c->rangeRecord[i].end)
+ {
i++;
if (more ())
+ {
j = c->rangeRecord[i].start;
+ coverage = c->rangeRecord[i].value;
+ }
return;
}
+ coverage++;
j++;
}
- inline uint16_t get_glyph (void) { return j; }
- inline uint16_t get_coverage (void) { return coverage; }
+ inline hb_codepoint_t get_glyph (void) { return j; }
+ inline unsigned int get_coverage (void) { return coverage; }
private:
const struct CoverageFormat2 *c;
@@ -957,14 +964,14 @@ struct Coverage
default: break;
}
}
- inline uint16_t get_glyph (void) {
+ inline hb_codepoint_t get_glyph (void) {
switch (format) {
case 1: return u.format1.get_glyph ();
case 2: return u.format2.get_glyph ();
default:return 0;
}
}
- inline uint16_t get_coverage (void) {
+ inline unsigned int get_coverage (void) {
switch (format) {
case 1: return u.format1.get_coverage ();
case 2: return u.format2.get_coverage ();
@@ -1162,11 +1169,380 @@ struct ClassDef
/*
+ * Item Variation Store
+ */
+
+struct VarRegionAxis
+{
+ inline float evaluate (int coord) const
+ {
+ int start = startCoord, peak = peakCoord, end = endCoord;
+
+ /* TODO Move these to sanitize(). */
+ if (unlikely (start > peak || peak > end))
+ return 1.;
+ if (unlikely (start < 0 && end > 0 && peak != 0))
+ return 1.;
+
+ if (peak == 0 || coord == peak)
+ return 1.;
+
+ if (coord <= start || end <= coord)
+ return 0.;
+
+ /* Interpolate */
+ if (coord < peak)
+ return float (coord - start) / (peak - start);
+ else
+ return float (end - coord) / (end - peak);
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ /* TODO Handle invalid start/peak/end configs, so we don't
+ * have to do that at runtime. */
+ }
+
+ public:
+ F2DOT14 startCoord;
+ F2DOT14 peakCoord;
+ F2DOT14 endCoord;
+ public:
+ DEFINE_SIZE_STATIC (6);
+};
+
+struct VarRegionList
+{
+ inline float evaluate (unsigned int region_index,
+ int *coords, unsigned int coord_len) const
+ {
+ if (unlikely (region_index >= regionCount))
+ return 0.;
+
+ const VarRegionAxis *axes = axesZ + (region_index * axisCount);
+
+ float v = 1.;
+ unsigned int count = MIN (coord_len, (unsigned int) axisCount);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ float factor = axes[i].evaluate (coords[i]);
+ if (factor == 0.)
+ return 0.;
+ v *= factor;
+ }
+ return v;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ c->check_array (axesZ, axesZ[0].static_size,
+ (unsigned int) axisCount * (unsigned int) regionCount));
+ }
+
+ protected:
+ USHORT axisCount;
+ USHORT regionCount;
+ VarRegionAxis axesZ[VAR];
+ public:
+ DEFINE_SIZE_ARRAY (4, axesZ);
+};
+
+struct VarData
+{
+ inline unsigned int get_row_size (void) const
+ { return shortCount + regionIndices.len; }
+
+ inline unsigned int get_size (void) const
+ { return itemCount * get_row_size (); }
+
+ inline float get_delta (unsigned int inner,
+ int *coords, unsigned int coord_count,
+ const VarRegionList &regions) const
+ {
+ if (unlikely (inner >= itemCount))
+ return 0.;
+
+ unsigned int count = regionIndices.len;
+ unsigned int scount = shortCount;
+
+ const BYTE *bytes = &StructAfter<BYTE> (regionIndices);
+ const BYTE *row = bytes + inner * (scount + count);
+
+ float delta = 0.;
+ unsigned int i = 0;
+
+ const SHORT *scursor = reinterpret_cast<const SHORT *> (row);
+ for (; i < scount; i++)
+ {
+ float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
+ delta += scalar * *scursor++;
+ }
+ const INT8 *bcursor = reinterpret_cast<const INT8 *> (scursor);
+ for (; i < count; i++)
+ {
+ float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
+ delta += scalar * *bcursor++;
+ }
+
+ return delta;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ regionIndices.sanitize(c) &&
+ shortCount <= regionIndices.len &&
+ c->check_array (&StructAfter<BYTE> (regionIndices),
+ get_row_size (), itemCount));
+ }
+
+ protected:
+ USHORT itemCount;
+ USHORT shortCount;
+ ArrayOf<USHORT> regionIndices;
+ BYTE bytesX[VAR];
+ public:
+ DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
+};
+
+struct VariationStore
+{
+ inline float get_delta (unsigned int outer, unsigned int inner,
+ int *coords, unsigned int coord_count) const
+ {
+ if (unlikely (outer >= dataSets.len))
+ return 0.;
+
+ return (this+dataSets[outer]).get_delta (inner,
+ coords, coord_count,
+ this+regions);
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ format == 1 &&
+ regions.sanitize (c, this) &&
+ dataSets.sanitize (c, this));
+ }
+
+ protected:
+ USHORT format;
+ OffsetTo<VarRegionList, ULONG> regions;
+ OffsetArrayOf<VarData, ULONG> dataSets;
+ public:
+ DEFINE_SIZE_ARRAY (8, dataSets);
+};
+
+/*
+ * Feature Variations
+ */
+
+struct ConditionFormat1
+{
+ friend struct Condition;
+
+ private:
+ inline bool evaluate (const int *coords, unsigned int coord_len) const
+ {
+ int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
+ return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ protected:
+ USHORT format; /* Format identifier--format = 1 */
+ USHORT axisIndex;
+ F2DOT14 filterRangeMinValue;
+ F2DOT14 filterRangeMaxValue;
+ public:
+ DEFINE_SIZE_STATIC (8);
+};
+
+struct Condition
+{
+ inline bool evaluate (const int *coords, unsigned int coord_len) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.evaluate (coords, coord_len);
+ default:return false;
+ }
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.format.sanitize (c)) return_trace (false);
+ switch (u.format) {
+ case 1: return_trace (u.format1.sanitize (c));
+ default:return_trace (true);
+ }
+ }
+
+ protected:
+ union {
+ USHORT format; /* Format identifier */
+ ConditionFormat1 format1;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (2, format);
+};
+
+struct ConditionSet
+{
+ inline bool evaluate (const int *coords, unsigned int coord_len) const
+ {
+ unsigned int count = conditions.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+conditions.array[i]).evaluate (coords, coord_len))
+ return false;
+ return true;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (conditions.sanitize (c, this));
+ }
+
+ protected:
+ OffsetArrayOf<Condition, ULONG> conditions;
+ public:
+ DEFINE_SIZE_ARRAY (2, conditions);
+};
+
+struct FeatureTableSubstitutionRecord
+{
+ friend struct FeatureTableSubstitution;
+
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && feature.sanitize (c, base));
+ }
+
+ protected:
+ USHORT featureIndex;
+ OffsetTo<Feature, ULONG> feature;
+ public:
+ DEFINE_SIZE_STATIC (6);
+};
+
+struct FeatureTableSubstitution
+{
+ inline const Feature *find_substitute (unsigned int feature_index) const
+ {
+ unsigned int count = substitutions.len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ const FeatureTableSubstitutionRecord &record = substitutions.array[i];
+ if (record.featureIndex == feature_index)
+ return &(this+record.feature);
+ }
+ return NULL;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (version.sanitize (c) &&
+ likely (version.major == 1) &&
+ substitutions.sanitize (c, this));
+ }
+
+ protected:
+ FixedVersion<> version; /* Version--0x00010000u */
+ ArrayOf<FeatureTableSubstitutionRecord>
+ substitutions;
+ public:
+ DEFINE_SIZE_ARRAY (6, substitutions);
+};
+
+struct FeatureVariationRecord
+{
+ friend struct FeatureVariations;
+
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (conditions.sanitize (c, base) &&
+ substitutions.sanitize (c, base));
+ }
+
+ protected:
+ OffsetTo<ConditionSet, ULONG>
+ conditions;
+ OffsetTo<FeatureTableSubstitution, ULONG>
+ substitutions;
+ public:
+ DEFINE_SIZE_STATIC (8);
+};
+
+struct FeatureVariations
+{
+ static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu;
+
+ inline bool find_index (const int *coords, unsigned int coord_len,
+ unsigned int *index) const
+ {
+ unsigned int count = varRecords.len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ const FeatureVariationRecord &record = varRecords.array[i];
+ if ((this+record.conditions).evaluate (coords, coord_len))
+ {
+ *index = i;
+ return true;
+ }
+ }
+ *index = NOT_FOUND_INDEX;
+ return false;
+ }
+
+ inline const Feature *find_substitute (unsigned int variations_index,
+ unsigned int feature_index) const
+ {
+ const FeatureVariationRecord &record = varRecords[variations_index];
+ return (this+record.substitutions).find_substitute (feature_index);
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (version.sanitize (c) &&
+ likely (version.major == 1) &&
+ varRecords.sanitize (c, this));
+ }
+
+ protected:
+ FixedVersion<> version; /* Version--0x00010000u */
+ ArrayOf<FeatureVariationRecord, ULONG>
+ varRecords;
+ public:
+ DEFINE_SIZE_ARRAY (8, varRecords);
+};
+
+
+/*
* Device Tables
*/
-struct Device
+struct HintingDevice
{
+ friend struct Device;
+
+ private:
inline hb_position_t get_x_delta (hb_font_t *font) const
{ return get_delta (font->x_ppem, font->x_scale); }
@@ -1235,6 +1611,101 @@ struct Device
DEFINE_SIZE_ARRAY (6, deltaValue);
};
+struct VariationDevice
+{
+ friend struct Device;
+
+ private:
+
+ inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
+ { return font->em_scalef_x (get_delta (font, store)); }
+
+ inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
+ { return font->em_scalef_y (get_delta (font, store)); }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ private:
+
+ inline float get_delta (hb_font_t *font, const VariationStore &store) const
+ {
+ return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
+ }
+
+ protected:
+ USHORT outerIndex;
+ USHORT innerIndex;
+ USHORT deltaFormat; /* Format identifier for this table: 0x0x8000 */
+ public:
+ DEFINE_SIZE_STATIC (6);
+};
+
+struct DeviceHeader
+{
+ protected:
+ USHORT reserved1;
+ USHORT reserved2;
+ public:
+ USHORT format; /* Format identifier */
+ public:
+ DEFINE_SIZE_STATIC (6);
+};
+
+struct Device
+{
+ inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
+ {
+ switch (u.b.format)
+ {
+ case 1: case 2: case 3:
+ return u.hinting.get_x_delta (font);
+ case 0x8000:
+ return u.variation.get_x_delta (font, store);
+ default:
+ return 0;
+ }
+ }
+ inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
+ {
+ switch (u.b.format)
+ {
+ case 1: case 2: case 3:
+ return u.hinting.get_y_delta (font);
+ case 0x8000:
+ return u.variation.get_y_delta (font, store);
+ default:
+ return 0;
+ }
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.b.format.sanitize (c)) return_trace (false);
+ switch (u.b.format) {
+ case 1: case 2: case 3:
+ return_trace (u.hinting.sanitize (c));
+ case 0x8000:
+ return_trace (u.variation.sanitize (c));
+ default:
+ return_trace (true);
+ }
+ }
+
+ protected:
+ union {
+ DeviceHeader b;
+ HintingDevice hinting;
+ VariationDevice variation;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (6, b);
+};
+
} /* namespace OT */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh
index 2b4bc5a0218..b70cbb7a38b 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh
@@ -97,7 +97,7 @@ struct CaretValueFormat1
friend struct CaretValue;
private:
- inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
+ inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
{
return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
}
@@ -146,11 +146,11 @@ struct CaretValueFormat3
{
friend struct CaretValue;
- inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
+ inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const
{
return HB_DIRECTION_IS_HORIZONTAL (direction) ?
- font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
- font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
+ font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
+ font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -172,12 +172,15 @@ struct CaretValueFormat3
struct CaretValue
{
- inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
+ inline hb_position_t get_caret_value (hb_font_t *font,
+ hb_direction_t direction,
+ hb_codepoint_t glyph_id,
+ const VariationStore &var_store) const
{
switch (u.format) {
- case 1: return u.format1.get_caret_value (font, direction, glyph_id);
+ case 1: return u.format1.get_caret_value (font, direction);
case 2: return u.format2.get_caret_value (font, direction, glyph_id);
- case 3: return u.format3.get_caret_value (font, direction, glyph_id);
+ case 3: return u.format3.get_caret_value (font, direction, var_store);
default:return 0;
}
}
@@ -210,6 +213,7 @@ struct LigGlyph
inline unsigned int get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
+ const VariationStore &var_store,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
hb_position_t *caret_array /* OUT */) const
@@ -218,7 +222,7 @@ struct LigGlyph
const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
unsigned int count = *caret_count;
for (unsigned int i = 0; i < count; i++)
- caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id);
+ caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
}
return carets.len;
@@ -244,6 +248,7 @@ struct LigCaretList
inline unsigned int get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
+ const VariationStore &var_store,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
hb_position_t *caret_array /* OUT */) const
@@ -256,7 +261,7 @@ struct LigCaretList
return 0;
}
const LigGlyph &lig_glyph = this+ligGlyph[index];
- return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array);
+ return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -367,11 +372,17 @@ struct GDEF
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
hb_position_t *caret_array /* OUT */) const
- { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
+ { return (this+ligCaretList).get_lig_carets (font,
+ direction, glyph_id, get_var_store(),
+ start_offset, caret_count, caret_array); }
- inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; }
+ inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
- { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
+ { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
+
+ inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; }
+ inline const VariationStore &get_var_store (void) const
+ { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
inline bool sanitize (hb_sanitize_context_t *c) const
{
@@ -382,10 +393,10 @@ struct GDEF
attachList.sanitize (c, this) &&
ligCaretList.sanitize (c, this) &&
markAttachClassDef.sanitize (c, this) &&
- (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this)));
+ (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
+ (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
}
-
/* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
* glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
* Not to be confused with lookup_props which is very similar. */
@@ -410,7 +421,7 @@ struct GDEF
protected:
FixedVersion<>version; /* Version of the GDEF table--currently
- * 0x00010002u */
+ * 0x00010003u */
OffsetTo<ClassDef>
glyphClassDef; /* Offset to class definition table
* for glyph type--from beginning of
@@ -428,12 +439,17 @@ struct GDEF
* mark attachment type--from beginning
* of GDEF header (may be Null) */
OffsetTo<MarkGlyphSets>
- markGlyphSetsDef[VAR]; /* Offset to the table of mark set
+ markGlyphSetsDef; /* Offset to the table of mark set
* definitions--from beginning of GDEF
* header (may be NULL). Introduced
- * in version 00010002. */
+ * in version 0x00010002. */
+ OffsetTo<VariationStore, ULONG>
+ varStore; /* Offset to the table of Item Variation
+ * Store--from beginning of GDEF
+ * header (may be NULL). Introduced
+ * in version 0x00010003. */
public:
- DEFINE_SIZE_ARRAY (12, markGlyphSetsDef);
+ DEFINE_SIZE_MIN (12);
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh
index bbe390cf7d2..952fd60fec5 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh
@@ -103,18 +103,17 @@ struct ValueFormat : USHORT
inline unsigned int get_size (void) const
{ return get_len () * Value::static_size; }
- void apply_value (hb_font_t *font,
- hb_direction_t direction,
+ void apply_value (hb_apply_context_t *c,
const void *base,
const Value *values,
hb_glyph_position_t &glyph_pos) const
{
- unsigned int x_ppem, y_ppem;
unsigned int format = *this;
- hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction);
-
if (!format) return;
+ hb_font_t *font = c->font;
+ hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
+
if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++));
if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++));
if (format & xAdvance) {
@@ -129,27 +128,29 @@ struct ValueFormat : USHORT
if (!has_device ()) return;
- x_ppem = font->x_ppem;
- y_ppem = font->y_ppem;
+ bool use_x_device = font->x_ppem || font->num_coords;
+ bool use_y_device = font->y_ppem || font->num_coords;
- if (!x_ppem && !y_ppem) return;
+ if (!use_x_device && !use_y_device) return;
+
+ const VariationStore &store = c->var_store;
/* pixel -> fractional pixel */
if (format & xPlaDevice) {
- if (x_ppem) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font);
+ if (use_x_device) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font, store);
values++;
}
if (format & yPlaDevice) {
- if (y_ppem) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font);
+ if (use_y_device) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font, store);
values++;
}
if (format & xAdvDevice) {
- if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font);
+ if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store);
values++;
}
if (format & yAdvDevice) {
/* y_advance values grow downward but font-space grows upward, hence negation */
- if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font);
+ if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store);
values++;
}
}
@@ -231,11 +232,12 @@ struct ValueFormat : USHORT
struct AnchorFormat1
{
- inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
+ inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
- *x = font->em_scale_x (xCoordinate);
- *y = font->em_scale_y (yCoordinate);
+ hb_font_t *font = c->font;
+ *x = font->em_scale_x (xCoordinate);
+ *y = font->em_scale_y (yCoordinate);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -254,18 +256,19 @@ struct AnchorFormat1
struct AnchorFormat2
{
- inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
+ inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
hb_position_t *x, hb_position_t *y) const
{
- unsigned int x_ppem = font->x_ppem;
- unsigned int y_ppem = font->y_ppem;
- hb_position_t cx, cy;
- hb_bool_t ret;
+ hb_font_t *font = c->font;
+ unsigned int x_ppem = font->x_ppem;
+ unsigned int y_ppem = font->y_ppem;
+ hb_position_t cx, cy;
+ hb_bool_t ret;
- ret = (x_ppem || y_ppem) &&
- font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
- *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
- *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
+ ret = (x_ppem || y_ppem) &&
+ font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+ *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
+ *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -285,16 +288,17 @@ struct AnchorFormat2
struct AnchorFormat3
{
- inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
+ inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
- *x = font->em_scale_x (xCoordinate);
- *y = font->em_scale_y (yCoordinate);
+ hb_font_t *font = c->font;
+ *x = font->em_scale_x (xCoordinate);
+ *y = font->em_scale_y (yCoordinate);
- if (font->x_ppem)
- *x += (this+xDeviceTable).get_x_delta (font);
- if (font->y_ppem)
- *y += (this+yDeviceTable).get_x_delta (font);
+ if (font->x_ppem || font->num_coords)
+ *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
+ if (font->y_ppem || font->num_coords)
+ *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -321,14 +325,14 @@ struct AnchorFormat3
struct Anchor
{
- inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
+ inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
hb_position_t *x, hb_position_t *y) const
{
*x = *y = 0;
switch (u.format) {
- case 1: u.format1.get_anchor (font, glyph_id, x, y); return;
- case 2: u.format2.get_anchor (font, glyph_id, x, y); return;
- case 3: u.format3.get_anchor (font, glyph_id, x, y); return;
+ case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
+ case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
+ case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
default: return;
}
}
@@ -370,7 +374,7 @@ struct AnchorMatrix
{
TRACE_SANITIZE (this);
if (!c->check_struct (this)) return_trace (false);
- if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return_trace (false);
+ if (unlikely (_hb_unsigned_int_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);
for (unsigned int i = 0; i < count; i++)
@@ -428,8 +432,8 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
hb_position_t mark_x, mark_y, base_x, base_y;
- mark_anchor.get_anchor (c->font, buffer->cur().codepoint, &mark_x, &mark_y);
- glyph_anchor.get_anchor (c->font, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
+ mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
+ glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
hb_glyph_position_t &o = buffer->cur_pos();
o.x_offset = base_x - mark_x;
@@ -472,8 +476,7 @@ struct SinglePosFormat1
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- valueFormat.apply_value (c->font, c->direction, this,
- values, buffer->cur_pos());
+ valueFormat.apply_value (c, this, values, buffer->cur_pos());
buffer->idx++;
return_trace (true);
@@ -523,7 +526,7 @@ struct SinglePosFormat2
if (likely (index >= valueCount)) return_trace (false);
- valueFormat.apply_value (c->font, c->direction, this,
+ valueFormat.apply_value (c, this,
&values[index * valueFormat.get_len ()],
buffer->cur_pos());
@@ -640,10 +643,8 @@ struct PairSet
min = mid + 1;
else
{
- valueFormats[0].apply_value (c->font, c->direction, this,
- &record->values[0], buffer->cur_pos());
- valueFormats[1].apply_value (c->font, c->direction, this,
- &record->values[len1], buffer->pos[pos]);
+ valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
+ valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
if (len2)
pos++;
buffer->idx = pos;
@@ -689,7 +690,7 @@ struct PairPosFormat1
(this+coverage).add_coverage (c->input);
unsigned int count = pairSet.len;
for (unsigned int i = 0; i < count; i++)
- (this+pairSet[i]).collect_glyphs (c, &valueFormat1);
+ (this+pairSet[i]).collect_glyphs (c, valueFormat);
}
inline const Coverage &get_coverage (void) const
@@ -708,7 +709,7 @@ struct PairPosFormat1
skippy_iter.reset (buffer->idx, 1);
if (!skippy_iter.next ()) return_trace (false);
- return_trace ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx));
+ return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -717,11 +718,11 @@ struct PairPosFormat1
if (!c->check_struct (this)) return_trace (false);
- unsigned int len1 = valueFormat1.get_len ();
- unsigned int len2 = valueFormat2.get_len ();
+ unsigned int len1 = valueFormat[0].get_len ();
+ unsigned int len2 = valueFormat[1].get_len ();
PairSet::sanitize_closure_t closure = {
this,
- &valueFormat1,
+ valueFormat,
len1,
1 + len1 + len2
};
@@ -734,10 +735,10 @@ struct PairPosFormat1
OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
- ValueFormat valueFormat1; /* Defines the types of data in
+ ValueFormat valueFormat[2]; /* [0] Defines the types of data in
* ValueRecord1--for the first glyph
* in the pair--may be zero (0) */
- ValueFormat valueFormat2; /* Defines the types of data in
+ /* [1] Defines the types of data in
* ValueRecord2--for the second glyph
* in the pair--may be zero (0) */
OffsetArrayOf<PairSet>
@@ -790,10 +791,8 @@ struct PairPosFormat2
if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
- valueFormat1.apply_value (c->font, c->direction, this,
- v, buffer->cur_pos());
- valueFormat2.apply_value (c->font, c->direction, this,
- v + len1, buffer->pos[skippy_iter.idx]);
+ valueFormat1.apply_value (c, this, v, buffer->cur_pos());
+ valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
buffer->idx = skippy_iter.idx;
if (len2)
@@ -931,8 +930,8 @@ struct CursivePosFormat1
unsigned int j = skippy_iter.idx;
hb_position_t entry_x, entry_y, exit_x, exit_y;
- (this+this_record.exitAnchor).get_anchor (c->font, buffer->info[i].codepoint, &exit_x, &exit_y);
- (this+next_record.entryAnchor).get_anchor (c->font, buffer->info[j].codepoint, &entry_x, &entry_y);
+ (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
+ (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
hb_glyph_position_t *pos = buffer->pos;
@@ -1519,8 +1518,6 @@ struct GPOS : GSUBGPOS
const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
return_trace (list.sanitize (c, this));
}
- public:
- DEFINE_SIZE_STATIC (10);
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh
index 22031f43ced..66fcb3f3af3 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh
@@ -41,7 +41,10 @@ struct SingleSubstFormat1
{
TRACE_CLOSURE (this);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ /* TODO Switch to range-based API to work around malicious fonts.
+ * https://github.com/behdad/harfbuzz/issues/363 */
hb_codepoint_t glyph_id = iter.get_glyph ();
if (c->glyphs->has (glyph_id))
c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
@@ -52,7 +55,10 @@ struct SingleSubstFormat1
{
TRACE_COLLECT_GLYPHS (this);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ /* TODO Switch to range-based API to work around malicious fonts.
+ * https://github.com/behdad/harfbuzz/issues/363 */
hb_codepoint_t glyph_id = iter.get_glyph ();
c->input->add (glyph_id);
c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
@@ -120,7 +126,11 @@ struct SingleSubstFormat2
{
TRACE_CLOSURE (this);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ unsigned int count = substitute.len;
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ if (unlikely (iter.get_coverage () >= count))
+ break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
if (c->glyphs->has (iter.get_glyph ()))
c->glyphs->add (substitute[iter.get_coverage ()]);
}
@@ -130,7 +140,11 @@ struct SingleSubstFormat2
{
TRACE_COLLECT_GLYPHS (this);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ unsigned int count = substitute.len;
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ if (unlikely (iter.get_coverage () >= count))
+ break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
c->input->add (iter.get_glyph ());
c->output->add (substitute[iter.get_coverage ()]);
}
@@ -321,7 +335,11 @@ struct MultipleSubstFormat1
{
TRACE_CLOSURE (this);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ unsigned int count = sequence.len;
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ if (unlikely (iter.get_coverage () >= count))
+ break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
if (c->glyphs->has (iter.get_glyph ()))
(this+sequence[iter.get_coverage ()]).closure (c);
}
@@ -439,7 +457,11 @@ struct AlternateSubstFormat1
{
TRACE_CLOSURE (this);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ unsigned int count = alternateSet.len;
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ if (unlikely (iter.get_coverage () >= count))
+ break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
if (c->glyphs->has (iter.get_glyph ())) {
const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
unsigned int count = alt_set.len;
@@ -453,7 +475,11 @@ struct AlternateSubstFormat1
{
TRACE_COLLECT_GLYPHS (this);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ unsigned int count = alternateSet.len;
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ if (unlikely (iter.get_coverage () >= count))
+ break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
c->input->add (iter.get_glyph ());
const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
unsigned int count = alt_set.len;
@@ -762,7 +788,11 @@ struct LigatureSubstFormat1
{
TRACE_CLOSURE (this);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ unsigned int count = ligatureSet.len;
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ if (unlikely (iter.get_coverage () >= count))
+ break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
if (c->glyphs->has (iter.get_glyph ()))
(this+ligatureSet[iter.get_coverage ()]).closure (c);
}
@@ -772,7 +802,11 @@ struct LigatureSubstFormat1
{
TRACE_COLLECT_GLYPHS (this);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ unsigned int count = ligatureSet.len;
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ if (unlikely (iter.get_coverage () >= count))
+ break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
c->input->add (iter.get_glyph ());
(this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c);
}
@@ -923,7 +957,11 @@ struct ReverseChainSingleSubstFormat1
const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
Coverage::Iter iter;
- for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ count = substitute.len;
+ for (iter.init (this+coverage); iter.more (); iter.next ())
+ {
+ if (unlikely (iter.get_coverage () >= count))
+ break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
if (c->glyphs->has (iter.get_glyph ()))
c->glyphs->add (substitute[iter.get_coverage ()]);
}
@@ -1273,8 +1311,6 @@ struct GSUB : GSUBGPOS
const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
return_trace (list.sanitize (c, this));
}
- public:
- DEFINE_SIZE_STATIC (10);
};
@@ -1285,28 +1321,10 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
{
- unsigned int props = gdef.get_glyph_props (info[i].codepoint);
- if (!props)
- {
- /* Never mark default-ignorables as marks.
- * They won't get in the way of lookups anyway,
- * but having them as mark will cause them to be skipped
- * over if the lookup-flag says so, but at least for the
- * Mongolian variation selectors, looks like Uniscribe
- * marks them as non-mark. Some Mongolian fonts without
- * GDEF rely on this. Another notable character that
- * this applies to is COMBINING GRAPHEME JOINER. */
- props = (_hb_glyph_info_get_general_category (&info[i]) !=
- HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
- _hb_glyph_info_is_default_ignorable (&info[i])) ?
- HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
- HB_OT_LAYOUT_GLYPH_PROPS_MARK;
- }
- _hb_glyph_info_set_glyph_props (&info[i], props);
- _hb_glyph_info_clear_lig_props (&info[i]);
+ _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
+ _hb_glyph_info_clear_lig_props (&buffer->info[i]);
buffer->info[i].syllable() = 0;
}
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos-private.hh
index 997d2255054..fd75c5425a9 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos-private.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos-private.hh
@@ -469,6 +469,7 @@ struct hb_apply_context_t :
unsigned int lookup_props;
const GDEF &gdef;
bool has_glyph_classes;
+ const VariationStore &var_store;
skipping_iterator_t iter_input, iter_context;
unsigned int lookup_index;
unsigned int debug_depth;
@@ -487,6 +488,7 @@ struct hb_apply_context_t :
lookup_props (0),
gdef (*hb_ot_layout_from_face (face)->gdef),
has_glyph_classes (gdef.has_glyph_classes ()),
+ var_store (gdef.get_var_store ()),
iter_input (),
iter_context (),
lookup_index ((unsigned int) -1),
@@ -999,8 +1001,12 @@ static inline bool apply_lookup (hb_apply_context_t *c,
end = int (end) + delta;
if (end <= match_positions[idx])
{
+ /* End might end up being smaller than match_positions[idx] if the recursed
+ * lookup ended up removing many items, more than we have had matched.
+ * Just never rewind end back and get out of here.
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
+ end = match_positions[idx];
/* There can't be any further changes. */
- assert (end == match_positions[idx]);
break;
}
@@ -2269,6 +2275,24 @@ struct GSUBGPOS
inline const Lookup& get_lookup (unsigned int i) const
{ return (this+lookupList)[i]; }
+ inline bool find_variations_index (const int *coords, unsigned int num_coords,
+ unsigned int *index) const
+ { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
+ .find_index (coords, num_coords, index); }
+ inline const Feature& get_feature_variation (unsigned int feature_index,
+ unsigned int variations_index) const
+ {
+ if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
+ version.to_int () >= 0x00010001u)
+ {
+ const Feature *feature = (this+featureVars).find_substitute (variations_index,
+ feature_index);
+ if (feature)
+ return *feature;
+ }
+ return get_feature (feature_index);
+ }
+
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -2276,7 +2300,8 @@ struct GSUBGPOS
likely (version.major == 1) &&
scriptList.sanitize (c, this) &&
featureList.sanitize (c, this) &&
- lookupList.sanitize (c, this));
+ lookupList.sanitize (c, this) &&
+ (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
}
protected:
@@ -2288,8 +2313,13 @@ struct GSUBGPOS
featureList; /* FeatureList table */
OffsetTo<LookupList>
lookupList; /* LookupList table */
+ OffsetTo<FeatureVariations, ULONG>
+ featureVars; /* Offset to Feature Variations
+ table--from beginning of table
+ * (may be NULL). Introduced
+ * in version 0x00010001. */
public:
- DEFINE_SIZE_STATIC (10);
+ DEFINE_SIZE_MIN (10);
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
index 0501181a332..145ec763898 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
@@ -35,7 +35,6 @@
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
#include "hb-ot-layout-jstf-table.hh"
-#include "hb-ot-layout-math-table.hh"
#include "hb-ot-map-private.hh"
@@ -205,31 +204,6 @@ _get_gpos (hb_face_t *face)
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
return *hb_ot_layout_from_face (face)->gpos;
}
-static inline const OT::MATH&
-_get_math (hb_face_t *face)
-{
- if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH);
-
- hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-
-retry:
- const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math);
-
- if (unlikely (!math))
- {
- hb_blob_t *blob = OT::Sanitizer<OT::MATH>::sanitize (face->reference_table (HB_OT_TAG_MATH));
- math = OT::Sanitizer<OT::MATH>::lock_instance (blob);
- if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math))
- {
- hb_blob_destroy (blob);
- goto retry;
- }
- layout->math_blob = blob;
- }
-
- return *math;
-}
-
/*
* GDEF
@@ -582,10 +556,13 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face,
unsigned int *lookup_count /* IN/OUT */,
unsigned int *lookup_indexes /* OUT */)
{
- const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
- const OT::Feature &f = g.get_feature (feature_index);
-
- return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
+ return hb_ot_layout_feature_with_variations_get_lookups (face,
+ table_tag,
+ feature_index,
+ HB_OT_LAYOUT_NO_VARIATIONS_INDEX,
+ start_offset,
+ lookup_count,
+ lookup_indexes);
}
/**
@@ -836,6 +813,38 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
}
+/* Variations support */
+
+hb_bool_t
+hb_ot_layout_table_find_feature_variations (hb_face_t *face,
+ hb_tag_t table_tag,
+ const int *coords,
+ unsigned int num_coords,
+ unsigned int *variations_index /* out */)
+{
+ const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+ return g.find_variations_index (coords, num_coords, variations_index);
+}
+
+unsigned int
+hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int feature_index,
+ unsigned int variations_index,
+ unsigned int start_offset,
+ unsigned int *lookup_count /* IN/OUT */,
+ unsigned int *lookup_indexes /* OUT */)
+{
+ ASSERT_STATIC (OT::FeatureVariations::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_VARIATIONS_INDEX);
+ const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+ const OT::Feature &f = g.get_feature_variation (feature_index, variations_index);
+
+ return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
+}
+
+
/*
* OT::GSUB
*/
@@ -1220,221 +1229,3 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
{
apply_string<GSUBProxy> (c, lookup, accel);
}
-
-
-/*
- * MATH
- */
-/* TODO Move this to hb-ot-math.cc and separate it from hb_ot_layout_t. */
-
-/**
- * hb_ot_math_has_data:
- * @face: #hb_face_t to test
- *
- * This function allows to verify the presence of an OpenType MATH table on the
- * face. If so, such a table will be loaded into memory and sanitized. You can
- * then safely call other functions for math layout and shaping.
- *
- * Return value: #TRUE if face has a MATH table and #FALSE otherwise
- *
- * Since: 1.3.3
- **/
-hb_bool_t
-hb_ot_math_has_data (hb_face_t *face)
-{
- return &_get_math (face) != &OT::Null(OT::MATH);
-}
-
-/**
- * hb_ot_math_get_constant:
- * @font: #hb_font_t from which to retrieve the value
- * @constant: #hb_ot_math_constant_t the constant to retrieve
- *
- * This function returns the requested math constants as a #hb_position_t.
- * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
- * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
- * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is
- * actually an integer between 0 and 100 representing that percentage.
- *
- * Return value: the requested constant or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_constant (hb_font_t *font,
- hb_ot_math_constant_t constant)
-{
- const OT::MATH &math = _get_math (font->face);
- return math.get_constant(constant, font);
-}
-
-/**
- * hb_ot_math_get_glyph_italics_correction:
- * @font: #hb_font_t from which to retrieve the value
- * @glyph: glyph index from which to retrieve the value
- *
- * Return value: the italics correction of the glyph or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
- hb_codepoint_t glyph)
-{
- const OT::MATH &math = _get_math (font->face);
- return math.get_math_glyph_info().get_italics_correction (glyph, font);
-}
-
-/**
- * hb_ot_math_get_glyph_top_accent_attachment:
- * @font: #hb_font_t from which to retrieve the value
- * @glyph: glyph index from which to retrieve the value
- *
- * Return value: the top accent attachment of the glyph or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
- hb_codepoint_t glyph)
-{
- const OT::MATH &math = _get_math (font->face);
- return math.get_math_glyph_info().get_top_accent_attachment (glyph, font);
-}
-
-/**
- * hb_ot_math_is_glyph_extended_shape:
- * @font: a #hb_font_t to test
- * @glyph: a glyph index to test
- *
- * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise
- *
- * Since: 1.3.3
- **/
-hb_bool_t
-hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
- hb_codepoint_t glyph)
-{
- const OT::MATH &math = _get_math (face);
- return math.get_math_glyph_info().is_extended_shape (glyph);
-}
-
-/**
- * hb_ot_math_get_glyph_kerning:
- * @font: #hb_font_t from which to retrieve the value
- * @glyph: glyph index from which to retrieve the value
- * @kern: the #hb_ot_math_kern_t from which to retrieve the value
- * @correction_height: the correction height to use to determine the kerning.
- *
- * This function tries to retrieve the MathKern table for the specified font,
- * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the
- * MathKern table to find one value that is greater or equal to specified
- * correction_height. If one is found the corresponding value from the list of
- * kerns is returned and otherwise the last kern value is returned.
- *
- * Return value: requested kerning or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_glyph_kerning (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_ot_math_kern_t kern,
- hb_position_t correction_height)
-{
- const OT::MATH &math = _get_math (font->face);
- return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
-}
-
-/**
- * hb_ot_math_get_glyph_variants:
- * @font: #hb_font_t from which to retrieve the values
- * @glyph: index of the glyph to stretch
- * @direction: direction of the stretching
- * @start_offset: offset of the first variant to retrieve
- * @variants_count: maximum number of variants to retrieve after start_offset
- * (IN) and actual number of variants retrieved (OUT)
- * @variants: array of size at least @variants_count to store the result
- *
- * This function tries to retrieve the MathGlyphConstruction for the specified
- * font, glyph and direction. Note that only the value of
- * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
- * of size variants as an array of hb_ot_math_glyph_variant_t structs.
- *
- * Return value: the total number of size variants available or 0
- *
- * Since: 1.3.3
- **/
-unsigned int
-hb_ot_math_get_glyph_variants (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_direction_t direction,
- unsigned int start_offset,
- unsigned int *variants_count, /* IN/OUT */
- hb_ot_math_glyph_variant_t *variants /* OUT */)
-{
- const OT::MATH &math = _get_math (font->face);
- return math.get_math_variants().get_glyph_variants (glyph, direction, font,
- start_offset,
- variants_count,
- variants);
-}
-
-/**
- * hb_ot_math_get_min_connector_overlap:
- * @font: #hb_font_t from which to retrieve the value
- * @direction: direction of the stretching
- *
- * This function tries to retrieve the MathVariants table for the specified
- * font and returns the minimum overlap of connecting glyphs to draw a glyph
- * assembly in the specified direction. Note that only the value of
- * #HB_DIRECTION_IS_HORIZONTAL is considered.
- *
- * Return value: requested min connector overlap or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_min_connector_overlap (hb_font_t *font,
- hb_direction_t direction)
-{
- const OT::MATH &math = _get_math (font->face);
- return math.get_math_variants().get_min_connector_overlap (direction, font);
-}
-
-/**
- * hb_ot_math_get_glyph_assembly:
- * @font: #hb_font_t from which to retrieve the values
- * @glyph: index of the glyph to stretch
- * @direction: direction of the stretching
- * @start_offset: offset of the first glyph part to retrieve
- * @parts_count: maximum number of glyph parts to retrieve after start_offset
- * (IN) and actual number of parts retrieved (OUT)
- * @parts: array of size at least @parts_count to store the result
- * @italics_correction: italic correction of the glyph assembly
- *
- * This function tries to retrieve the GlyphAssembly for the specified font,
- * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
- * is considered. It provides the information necessary to draw the glyph
- * assembly as an array of #hb_ot_math_glyph_part_t.
- *
- * Return value: the total number of parts in the glyph assembly
- *
- * Since: 1.3.3
- **/
-unsigned int
-hb_ot_math_get_glyph_assembly (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_direction_t direction,
- unsigned int start_offset,
- unsigned int *parts_count, /* IN/OUT */
- hb_ot_math_glyph_part_t *parts, /* OUT */
- hb_position_t *italics_correction /* OUT */)
-{
- const OT::MATH &math = _get_math (font->face);
- return math.get_math_variants().get_glyph_parts (glyph, direction, font,
- start_offset,
- parts_count,
- parts,
- italics_correction);
-}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h
index eb23d45b68a..9861f0fc7bb 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h
@@ -95,6 +95,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
#define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu
#define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu
+#define HB_OT_LAYOUT_NO_VARIATIONS_INDEX 0xFFFFFFFFu
HB_EXTERN unsigned int
hb_ot_layout_table_get_script_tags (hb_face_t *face,
@@ -236,6 +237,24 @@ Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face,
void *user_data);
#endif
+/* Variations support */
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_table_find_feature_variations (hb_face_t *face,
+ hb_tag_t table_tag,
+ const int *coords,
+ unsigned int num_coords,
+ unsigned int *variations_index /* out */);
+
+HB_EXTERN unsigned int
+hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int feature_index,
+ unsigned int variations_index,
+ unsigned int start_offset,
+ unsigned int *lookup_count /* IN/OUT */,
+ unsigned int *lookup_indexes /* OUT */);
+
/*
* GSUB
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map-private.hh
index 8692caa9392..0395c9c22ff 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map-private.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map-private.hh
@@ -139,12 +139,6 @@ struct hb_ot_map_t
private:
- HB_INTERNAL void add_lookups (hb_face_t *face,
- unsigned int table_index,
- unsigned int feature_index,
- hb_mask_t mask,
- bool auto_zwj);
-
hb_mask_t global_mask;
hb_prealloced_array_t<feature_map_t, 8> features;
@@ -182,7 +176,9 @@ struct hb_ot_map_builder_t
inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
{ add_pause (1, pause_func); }
- HB_INTERNAL void compile (struct hb_ot_map_t &m);
+ HB_INTERNAL void compile (hb_ot_map_t &m,
+ const int *coords,
+ unsigned int num_coords);
inline void finish (void) {
feature_infos.finish ();
@@ -194,6 +190,14 @@ struct hb_ot_map_builder_t
private:
+ HB_INTERNAL void add_lookups (hb_ot_map_t &m,
+ hb_face_t *face,
+ unsigned int table_index,
+ unsigned int feature_index,
+ unsigned int variations_index,
+ hb_mask_t mask,
+ bool auto_zwj);
+
struct feature_info_t {
hb_tag_t tag;
unsigned int seq; /* sequence#, used for stable sorting only */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc
index 17e3f4065e3..9b331d5210f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc
@@ -31,44 +31,13 @@
#include "hb-ot-layout-private.hh"
-void
-hb_ot_map_t::add_lookups (hb_face_t *face,
- unsigned int table_index,
- unsigned int feature_index,
- hb_mask_t mask,
- bool auto_zwj)
+void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
{
- unsigned int lookup_indices[32];
- unsigned int offset, len;
- unsigned int table_lookup_count;
-
- table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]);
-
- offset = 0;
- do {
- len = ARRAY_LENGTH (lookup_indices);
- hb_ot_layout_feature_get_lookups (face,
- table_tags[table_index],
- feature_index,
- offset, &len,
- lookup_indices);
-
- for (unsigned int i = 0; i < len; i++)
- {
- if (lookup_indices[i] >= table_lookup_count)
- continue;
- hb_ot_map_t::lookup_map_t *lookup = lookups[table_index].push ();
- if (unlikely (!lookup))
- return;
- lookup->mask = mask;
- lookup->index = lookup_indices[i];
- lookup->auto_zwj = auto_zwj;
- }
-
- offset += len;
- } while (len == ARRAY_LENGTH (lookup_indices));
+ for (unsigned int i = 0; i < lookups[table_index].len; i++)
+ hb_set_add (lookups_out, lookups[table_index][i].index);
}
+
hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
const hb_segment_properties_t *props_)
{
@@ -109,13 +78,48 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
info->stage[1] = current_stage[1];
}
-
-void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
+void
+hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
+ hb_face_t *face,
+ unsigned int table_index,
+ unsigned int feature_index,
+ unsigned int variations_index,
+ hb_mask_t mask,
+ bool auto_zwj)
{
- for (unsigned int i = 0; i < lookups[table_index].len; i++)
- hb_set_add (lookups_out, lookups[table_index][i].index);
+ unsigned int lookup_indices[32];
+ unsigned int offset, len;
+ unsigned int table_lookup_count;
+
+ table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]);
+
+ offset = 0;
+ do {
+ len = ARRAY_LENGTH (lookup_indices);
+ hb_ot_layout_feature_with_variations_get_lookups (face,
+ table_tags[table_index],
+ feature_index,
+ variations_index,
+ offset, &len,
+ lookup_indices);
+
+ for (unsigned int i = 0; i < len; i++)
+ {
+ if (lookup_indices[i] >= table_lookup_count)
+ continue;
+ hb_ot_map_t::lookup_map_t *lookup = m.lookups[table_index].push ();
+ if (unlikely (!lookup))
+ return;
+ lookup->mask = mask;
+ lookup->index = lookup_indices[i];
+ lookup->auto_zwj = auto_zwj;
+ }
+
+ offset += len;
+ } while (len == ARRAY_LENGTH (lookup_indices));
}
+
void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func)
{
stage_info_t *s = stages[table_index].push ();
@@ -128,7 +132,9 @@ void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::paus
}
void
-hb_ot_map_builder_t::compile (hb_ot_map_t &m)
+hb_ot_map_builder_t::compile (hb_ot_map_t &m,
+ const int *coords,
+ unsigned int num_coords)
{
m.global_mask = 1;
@@ -262,23 +268,32 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
{
/* Collect lookup indices for features */
+ unsigned int variations_index;
+ hb_ot_layout_table_find_feature_variations (face,
+ table_tags[table_index],
+ coords,
+ num_coords,
+ &variations_index);
+
unsigned int stage_index = 0;
unsigned int last_num_lookups = 0;
for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
{
if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX &&
required_feature_stage[table_index] == stage)
- m.add_lookups (face, table_index,
- required_feature_index[table_index],
- 1 /* mask */,
- true /* auto_zwj */);
+ add_lookups (m, face, table_index,
+ required_feature_index[table_index],
+ variations_index,
+ 1 /* mask */,
+ true /* auto_zwj */);
for (unsigned i = 0; i < m.features.len; i++)
if (m.features[i].stage[table_index] == stage)
- m.add_lookups (face, table_index,
- m.features[i].index[table_index],
- m.features[i].mask,
- m.features[i].auto_zwj);
+ add_lookups (m, face, table_index,
+ m.features[i].index[table_index],
+ variations_index,
+ m.features[i].mask,
+ m.features[i].auto_zwj);
/* Sort lookups and merge duplicates */
if (last_num_lookups < m.lookups[table_index].len)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math.cc
new file mode 100644
index 00000000000..9ef21d29955
--- /dev/null
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math.cc
@@ -0,0 +1,272 @@
+/*
+ * Copyright © 2016 Igalia S.L.
+ *
+ * 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.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+#include "hb-open-type-private.hh"
+
+#include "hb-ot-layout-math-table.hh"
+
+HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
+
+static inline const OT::MATH&
+_get_math (hb_face_t *face)
+{
+ if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH);
+
+ hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+
+retry:
+ const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math);
+
+ if (unlikely (!math))
+ {
+ hb_blob_t *blob = OT::Sanitizer<OT::MATH>::sanitize (face->reference_table (HB_OT_TAG_MATH));
+ math = OT::Sanitizer<OT::MATH>::lock_instance (blob);
+ if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math))
+ {
+ hb_blob_destroy (blob);
+ goto retry;
+ }
+ layout->math_blob = blob;
+ }
+
+ return *math;
+}
+
+/*
+ * OT::MATH
+ */
+
+/**
+ * hb_ot_math_has_data:
+ * @face: #hb_face_t to test
+ *
+ * This function allows to verify the presence of an OpenType MATH table on the
+ * face. If so, such a table will be loaded into memory and sanitized. You can
+ * then safely call other functions for math layout and shaping.
+ *
+ * Return value: #TRUE if face has a MATH table and #FALSE otherwise
+ *
+ * Since: 1.3.3
+ **/
+hb_bool_t
+hb_ot_math_has_data (hb_face_t *face)
+{
+ return &_get_math (face) != &OT::Null(OT::MATH);
+}
+
+/**
+ * hb_ot_math_get_constant:
+ * @font: #hb_font_t from which to retrieve the value
+ * @constant: #hb_ot_math_constant_t the constant to retrieve
+ *
+ * This function returns the requested math constants as a #hb_position_t.
+ * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
+ * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
+ * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is
+ * actually an integer between 0 and 100 representing that percentage.
+ *
+ * Return value: the requested constant or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_constant (hb_font_t *font,
+ hb_ot_math_constant_t constant)
+{
+ const OT::MATH &math = _get_math (font->face);
+ return math.get_constant(constant, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_italics_correction:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the italics correction of the glyph or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
+ hb_codepoint_t glyph)
+{
+ const OT::MATH &math = _get_math (font->face);
+ return math.get_math_glyph_info().get_italics_correction (glyph, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_top_accent_attachment:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the top accent attachment of the glyph or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
+ hb_codepoint_t glyph)
+{
+ const OT::MATH &math = _get_math (font->face);
+ return math.get_math_glyph_info().get_top_accent_attachment (glyph, font);
+}
+
+/**
+ * hb_ot_math_is_glyph_extended_shape:
+ * @font: a #hb_font_t to test
+ * @glyph: a glyph index to test
+ *
+ * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise
+ *
+ * Since: 1.3.3
+ **/
+hb_bool_t
+hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
+ hb_codepoint_t glyph)
+{
+ const OT::MATH &math = _get_math (face);
+ return math.get_math_glyph_info().is_extended_shape (glyph);
+}
+
+/**
+ * hb_ot_math_get_glyph_kerning:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ * @kern: the #hb_ot_math_kern_t from which to retrieve the value
+ * @correction_height: the correction height to use to determine the kerning.
+ *
+ * This function tries to retrieve the MathKern table for the specified font,
+ * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the
+ * MathKern table to find one value that is greater or equal to specified
+ * correction_height. If one is found the corresponding value from the list of
+ * kerns is returned and otherwise the last kern value is returned.
+ *
+ * Return value: requested kerning or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_kerning (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ hb_position_t correction_height)
+{
+ const OT::MATH &math = _get_math (font->face);
+ return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_variants:
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first variant to retrieve
+ * @variants_count: maximum number of variants to retrieve after start_offset
+ * (IN) and actual number of variants retrieved (OUT)
+ * @variants: array of size at least @variants_count to store the result
+ *
+ * This function tries to retrieve the MathGlyphConstruction for the specified
+ * font, glyph and direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
+ * of size variants as an array of hb_ot_math_glyph_variant_t structs.
+ *
+ * Return value: the total number of size variants available or 0
+ *
+ * Since: 1.3.3
+ **/
+unsigned int
+hb_ot_math_get_glyph_variants (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ unsigned int start_offset,
+ unsigned int *variants_count, /* IN/OUT */
+ hb_ot_math_glyph_variant_t *variants /* OUT */)
+{
+ const OT::MATH &math = _get_math (font->face);
+ return math.get_math_variants().get_glyph_variants (glyph, direction, font,
+ start_offset,
+ variants_count,
+ variants);
+}
+
+/**
+ * hb_ot_math_get_min_connector_overlap:
+ * @font: #hb_font_t from which to retrieve the value
+ * @direction: direction of the stretching
+ *
+ * This function tries to retrieve the MathVariants table for the specified
+ * font and returns the minimum overlap of connecting glyphs to draw a glyph
+ * assembly in the specified direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered.
+ *
+ * Return value: requested min connector overlap or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_min_connector_overlap (hb_font_t *font,
+ hb_direction_t direction)
+{
+ const OT::MATH &math = _get_math (font->face);
+ return math.get_math_variants().get_min_connector_overlap (direction, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_assembly:
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first glyph part to retrieve
+ * @parts_count: maximum number of glyph parts to retrieve after start_offset
+ * (IN) and actual number of parts retrieved (OUT)
+ * @parts: array of size at least @parts_count to store the result
+ * @italics_correction: italic correction of the glyph assembly
+ *
+ * This function tries to retrieve the GlyphAssembly for the specified font,
+ * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
+ * is considered. It provides the information necessary to draw the glyph
+ * assembly as an array of #hb_ot_math_glyph_part_t.
+ *
+ * Return value: the total number of parts in the glyph assembly
+ *
+ * Since: 1.3.3
+ **/
+unsigned int
+hb_ot_math_get_glyph_assembly (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ unsigned int start_offset,
+ unsigned int *parts_count, /* IN/OUT */
+ hb_ot_math_glyph_part_t *parts, /* OUT */
+ hb_position_t *italics_correction /* OUT */)
+{
+ const OT::MATH &math = _get_math (font->face);
+ return math.get_math_variants().get_glyph_parts (glyph, direction, font,
+ start_offset,
+ parts_count,
+ parts,
+ italics_correction);
+}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc
index 4da8990558a..56ec5cd65cf 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc
@@ -618,6 +618,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
NULL, /* decompose */
NULL, /* compose */
setup_masks_arabic,
+ NULL, /* disable_otl */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc
index be60e56feb8..42830ab6185 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc
@@ -40,6 +40,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
NULL, /* decompose */
NULL, /* compose */
NULL, /* setup_masks */
+ NULL, /* disable_otl */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hangul.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hangul.cc
index 5f4d98b70c8..eb95a28c09c 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hangul.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hangul.cc
@@ -419,6 +419,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
NULL, /* decompose */
NULL, /* compose */
setup_masks_hangul,
+ NULL, /* disable_otl */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hebrew.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hebrew.cc
index 32159002e93..96f24946165 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hebrew.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hebrew.cc
@@ -154,6 +154,18 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
return found;
}
+static bool
+disable_otl_hebrew (const hb_ot_shape_plan_t *plan)
+{
+ /* For Hebrew shaper, use fallback if GPOS does not have 'hebr'
+ * script. This matches Uniscribe better, and makes fonts like
+ * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work.
+ * See:
+ * https://github.com/behdad/harfbuzz/issues/347#issuecomment-267838368
+ */
+ return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r');
+}
+
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
{
@@ -168,6 +180,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
NULL, /* decompose */
compose_hebrew,
NULL, /* setup_masks */
+ disable_otl_hebrew,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc
index 94556f65470..b48fb561c39 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc
@@ -1713,33 +1713,28 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
switch (ab)
{
/* Don't decompose these. */
- case 0x0931u : return false;
- case 0x0B94u : return false;
+ case 0x0931u : return false; /* DEVANAGARI LETTER RRA */
+ case 0x0B94u : return false; /* TAMIL LETTER AU */
/*
* Decompose split matras that don't have Unicode decompositions.
*/
- case 0x0F77u : *a = 0x0FB2u; *b= 0x0F81u; return true;
- case 0x0F79u : *a = 0x0FB3u; *b= 0x0F81u; return true;
+ /* Khmer */
case 0x17BEu : *a = 0x17C1u; *b= 0x17BEu; return true;
case 0x17BFu : *a = 0x17C1u; *b= 0x17BFu; return true;
case 0x17C0u : *a = 0x17C1u; *b= 0x17C0u; return true;
case 0x17C4u : *a = 0x17C1u; *b= 0x17C4u; return true;
case 0x17C5u : *a = 0x17C1u; *b= 0x17C5u; return true;
- case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true;
- case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true;
- case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true;
- case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
- case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
+
#if 0
+ /* Gujarati */
/* This one has no decomposition in Unicode, but needs no decomposition either. */
/* case 0x0AC9u : return false; */
+
+ /* Oriya */
case 0x0B57u : *a = no decomp, -> RIGHT; return true;
- case 0x1C29u : *a = no decomp, -> LEFT; return true;
- case 0xA9C0u : *a = no decomp, -> RIGHT; return true;
- case 0x111BuF : *a = no decomp, -> ABOVE; return true;
#endif
}
@@ -1819,6 +1814,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
decompose_indic,
compose_indic,
setup_masks_indic,
+ NULL, /* disable_otl */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc
index 577d790c783..bb68622e2a7 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc
@@ -521,6 +521,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
NULL, /* decompose */
NULL, /* compose */
NULL, /* setup_masks */
+ NULL, /* disable_otl */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
@@ -538,6 +539,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
NULL, /* decompose */
NULL, /* compose */
setup_masks_myanmar,
+ NULL, /* disable_otl */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
false, /* fallback_position */
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-private.hh
index fb0c7040617..39572dfe007 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-private.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-private.hh
@@ -146,6 +146,14 @@ struct hb_ot_complex_shaper_t
hb_buffer_t *buffer,
hb_font_t *font);
+ /* disable_otl()
+ * Called during shape().
+ * If set and returns true, GDEF/GSUB/GPOS of the font are ignored
+ * and fallback operations used.
+ * May be NULL.
+ */
+ bool (*disable_otl) (const hb_ot_shape_plan_t *plan);
+
hb_ot_shape_zero_width_marks_type_t zero_width_marks;
bool fallback_position;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-thai.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-thai.cc
index 4322b0d1d63..e6f80f59e7f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-thai.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-thai.cc
@@ -376,6 +376,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
NULL, /* decompose */
NULL, /* compose */
NULL, /* setup_masks */
+ NULL, /* disable_otl */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
false,/* fallback_position */
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-tibetan.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-tibetan.cc
index a77b531daa5..aadf59f5add 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-tibetan.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-tibetan.cc
@@ -57,6 +57,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
NULL, /* decompose */
NULL, /* compose */
NULL, /* setup_masks */
+ NULL, /* disable_otl */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use.cc
index 045ead52f68..5b19d5d74a7 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use.cc
@@ -559,6 +559,47 @@ reorder (const hb_ot_shape_plan_t *plan,
}
static bool
+decompose_use (const hb_ot_shape_normalize_context_t *c,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b)
+{
+ switch (ab)
+ {
+ /* Chakma:
+ * Special case where the Unicode decomp gives matras in the wrong order
+ * for cluster validation.
+ */
+ case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
+ case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
+
+ /*
+ * Decompose split matras that don't have Unicode decompositions.
+ */
+
+ /* Limbu */
+ case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true;
+ case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true;
+
+ /* Balinese */
+ case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true;
+
+#if 0
+ /* Lepcha */
+ case 0x1C29u : *a = no decomp, -> LEFT; return true;
+
+ /* Javanese */
+ case 0xA9C0u : *a = no decomp, -> RIGHT; return true;
+
+ /* Sharada */
+ case 0x111BFu : *a = no decomp, -> ABOVE; return true;
+#endif
+ }
+
+ return (bool) c->unicode->decompose (ab, a, b);
+}
+
+static bool
compose_use (const hb_ot_shape_normalize_context_t *c,
hb_codepoint_t a,
hb_codepoint_t b,
@@ -582,9 +623,10 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
NULL, /* preprocess_text */
NULL, /* postprocess_glyphs */
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
- NULL, /* decompose */
+ decompose_use,
compose_use,
setup_masks_use,
+ NULL, /* disable_otl */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
false, /* fallback_position */
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-private.hh
index 54ac2c3cf7c..594e54c026a 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-private.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-private.hh
@@ -77,11 +77,13 @@ struct hb_ot_shape_planner_t
map (face, &props) {}
~hb_ot_shape_planner_t (void) { map.finish (); }
- inline void compile (hb_ot_shape_plan_t &plan)
+ inline void compile (hb_ot_shape_plan_t &plan,
+ const int *coords,
+ unsigned int num_coords)
{
plan.props = props;
plan.shaper = shaper;
- map.compile (plan.map);
+ map.compile (plan.map, coords, num_coords);
plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
index 7811cb7f8e8..ddd6662e845 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
@@ -69,6 +69,9 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
{
hb_ot_map_builder_t *map = &planner->map;
+ map->add_global_bool_feature (HB_TAG('r','v','r','n'));
+ map->add_gsub_pause (NULL);
+
switch (props->direction) {
case HB_DIRECTION_LTR:
map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
@@ -163,7 +166,9 @@ _hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
hb_ot_shaper_shape_plan_data_t *
_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
const hb_feature_t *user_features,
- unsigned int num_user_features)
+ unsigned int num_user_features,
+ const int *coords,
+ unsigned int num_coords)
{
hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
if (unlikely (!plan))
@@ -173,9 +178,10 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
planner.shaper = hb_ot_shape_complex_categorize (&planner);
- hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features);
+ hb_ot_shape_collect_features (&planner, &shape_plan->props,
+ user_features, num_user_features);
- planner.compile (*plan);
+ planner.compile (*plan, coords, num_coords);
if (plan->shaper->data_create) {
plan->data = plan->shaper->data_create (plan);
@@ -212,6 +218,8 @@ struct hb_ot_shape_context_t
unsigned int num_user_features;
/* Transient stuff */
+ bool fallback_positioning;
+ bool fallback_glyph_classes;
hb_direction_t target_direction;
};
@@ -524,6 +532,32 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
}
static inline void
+hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
+{
+ unsigned int count = c->buffer->len;
+ hb_glyph_info_t *info = c->buffer->info;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ hb_ot_layout_glyph_props_flags_t klass;
+
+ /* Never mark default-ignorables as marks.
+ * They won't get in the way of lookups anyway,
+ * but having them as mark will cause them to be skipped
+ * over if the lookup-flag says so, but at least for the
+ * Mongolian variation selectors, looks like Uniscribe
+ * marks them as non-mark. Some Mongolian fonts without
+ * GDEF rely on this. Another notable character that
+ * this applies to is COMBINING GRAPHEME JOINER. */
+ klass = (_hb_glyph_info_get_general_category (&info[i]) !=
+ HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
+ _hb_glyph_info_is_default_ignorable (&info[i])) ?
+ HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
+ HB_OT_LAYOUT_GLYPH_PROPS_MARK;
+ _hb_glyph_info_set_glyph_props (&info[i], klass);
+ }
+}
+
+static inline void
hb_ot_substitute_default (hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
@@ -539,7 +573,7 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c)
hb_ot_shape_setup_masks (c);
/* This is unfortunate to go here, but necessary... */
- if (!hb_ot_layout_has_positioning (c->face))
+ if (c->fallback_positioning)
_hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
hb_ot_map_glyphs_fast (buffer);
@@ -554,6 +588,9 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
hb_ot_layout_substitute_start (c->font, buffer);
+ if (!hb_ot_layout_has_glyph_classes (c->face))
+ hb_synthesize_glyph_classes (c);
+
c->plan->substitute (c->font, buffer);
return;
@@ -632,14 +669,12 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
_hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
}
-static inline bool
+static inline void
hb_ot_position_complex (hb_ot_shape_context_t *c)
{
hb_ot_layout_position_start (c->font, c->buffer);
- bool ret = false;
unsigned int count = c->buffer->len;
- bool has_positioning = (bool) hb_ot_layout_has_positioning (c->face);
/* If the font has no GPOS, AND, no fallback positioning will
* happen, AND, direction is forward, then when zeroing mark
@@ -650,8 +685,9 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
* If fallback positinoing happens or GPOS is present, we don't
* care.
*/
- bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallback_position ||
- HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction));
+ bool adjust_offsets_when_zeroing = c->fallback_positioning &&
+ !c->plan->shaper->fallback_position &&
+ HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
switch (c->plan->shaper->zero_width_marks)
{
@@ -665,7 +701,7 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
break;
}
- if (has_positioning)
+ if (likely (!c->fallback_positioning))
{
hb_glyph_info_t *info = c->buffer->info;
hb_glyph_position_t *pos = c->buffer->pos;
@@ -688,7 +724,6 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
&pos[i].x_offset,
&pos[i].y_offset);
- ret = true;
}
switch (c->plan->shaper->zero_width_marks)
@@ -707,8 +742,6 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
hb_ot_layout_position_finish_advances (c->font, c->buffer);
hb_ot_zero_width_default_ignorables (c);
hb_ot_layout_position_finish_offsets (c->font, c->buffer);
-
- return ret;
}
static inline void
@@ -718,9 +751,9 @@ hb_ot_position (hb_ot_shape_context_t *c)
hb_ot_position_default (c);
- hb_bool_t fallback = !hb_ot_position_complex (c);
+ hb_ot_position_complex (c);
- if (fallback && c->plan->shaper->fallback_position)
+ if (c->fallback_positioning && c->plan->shaper->fallback_position)
_hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
@@ -728,7 +761,7 @@ hb_ot_position (hb_ot_shape_context_t *c)
/* Visual fallback goes here. */
- if (fallback)
+ if (c->fallback_positioning)
_hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
_hb_buffer_deallocate_gsubgpos_vars (c->buffer);
@@ -748,6 +781,11 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
(unsigned) HB_BUFFER_MAX_LEN_MIN);
}
+ bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan);
+ //c->fallback_substitute = disable_otl || !hb_ot_layout_has_substitution (c->face);
+ c->fallback_positioning = disable_otl || !hb_ot_layout_has_positioning (c->face);
+ c->fallback_glyph_classes = disable_otl || !hb_ot_layout_has_glyph_classes (c->face);
+
/* Save the original direction, we use it later. */
c->target_direction = c->buffer->props.direction;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh
index c45be6f2f7f..666af6260b4 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh
@@ -689,17 +689,20 @@ _hb_debug_msg_va (const char *what,
fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), "");
if (indented) {
-/* One may want to add ASCII version of these. See:
- * https://bugs.freedesktop.org/show_bug.cgi?id=50970 */
#define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
#define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
#define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
#define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
#define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */
- static const char bars[] = VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
+ static const char bars[] =
+ VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
+ VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
+ VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
+ VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
+ VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
fprintf (stderr, "%2u %s" VRBAR "%s",
level,
- bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), (unsigned int) (sizeof (VBAR) - 1) * level),
+ bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
} else
fprintf (stderr, " " VRBAR LBAR);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan-private.hh
index 607da5e7791..aa0413a272d 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan-private.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan-private.hh
@@ -47,12 +47,17 @@ struct hb_shape_plan_t
hb_feature_t *user_features;
unsigned int num_user_features;
+ int *coords;
+ unsigned int num_coords;
+
struct hb_shaper_data_t shaper_data;
};
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
- , const hb_feature_t *user_features \
- , unsigned int num_user_features
+ , const hb_feature_t *user_features \
+ , unsigned int num_user_features \
+ , const int *coords \
+ , unsigned int num_coords
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan);
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
index 87231fb33a6..600faaeb18c 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
@@ -46,11 +46,14 @@ static void
hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
const hb_feature_t *user_features,
unsigned int num_user_features,
+ const int *coords,
+ unsigned int num_coords,
const char * const *shaper_list)
{
DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
- "num_features=%d shaper_list=%p",
+ "num_features=%d num_coords=%d shaper_list=%p",
num_user_features,
+ num_coords,
shaper_list);
const hb_shaper_pair_t *shapers = _hb_shapers_get ();
@@ -59,7 +62,9 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
HB_STMT_START { \
if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \
HB_SHAPER_DATA (shaper, shape_plan) = \
- HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_features, num_user_features); \
+ HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \
+ user_features, num_user_features, \
+ coords, num_coords); \
shape_plan->shaper_func = _hb_##shaper##_shape; \
shape_plan->shaper_name = #shaper; \
return; \
@@ -115,14 +120,31 @@ hb_shape_plan_create (hb_face_t *face,
unsigned int num_user_features,
const char * const *shaper_list)
{
+ return hb_shape_plan_create2 (face, props,
+ user_features, num_user_features,
+ NULL, 0,
+ shaper_list);
+}
+
+hb_shape_plan_t *
+hb_shape_plan_create2 (hb_face_t *face,
+ const hb_segment_properties_t *props,
+ const hb_feature_t *user_features,
+ unsigned int num_user_features,
+ const int *orig_coords,
+ unsigned int num_coords,
+ const char * const *shaper_list)
+{
DEBUG_MSG_FUNC (SHAPE_PLAN, NULL,
- "face=%p num_features=%d shaper_list=%p",
+ "face=%p num_features=%d num_coords=%d shaper_list=%p",
face,
num_user_features,
+ num_coords,
shaper_list);
hb_shape_plan_t *shape_plan;
hb_feature_t *features = NULL;
+ int *coords = NULL;
if (unlikely (!face))
face = hb_face_get_empty ();
@@ -130,7 +152,14 @@ hb_shape_plan_create (hb_face_t *face,
return hb_shape_plan_get_empty ();
if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
return hb_shape_plan_get_empty ();
- if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) {
+ if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
+ {
+ free (features);
+ return hb_shape_plan_get_empty ();
+ }
+ if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
+ {
+ free (coords);
free (features);
return hb_shape_plan_get_empty ();
}
@@ -145,8 +174,15 @@ hb_shape_plan_create (hb_face_t *face,
shape_plan->user_features = features;
if (num_user_features)
memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+ shape_plan->num_coords = num_coords;
+ shape_plan->coords = coords;
+ if (num_coords)
+ memcpy (coords, orig_coords, num_coords * sizeof (int));
- hb_shape_plan_plan (shape_plan, user_features, num_user_features, shaper_list);
+ hb_shape_plan_plan (shape_plan,
+ user_features, num_user_features,
+ coords, num_coords,
+ shaper_list);
return shape_plan;
}
@@ -176,6 +212,9 @@ hb_shape_plan_get_empty (void)
NULL, /* user_features */
0, /* num_user_featurs */
+ NULL, /* coords */
+ 0, /* num_coords */
+
{
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
#include "hb-shaper-list.hh"
@@ -220,6 +259,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
#undef HB_SHAPER_IMPLEMENT
free (shape_plan->user_features);
+ free (shape_plan->coords);
free (shape_plan);
}
@@ -351,6 +391,8 @@ struct hb_shape_plan_proposal_t
const char * const *shaper_list;
const hb_feature_t *user_features;
unsigned int num_user_features;
+ const int *coords;
+ unsigned int num_coords;
hb_shape_func_t *shaper_func;
};
@@ -358,12 +400,26 @@ static inline hb_bool_t
hb_shape_plan_user_features_match (const hb_shape_plan_t *shape_plan,
const hb_shape_plan_proposal_t *proposal)
{
- if (proposal->num_user_features != shape_plan->num_user_features) return false;
+ if (proposal->num_user_features != shape_plan->num_user_features)
+ return false;
for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++)
if (proposal->user_features[i].tag != shape_plan->user_features[i].tag ||
proposal->user_features[i].value != shape_plan->user_features[i].value ||
proposal->user_features[i].start != shape_plan->user_features[i].start ||
- proposal->user_features[i].end != shape_plan->user_features[i].end) return false;
+ proposal->user_features[i].end != shape_plan->user_features[i].end)
+ return false;
+ return true;
+}
+
+static inline hb_bool_t
+hb_shape_plan_coords_match (const hb_shape_plan_t *shape_plan,
+ const hb_shape_plan_proposal_t *proposal)
+{
+ if (proposal->num_coords != shape_plan->num_coords)
+ return false;
+ for (unsigned int i = 0, n = proposal->num_coords; i < n; i++)
+ if (proposal->coords[i] != shape_plan->coords[i])
+ return false;
return true;
}
@@ -373,6 +429,7 @@ hb_shape_plan_matches (const hb_shape_plan_t *shape_plan,
{
return hb_segment_properties_equal (&shape_plan->props, &proposal->props) &&
hb_shape_plan_user_features_match (shape_plan, proposal) &&
+ hb_shape_plan_coords_match (shape_plan, proposal) &&
((shape_plan->default_shaper_list && proposal->shaper_list == NULL) ||
(shape_plan->shaper_func == proposal->shaper_func));
}
@@ -389,6 +446,13 @@ hb_non_global_user_features_present (const hb_feature_t *user_features,
return false;
}
+static inline hb_bool_t
+hb_coords_present (const int *coords,
+ unsigned int num_coords)
+{
+ return num_coords != 0;
+}
+
/**
* hb_shape_plan_create_cached:
* @face:
@@ -410,6 +474,21 @@ hb_shape_plan_create_cached (hb_face_t *face,
unsigned int num_user_features,
const char * const *shaper_list)
{
+ return hb_shape_plan_create_cached2 (face, props,
+ user_features, num_user_features,
+ NULL, 0,
+ shaper_list);
+}
+
+hb_shape_plan_t *
+hb_shape_plan_create_cached2 (hb_face_t *face,
+ const hb_segment_properties_t *props,
+ const hb_feature_t *user_features,
+ unsigned int num_user_features,
+ const int *coords,
+ unsigned int num_coords,
+ const char * const *shaper_list)
+{
DEBUG_MSG_FUNC (SHAPE_PLAN, NULL,
"face=%p num_features=%d shaper_list=%p",
face,
@@ -456,16 +535,21 @@ retry:
/* Not found. */
- hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list);
+ hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props,
+ user_features, num_user_features,
+ coords, num_coords,
+ shaper_list);
/* Don't add to the cache if face is inert. */
if (unlikely (hb_object_is_inert (face)))
return shape_plan;
/* Don't add the plan to the cache if there were user features with non-global ranges */
-
if (hb_non_global_user_features_present (user_features, num_user_features))
return shape_plan;
+ /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */
+ if (hb_coords_present (coords, num_coords))
+ return shape_plan;
hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t));
if (unlikely (!node))
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.h
index aa5e0c7d6f5..b62ae7ca350 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.h
@@ -53,6 +53,25 @@ hb_shape_plan_create_cached (hb_face_t *face,
const char * const *shaper_list);
HB_EXTERN hb_shape_plan_t *
+hb_shape_plan_create2 (hb_face_t *face,
+ const hb_segment_properties_t *props,
+ const hb_feature_t *user_features,
+ unsigned int num_user_features,
+ const int *coords,
+ unsigned int num_coords,
+ const char * const *shaper_list);
+
+HB_EXTERN hb_shape_plan_t *
+hb_shape_plan_create_cached2 (hb_face_t *face,
+ const hb_segment_properties_t *props,
+ const hb_feature_t *user_features,
+ unsigned int num_user_features,
+ const int *coords,
+ unsigned int num_coords,
+ const char * const *shaper_list);
+
+
+HB_EXTERN hb_shape_plan_t *
hb_shape_plan_get_empty (void);
HB_EXTERN hb_shape_plan_t *
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
index 41a4fc500ea..706f14420d4 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
@@ -373,7 +373,10 @@ hb_shape_full (hb_font_t *font,
unsigned int num_features,
const char * const *shaper_list)
{
- hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
+ hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props,
+ features, num_features,
+ font->coords, font->num_coords,
+ shaper_list);
hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
hb_shape_plan_destroy (shape_plan);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc
index 07007a64022..6e4db01495f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc
@@ -587,7 +587,9 @@ struct hb_uniscribe_shaper_shape_plan_data_t {};
hb_uniscribe_shaper_shape_plan_data_t *
_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
- unsigned int num_user_features HB_UNUSED)
+ unsigned int num_user_features HB_UNUSED,
+ const int *coords HB_UNUSED,
+ unsigned int num_coords HB_UNUSED)
{
return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}