From 22037499b42d9fce100ee771a229b961b5e1cb2d Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sun, 4 Aug 2019 11:31:31 +0430 Subject: [PATCH] [style] New experimental API, hb_style_get_value Searches variation axes of a hb_font_t object for a specific axis first, if not set, then tries to get default style values from different tables of the font. --- docs/harfbuzz-sections.txt | 6 ++ src/Makefile.sources | 2 + src/harfbuzz.cc | 1 + src/hb-config.hh | 2 +- src/hb-ot-face-table-list.hh | 5 +- src/hb-ot-stat-table.hh | 73 +++++++++++++++ src/hb-style.cc | 110 ++++++++++++++++++++++ src/hb-style.h | 75 +++++++++++++++ src/hb-subset-plan.cc | 2 +- src/hb.h | 1 + test/api/Makefile.am | 1 + test/api/fonts/aat-fdsc.ttf | Bin 0 -> 556 bytes test/api/test-ot-face.c | 6 ++ test/api/test-style.c | 177 +++++++++++++++++++++++++++++++++++ 14 files changed, 457 insertions(+), 4 deletions(-) create mode 100644 src/hb-style.cc create mode 100644 src/hb-style.h create mode 100644 test/api/fonts/aat-fdsc.ttf create mode 100644 test/api/test-style.c diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index bcad37a77..3549ea406 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -714,6 +714,12 @@ hb_shape_plan_set_user_data hb_shape_plan_t +
+hb-style +hb_style_tag_t +hb_style_get_value +
+
hb-unicode HB_UNICODE_MAX diff --git a/src/Makefile.sources b/src/Makefile.sources index 81b5cde7a..d8fe508be 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -159,6 +159,7 @@ HB_BASE_sources = \ hb-shaper.hh \ hb-static.cc \ hb-string-array.hh \ + hb-style.cc \ hb-ucd-table.hh \ hb-ucd.cc \ hb-unicode-emoji-table.hh \ @@ -213,6 +214,7 @@ HB_BASE_headers = \ hb-set.h \ hb-shape-plan.h \ hb-shape.h \ + hb-style.h \ hb-unicode.h \ hb-version.h \ hb.h \ diff --git a/src/harfbuzz.cc b/src/harfbuzz.cc index 6a07a9e0d..226d013d2 100644 --- a/src/harfbuzz.cc +++ b/src/harfbuzz.cc @@ -43,6 +43,7 @@ #include "hb-shape.cc" #include "hb-shaper.cc" #include "hb-static.cc" +#include "hb-style.cc" #include "hb-ucd.cc" #include "hb-unicode.cc" #include "hb-glib.cc" diff --git a/src/hb-config.hh b/src/hb-config.hh index 07659fad1..fc8d424bf 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -76,7 +76,7 @@ #define HB_NO_SETLOCALE #define HB_NO_OT_FONT_GLYPH_NAMES #define HB_NO_OT_SHAPE_FRACTIONS -#define HB_NO_STAT +#define HB_NO_STYLE #define HB_NO_SUBSET_LAYOUT #define HB_NO_VAR #endif diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index 6fa9baf13..5519d4fdf 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -53,13 +53,14 @@ HB_OT_ACCELERATOR (OT, cmap) HB_OT_TABLE (OT, hhea) HB_OT_ACCELERATOR (OT, hmtx) HB_OT_TABLE (OT, OS2) -#if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS) +#if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS) || !defined(HB_NO_STYLE) HB_OT_ACCELERATOR (OT, post) #endif #ifndef HB_NO_NAME HB_OT_ACCELERATOR (OT, name) #endif -#ifndef HB_NO_STAT +#ifndef HB_NO_STYLE +HB_OT_TABLE (AAT, fdsc) HB_OT_TABLE (OT, STAT) #endif #ifndef HB_NO_META diff --git a/src/hb-ot-stat-table.hh b/src/hb-ot-stat-table.hh index 88135234d..655064bdf 100644 --- a/src/hb-ot-stat-table.hh +++ b/src/hb-ot-stat-table.hh @@ -59,6 +59,9 @@ enum struct AxisValueFormat1 { + unsigned int get_axis_index () const { return axisIndex; } + float get_value () const { return value.to_float (); } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } bool sanitize (hb_sanitize_context_t *c) const @@ -84,6 +87,9 @@ struct AxisValueFormat1 struct AxisValueFormat2 { + unsigned int get_axis_index () const { return axisIndex; } + float get_value () const { return nominalValue.to_float (); } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } bool sanitize (hb_sanitize_context_t *c) const @@ -113,6 +119,9 @@ struct AxisValueFormat2 struct AxisValueFormat3 { + unsigned int get_axis_index () const { return axisIndex; } + float get_value () const { return value.to_float (); } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } bool sanitize (hb_sanitize_context_t *c) const @@ -140,6 +149,9 @@ struct AxisValueFormat3 struct AxisValueRecord { + unsigned int get_axis_index () const { return axisIndex; } + float get_value () const { return value.to_float (); } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -157,6 +169,9 @@ struct AxisValueRecord struct AxisValueFormat4 { + const AxisValueRecord &get_axis_record (unsigned int axis_index) const + { return axisValues.as_array (axisCount)[axis_index]; } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } bool sanitize (hb_sanitize_context_t *c) const @@ -183,6 +198,30 @@ struct AxisValueFormat4 struct AxisValue { + bool get_value (unsigned int axis_index) const + { + switch (u.format) + { + case 1: return u.format1.get_value (); + case 2: return u.format2.get_value (); + case 3: return u.format3.get_value (); + case 4: return u.format4.get_axis_record (axis_index).get_value (); + default:return 0; + } + } + + unsigned int get_axis_index () const + { + switch (u.format) + { + case 1: return u.format1.get_axis_index (); + case 2: return u.format2.get_axis_index (); + case 3: return u.format3.get_axis_index (); + /* case 4: Makes more sense for variable fonts which are handled by fvar in hb-style */ + default:return -1; + } + } + hb_ot_name_id_t get_value_name_id () const { switch (u.format) @@ -226,6 +265,8 @@ struct AxisValue struct StatAxisRecord { + int cmp (hb_tag_t key) const { return tag.cmp (key); } + hb_ot_name_id_t get_name_id () const { return nameID; } bool sanitize (hb_sanitize_context_t *c) const @@ -251,6 +292,38 @@ struct STAT bool has_data () const { return version.to_int (); } + bool find_axis_index (hb_tag_t tag, unsigned int *axis_index) const + { + hb_array_t axes = get_design_axes (); + /* TODO: add lfind in hb_array_t and use it in here and fvar's find_axis_info */ + for (unsigned int i = 0; i < axes.length; i++) + if (!axes[i].cmp (tag)) + { + *axis_index = i; + return true; + } + return false; + } + + bool get_value (hb_tag_t tag, float *value) const + { + unsigned int axis_index; + if (!find_axis_index (tag, &axis_index)) return false; + + hb_array_t> axis_values = get_axis_value_offsets (); + for (unsigned int i = 0; i < axis_values.length; i++) + { + const AxisValue& axis_value = (this + axis_values[i]); + if (axis_value.get_axis_index () == axis_index) + { + if (value) + *value = axis_value.get_value (axis_index); + return true; + } + } + return false; + } + unsigned get_design_axis_count () const { return designAxisCount; } hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const diff --git a/src/hb-style.cc b/src/hb-style.cc new file mode 100644 index 000000000..dd54fdd9d --- /dev/null +++ b/src/hb-style.cc @@ -0,0 +1,110 @@ +/* + * Copyright © 2019 Ebrahim Byagowi + * + * 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. + */ + +#include "hb.hh" + +#ifndef HB_NO_STYLE + +#include "hb-aat-fdsc-table.hh" +#include "hb-ot-var-avar-table.hh" +#include "hb-ot-var-fvar-table.hh" +#include "hb-ot-stat-table.hh" +#include "hb-ot-os2-table.hh" +#include "hb-ot-head-table.hh" +#include "hb-ot-post-table.hh" +#include "hb-ot-face.hh" + +/** + * hb_style_get_value: + * @font: a #hb_font_t object. + * @style_tag: a style tag. + * + * Searches variation axes of a hb_font_t object for a specific axis first, + * if not set, then tries to get default style values from different + * tables of the font. + * + * Returns: Corresponding axis or default value to a style tag. + * + * Since: REPLACEME + **/ +float +hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag) +{ + hb_face_t *face = font->face; + +#ifndef HB_NO_VAR + hb_ot_var_axis_info_t axis; + if (hb_ot_var_find_axis_info (face, style_tag, &axis)) + { + if (axis.axis_index < font->num_coords) return font->design_coords[axis.axis_index]; + /* If a face is variable, fvar's default_value is better than STAT records */ + return axis.default_value; + } +#endif + + /* STAT */ + float value; + if (face->table.STAT->get_value (style_tag, &value)) + return value; + + /* Check Apple's fdsc as OS2 table is optional in AAT */ + const AAT::FontDescriptor &descriptor = face->table.fdsc->get_descriptor (style_tag); + if (descriptor.has_data ()) + { + float value = descriptor.get_value (); + /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fdsc.html */ + /* Percent weight relative to regular weight. */ + if (style_tag == HB_STYLE_TAG_WEIGHT) value *= 400.f; + /* Percent width relative to regular width. */ + if (style_tag == HB_STYLE_TAG_WIDTH) value *= 100.f; + return value; + } + + switch ((unsigned) style_tag) + { + case HB_STYLE_TAG_ITALIC: + return face->table.OS2->is_italic () || face->table.head->is_italic () ? 1 : 0; + case HB_STYLE_TAG_OPTICAL_SIZE: + { + unsigned int lower, upper; + return face->table.OS2->v5 ().get_optical_size (&lower, &upper) + ? (float) (lower + upper) / 2.f + : 12.f; + } + case HB_STYLE_TAG_SLANT: + return face->table.post->table->italicAngle.to_float (); + case HB_STYLE_TAG_WIDTH: + return face->table.OS2->has_data () + ? face->table.OS2->get_width () + : (face->table.head->is_condensed () ? 75 : 100); + case HB_STYLE_TAG_WEIGHT: + return face->table.OS2->has_data () + ? face->table.OS2->usWeightClass + : (face->table.head->is_bold () ? 700 : 400); + default: + return 0; + } +} + +#endif diff --git a/src/hb-style.h b/src/hb-style.h new file mode 100644 index 000000000..ee84b7232 --- /dev/null +++ b/src/hb-style.h @@ -0,0 +1,75 @@ +/* + * Copyright © 2019 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_H_IN +#error "Include instead." +#endif + +#ifndef HB_STYLE_H +#define HB_STYLE_H + +#include "hb.h" + +HB_BEGIN_DECLS + + +/** + * hb_style_tag_t: + * @HB_STYLE_TAG_ITALIC: Used to vary between non-italic and italic. + * A value of 0 can be interpreted as "Roman" (non-italic); a value of 1 can + * be interpreted as (fully) italic. + * @HB_STYLE_TAG_OPTICAL_SIZE: Used to vary design to suit different text sizes. + * Non-zero. Values can be interpreted as text size, in points. + * @HB_STYLE_TAG_SLANT: Used to vary between upright and slanted text. Values + * must be greater than -90 and less than +90. Values can be interpreted as + * the angle, in counter-clockwise degrees, of oblique slant from whatever the + * designer considers to be upright for that font design. + * @HB_STYLE_TAG_WIDTH: Used to vary width of text from narrower to wider. + * Non-zero. Values can be interpreted as a percentage of whatever the font + * designer considers “normal width” for that font design. + * @HB_STYLE_TAG_WEIGHT: Used to vary stroke thicknesses or other design details + * to give variation from lighter to blacker. Values can be interpreted in direct + * comparison to values for usWeightClass in the OS/2 table, + * or the CSS font-weight property. + * + * Defined by https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg + * + * Since: REPLACEME + **/ +typedef enum { + HB_STYLE_TAG_ITALIC = HB_TAG ('i','t','a','l'), + HB_STYLE_TAG_OPTICAL_SIZE = HB_TAG ('o','p','s','z'), + HB_STYLE_TAG_SLANT = HB_TAG ('s','l','n','t'), + HB_STYLE_TAG_WIDTH = HB_TAG ('w','d','t','h'), + HB_STYLE_TAG_WEIGHT = HB_TAG ('w','g','h','t'), + + _HB_STYLE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/ +} hb_style_tag_t; + +HB_EXTERN float +hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag); + +HB_END_DECLS + +#endif /* HB_STYLE_H */ diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 232131c59..9a5d74b64 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -301,7 +301,7 @@ static void _nameid_closure (hb_face_t *face, hb_set_t *nameids) { -#ifndef HB_NO_STAT +#ifndef HB_NO_STYLE face->table.STAT->collect_name_ids (nameids); #endif #ifndef HB_NO_VAR diff --git a/src/hb.h b/src/hb.h index b0cc06c9e..360686ca6 100644 --- a/src/hb.h +++ b/src/hb.h @@ -39,6 +39,7 @@ #include "hb-set.h" #include "hb-shape.h" #include "hb-shape-plan.h" +#include "hb-style.h" #include "hb-unicode.h" #include "hb-version.h" diff --git a/test/api/Makefile.am b/test/api/Makefile.am index 0170b6807..01e12c570 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -52,6 +52,7 @@ TEST_PROGS = \ test-ot-metrics-tt-var \ test-set \ test-shape \ + test-style \ test-subset \ test-subset-cmap \ test-subset-drop-tables \ diff --git a/test/api/fonts/aat-fdsc.ttf b/test/api/fonts/aat-fdsc.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3f82869ead55c8b74350363426e53a7816b6f6cc GIT binary patch literal 556 zcmZvYze~eV5XbK&X{fQKB4ULiJVZfI{EaSxRRl)|2ge!`(+o))NTAh8oCF75-TVXm z6C4~I9CUGVaC8aIZbJRuODsh^c=zseckg~Y5=3Ot8R;bV4;ELdqcfL8Viw*bC$u9f zrEB18@Vw{7PJQlt3;YdUY6d6X#;#chKZ3{oW7{oHmTlN~IO{$f=C(cs`vYg%50kDg zVUf6iGK02b)3D-u=Fsj&T7_ze7r`=W#|h?wh<9ennYOlB22xq-5 zJdN?KOXV+;#stBeEVHk<(x3=cTf>X&O%}I^aY7{;y2LLO;JMMB;kn9g@ky& + +/* Unit tests for hb-style.h */ + +#define assert_cmpfloat(n1, n2) g_assert_cmpint ((int) (n1 * 100.f), ==, (int) (n2 * 100.f)) + +static void +test_empty_face (void) +{ + hb_font_t *empty = hb_font_get_empty (); + + assert_cmpfloat (hb_style_get_value (empty, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (empty, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (empty, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (empty, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (empty, HB_STYLE_TAG_WEIGHT), 400); +} + +static void +test_regular_face (void) +{ + hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf"); + hb_font_t *font = hb_font_create (face); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 400); + + hb_font_destroy (font); + hb_face_destroy (face); +} + +static void +test_face_fdsc (void) +{ + hb_face_t *face = hb_test_open_font_file ("fonts/aat-fdsc.ttf"); + hb_font_t *font = hb_font_create (face); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 24); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 6.33f); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 400); + + hb_font_destroy (font); + hb_face_destroy (face); +} + +static void +test_face_user_setting (void) +{ + hb_face_t *face = hb_test_open_font_file ("fonts/AdobeVFPrototype_vsindex.otf"); + hb_font_t *font = hb_font_create (face); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 389.34f); /* its default weight */ + assert_cmpfloat (hb_style_get_value (font, (hb_style_tag_t) HB_TAG ('C','N','T','R')), 0); + + hb_font_set_var_named_instance (font, 0); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 200); + assert_cmpfloat (hb_style_get_value (font, (hb_style_tag_t) HB_TAG ('C','N','T','R')), 0); + + hb_font_set_var_named_instance (font, 1); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 300); + assert_cmpfloat (hb_style_get_value (font, (hb_style_tag_t) HB_TAG ('C','N','T','R')), 0); + + hb_font_set_var_named_instance (font, 2); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 400); + assert_cmpfloat (hb_style_get_value (font, (hb_style_tag_t) HB_TAG ('C','N','T','R')), 0); + + hb_font_set_var_named_instance (font, 3); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT),600); + assert_cmpfloat (hb_style_get_value (font, (hb_style_tag_t) HB_TAG ('C','N','T','R')), 0); + + hb_font_set_var_named_instance (font, 4); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 700); + assert_cmpfloat (hb_style_get_value (font, (hb_style_tag_t) HB_TAG ('C','N','T','R')), 0); + + hb_font_set_var_named_instance (font, 5); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 900); + assert_cmpfloat (hb_style_get_value (font, (hb_style_tag_t) HB_TAG ('C','N','T','R')), 0); + + hb_font_set_var_named_instance (font, 6); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 900); + assert_cmpfloat (hb_style_get_value (font, (hb_style_tag_t) HB_TAG ('C','N','T','R')), 50); + + hb_font_set_var_named_instance (font, 7); + + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_ITALIC), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_OPTICAL_SIZE), 12); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_SLANT), 0); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WIDTH), 100); + assert_cmpfloat (hb_style_get_value (font, HB_STYLE_TAG_WEIGHT), 900); + assert_cmpfloat (hb_style_get_value (font, (hb_style_tag_t) HB_TAG ('C','N','T','R')), 100); + + hb_font_destroy (font); + hb_face_destroy (face); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_empty_face); + hb_test_add (test_regular_face); + hb_test_add (test_face_fdsc); + hb_test_add (test_face_user_setting); + + return hb_test_run (); +}