From 5fbcb992bd7887f95b1cf2ca045c9226de8148fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Thu, 25 Aug 2016 10:47:15 +0200 Subject: [PATCH 01/32] MATH Table: Add API to check availability of math data. --- src/Makefile.sources | 1 + src/hb-ot-layout-math-table.hh | 60 ++++++++++++++++ src/hb-ot-layout-private.hh | 3 + src/hb-ot-layout.cc | 45 ++++++++++++ src/hb-ot-layout.h | 7 ++ test/api/Makefile.am | 14 +++- test/api/fonts/MathTestFontEmpty.otf | Bin 0 -> 14320 bytes test/api/fonts/MathTestFontNone.otf | Bin 0 -> 14284 bytes test/api/test-ot-layout-math.c | 98 +++++++++++++++++++++++++++ 9 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 src/hb-ot-layout-math-table.hh create mode 100644 test/api/fonts/MathTestFontEmpty.otf create mode 100644 test/api/fonts/MathTestFontNone.otf create mode 100644 test/api/test-ot-layout-math.c diff --git a/src/Makefile.sources b/src/Makefile.sources index ac806838c..cd30b12f0 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -75,6 +75,7 @@ HB_OT_sources = \ hb-ot-layout-gsubgpos-private.hh \ hb-ot-layout-gsub-table.hh \ hb-ot-layout-jstf-table.hh \ + hb-ot-layout-math-table.hh \ hb-ot-layout-private.hh \ hb-ot-map.cc \ hb-ot-map-private.hh \ diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh new file mode 100644 index 000000000..f4ecf3f0e --- /dev/null +++ b/src/hb-ot-layout-math-table.hh @@ -0,0 +1,60 @@ +/* + * 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 + */ + +#ifndef HB_OT_LAYOUT_MATH_TABLE_HH +#define HB_OT_LAYOUT_MATH_TABLE_HH + +#include "hb-open-type-private.hh" +#include "hb-ot-layout-common-private.hh" + +namespace OT { + +/* + * MATH -- The MATH Table + */ + +struct MATH +{ + static const hb_tag_t tableTag = HB_OT_TAG_MATH; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1)); + } + +protected: + FixedVersion<>version; /* Version of the MATH table + initially set to 0x00010000u */ +public: + DEFINE_SIZE_STATIC (4); +}; + +} /* mathspace OT */ + + +#endif /* HB_OT_LAYOUT_MATH_TABLE_HH */ diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 778b2c442..a4272de63 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -124,6 +124,7 @@ namespace OT { struct GDEF; struct GSUB; struct GPOS; + struct MATH; } struct hb_ot_layout_lookup_accelerator_t @@ -152,10 +153,12 @@ struct hb_ot_layout_t hb_blob_t *gdef_blob; hb_blob_t *gsub_blob; hb_blob_t *gpos_blob; + hb_blob_t *math_blob; const struct OT::GDEF *gdef; const struct OT::GSUB *gsub; const struct OT::GPOS *gpos; + const struct OT::MATH *math; unsigned int gsub_lookup_count; unsigned int gpos_lookup_count; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 5cb1491c3..24d290c5c 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -35,6 +35,7 @@ #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" @@ -60,6 +61,10 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GPOS)); layout->gpos = OT::Sanitizer::lock_instance (layout->gpos_blob); + // The MATH table is rarer so we only try and load it in _get_math + layout->math_blob = NULL; + layout->math = NULL; + { /* * The ugly business of blacklisting individual fonts' tables happen here! @@ -178,6 +183,8 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gsub_blob); hb_blob_destroy (layout->gpos_blob); + if (layout->math_blob) hb_blob_destroy (layout->math_blob); + free (layout); } @@ -199,6 +206,21 @@ _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); + + // If the MATH table is not loaded yet, do it now. + if (!layout->math_blob) { + layout->math_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_MATH)); + layout->math = OT::Sanitizer::lock_instance (layout->math_blob); + } + + return *layout->math; +} /* @@ -1190,3 +1212,26 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, { apply_string (c, lookup, accel); } + +/* + * OT::MATH + */ + +/** + * hb_ot_layout_has_math_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: ???? + **/ +hb_bool_t +hb_ot_layout_has_math_data (hb_face_t *face) +{ + return &_get_math (face) != &OT::Null(OT::MATH); +} diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index eb23d45b6..7cbd794ce 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -42,6 +42,7 @@ HB_BEGIN_DECLS #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B') #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S') #define HB_OT_TAG_JSTF HB_TAG('J','S','T','F') +#define HB_OT_TAG_MATH HB_TAG('M','A','T','H') /* @@ -297,6 +298,12 @@ hb_ot_layout_get_size_params (hb_face_t *face, unsigned int *range_end /* OUT. May be NULL */); +/* + * MATH + */ + +HB_EXTERN hb_bool_t +hb_ot_layout_has_math_data (hb_face_t *face); HB_END_DECLS #endif /* HB_OT_LAYOUT_H */ diff --git a/test/api/Makefile.am b/test/api/Makefile.am index d7d40af39..dae8700c3 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -43,10 +43,22 @@ endif if HAVE_OT + TEST_PROGS += \ test-ot-tag \ $(NULL) -endif + +if HAVE_FREETYPE +TEST_PROGS += \ + test-ot-layout-math \ + $(NULL) +test_ot_layout_math_LDADD = $(LDADD) +test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) +test_ot_layout_math_CPPFLAGS += $(FREETYPE_CFLAGS) +test_ot_layout_math_LDADD += $(FREETYPE_LIBS) +endif # HAVE_FREETYPE + +endif # HAVE_OT # Tests for header compilation TEST_PROGS += \ diff --git a/test/api/fonts/MathTestFontEmpty.otf b/test/api/fonts/MathTestFontEmpty.otf new file mode 100644 index 0000000000000000000000000000000000000000..6b50d66fc3d653da18010d8c116e3a7778dda109 GIT binary patch literal 14320 zcmds8&5tALS$}(acCu79vzb*uE3&|=21V0~+w-|I(j*5w{+PDbZF_C^Oy+<>wOwvk z#;$Uz%H7iv2P6a%3I{mw4UCAQ?e1kc zL}GeuSG^z4_w#$6x7^(s3_8kDf2_8Zt~MI_AJl*Tmr@V!E2aMSpfcE3TewmW{}pde zr+@42d;juvN2#r^@9z}3U;f5-LD z@cO;UEP1*83tXv(e7`nxU(VH)E-ts;=6&GKyuYs9+{67`sr%obhjH@e&(uAv{|4r@ zkp=R6@=xtQ{r<2^F`rm) zV;gTmWlP<_om^j0U%By(^!jRU{95k%y86u<--Oq;u0o!jYd1bjuea3Bz3-&gSJd@; ze~?~Z&5ggMe*4~wbo^Rw{JOe-@6W5@{4Da1CyBl}+|_q)-+55d&0}}!ySiU)mG#X@ zlFT37y5*a(@-Up;+I5`4#E*3&3=-WB$H}Q1c^U&#f9M6VH`0q>CW5> zWN}Ltl=M?Civ2LqcglClLM+`&GQ)80gUFFL4Nptj4MrSvr*Wv=6W5=*M^jIq`pHDQ zx>5O9yU8Ob6*3-1{yd4xu|F+`(ebTLqvbfx-k1O982P*Pwr+IV1Kny?>+OC$FTUQ> zcOU46cN8t$=nMwD{qX<9(CPN-m4nBvI?Uqf;}Cl5aBOUO&W`#f6x`LceiG_9@n?&v zo4`0>G##D#BhMLmC$Qpt=D|~-G7P6MUl_TGf8yye{Wp)oA9%wgE*TPw`8IcUQAFPKUKASB9Kk+>fqt_r4sGmR%cxoJZ_y|T$ z$Y>ZxNPdX
  • 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 literal 0 HcmV?d00001 diff --git a/test/api/fonts/MathTestFontNone.otf b/test/api/fonts/MathTestFontNone.otf new file mode 100644 index 0000000000000000000000000000000000000000..52984eecc86b079a036841bfdce1b038eaf3ce0e GIT binary patch literal 14284 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 Date: Mon, 26 Sep 2016 10:45:58 +0100 Subject: [PATCH 02/32] [MATH] Fixups for previous commit --- src/hb-ot-layout-math-table.hh | 8 ++++---- src/hb-ot-layout.cc | 29 +++++++++++++++++++---------- src/hb-ot-layout.h | 2 ++ test/api/Makefile.am | 6 ++---- test/api/test-ot-layout-math.c | 16 +++++++++------- 5 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index f4ecf3f0e..7b3c0c7d2 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -38,18 +38,18 @@ namespace OT { struct MATH { - static const hb_tag_t tableTag = HB_OT_TAG_MATH; + static const hb_tag_t tableTag = HB_OT_TAG_MATH; inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && - likely (version.major == 1)); + likely (version.major == 1)); } protected: - FixedVersion<>version; /* Version of the MATH table - initially set to 0x00010000u */ + FixedVersion<>version; /* Version of the MATH table + * initially set to 0x00010000u */ public: DEFINE_SIZE_STATIC (4); }; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 24d290c5c..e6316e192 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -61,7 +61,7 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GPOS)); layout->gpos = OT::Sanitizer::lock_instance (layout->gpos_blob); - // The MATH table is rarer so we only try and load it in _get_math + /* The MATH table is rarely used, so only try and load it in _get_math. */ layout->math_blob = NULL; layout->math = NULL; @@ -182,8 +182,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gdef_blob); hb_blob_destroy (layout->gsub_blob); hb_blob_destroy (layout->gpos_blob); - - if (layout->math_blob) hb_blob_destroy (layout->math_blob); + hb_blob_destroy (layout->math_blob); free (layout); } @@ -213,13 +212,22 @@ _get_math (hb_face_t *face) hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - // If the MATH table is not loaded yet, do it now. - if (!layout->math_blob) { - layout->math_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_MATH)); - layout->math = OT::Sanitizer::lock_instance (layout->math_blob); +retry: + const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math); + + if (unlikely (!math)) + { + hb_blob_t *blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_MATH)); + math = OT::Sanitizer::lock_instance (blob); + if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math)) + { + hb_blob_destroy (blob); + goto retry; + } + layout->math_blob = blob; } - return *layout->math; + return *math; } @@ -1213,8 +1221,9 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, apply_string (c, lookup, accel); } + /* - * OT::MATH + * MATH */ /** @@ -1228,7 +1237,7 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, * * Return value: #TRUE if face has a MATH table and #FALSE otherwise * - * Since: ???? + * Since: 1.4 **/ hb_bool_t hb_ot_layout_has_math_data (hb_face_t *face) diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 7cbd794ce..e78679051 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -304,6 +304,8 @@ hb_ot_layout_get_size_params (hb_face_t *face, HB_EXTERN hb_bool_t hb_ot_layout_has_math_data (hb_face_t *face); + + HB_END_DECLS #endif /* HB_OT_LAYOUT_H */ diff --git a/test/api/Makefile.am b/test/api/Makefile.am index dae8700c3..322cd7d2a 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -52,10 +52,8 @@ if HAVE_FREETYPE TEST_PROGS += \ test-ot-layout-math \ $(NULL) -test_ot_layout_math_LDADD = $(LDADD) -test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) -test_ot_layout_math_CPPFLAGS += $(FREETYPE_CFLAGS) -test_ot_layout_math_LDADD += $(FREETYPE_LIBS) +test_ot_layout_math_LDADD = $(LDADD) $(FREETYPE_LIBS) +test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS) endif # HAVE_FREETYPE endif # HAVE_OT diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index cf7d76c16..3e8fec6e0 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -37,16 +37,16 @@ static FT_Face ft_face; static hb_font_t *hb_font; static hb_face_t *hb_face; -static void -initFreeType() +static inline void +initFreeType (void) { FT_Error ft_error; if ((ft_error = FT_Init_FreeType (&ft_library))) abort(); } -static void -cleanupFreeType() +static inline void +cleanupFreeType (void) { FT_Done_FreeType (ft_library); } @@ -57,15 +57,17 @@ openFont(const char* fontFile) FT_Error ft_error; if ((ft_error = FT_New_Face (ft_library, fontFile, 0, &ft_face))) abort(); - unsigned int fontSize = 1000; + +#define fontSize 1000 + if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) abort(); hb_font = hb_ft_font_create (ft_face, NULL); hb_face = hb_ft_face_create_cached(ft_face); } -static void -closeFont() +static inline void +closeFont (void) { hb_font_destroy (hb_font); FT_Done_Face (ft_face); From 319ff59161e6b027391f8b9fdce0db6dd44cc20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Thu, 25 Aug 2016 11:06:41 +0200 Subject: [PATCH 03/32] MATH Table: Add API to access math contants. --- src/Makefile.sources | 1 + src/hb-ot-layout-math-table.hh | 146 +++++++++++++++++++++++++++- src/hb-ot-layout.cc | 25 +++++ src/hb-ot-layout.h | 5 + src/hb-ot-math.h | 100 +++++++++++++++++++ test/api/fonts/MathTestFontFull.otf | Bin 0 -> 25412 bytes test/api/test-ot-layout-math.c | 72 ++++++++++++++ 7 files changed, 345 insertions(+), 4 deletions(-) create mode 100644 src/hb-ot-math.h create mode 100644 test/api/fonts/MathTestFontFull.otf diff --git a/src/Makefile.sources b/src/Makefile.sources index cd30b12f0..5c695c5c2 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -112,6 +112,7 @@ HB_OT_headers = \ hb-ot.h \ hb-ot-font.h \ hb-ot-layout.h \ + hb-ot-math.h \ hb-ot-shape.h \ hb-ot-tag.h \ $(NULL) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 7b3c0c7d2..02a1d45d0 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -29,9 +29,139 @@ #include "hb-open-type-private.hh" #include "hb-ot-layout-common-private.hh" +#include "hb-ot-math.h" namespace OT { + +struct MathValueRecord +{ + inline hb_position_t get_value (hb_font_t *font, bool horizontal, + const void *base) const + { + return horizontal ? + font->em_scale_x (value) + (base+deviceTable).get_x_delta (font) : + font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); + } + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && deviceTable.sanitize (c, base)); + } + +protected: + SHORT value; /* The X or Y value in design units */ + OffsetTo deviceTable; /* Offset to the device table - from the + beginning of parent table. May be NULL. + Suggested format for device table is 1. */ + +public: + DEFINE_SIZE_STATIC (2 * 2); +}; + +struct MathConstants +{ + inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = + HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - + HB_OT_MATH_CONSTANT_MATH_LEADING + 1; + for (unsigned int i = 0; i < count; i++) + if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && sanitize_math_value_records(c)); + } + + inline hb_position_t get_value (hb_font_t *font, hb_ot_math_constant_t constant) const + { + switch (constant) { + case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: + case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: + return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]); + + case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: + case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: + case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: + case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, true, this); + + case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: + case HB_OT_MATH_CONSTANT_AXIS_HEIGHT: + case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: + case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: + case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: + case HB_OT_MATH_CONSTANT_MATH_LEADING: + case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: + case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: + case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_STACK_GAP_MIN: + case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: + case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: + case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: + case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: + case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: + case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, false, this); + + case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: + case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: + return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; + + case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: + return radicalDegreeBottomRaisePercent; + } + } + +protected: + SHORT percentScaleDown[HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1]; + USHORT minHeight[HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT + 1]; + MathValueRecord mathValueRecords[HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1]; + SHORT radicalDegreeBottomRaisePercent; + +public: + DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1) + + 4 * (HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1) + + 2); +}; + /* * MATH -- The MATH Table */ @@ -44,14 +174,22 @@ struct MATH { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && - likely (version.major == 1)); + likely (version.major == 1) && + mathConstants.sanitize (c, this)); + } + + inline bool has_math_constants (void) const { return mathConstants != 0; } + inline const MathConstants &get_math_constants (void) const { + return this+mathConstants; } protected: - FixedVersion<>version; /* Version of the MATH table - * initially set to 0x00010000u */ + FixedVersion<>version; /* Version of the MATH table + * initially set to 0x00010000u */ + OffsetTo mathConstants; /* MathConstants table */ + public: - DEFINE_SIZE_STATIC (4); + DEFINE_SIZE_STATIC (6); }; } /* mathspace OT */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index e6316e192..2ae138876 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1244,3 +1244,28 @@ hb_ot_layout_has_math_data (hb_face_t *face) { return &_get_math (face) != &OT::Null(OT::MATH); } + +/** + * hb_ot_layout_get_math_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: ???? + **/ +hb_position_t +hb_ot_layout_get_math_constant (hb_font_t *font, + hb_ot_math_constant_t constant) +{ + const OT::MATH &math = _get_math (font->face); + return math.has_math_constants() ? + math.get_math_constants().get_value(font, constant) : 0; +} diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index e78679051..501082e28 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -33,6 +33,7 @@ #include "hb.h" +#include "hb-ot-math.h" #include "hb-ot-tag.h" HB_BEGIN_DECLS @@ -305,6 +306,10 @@ hb_ot_layout_get_size_params (hb_face_t *face, HB_EXTERN hb_bool_t hb_ot_layout_has_math_data (hb_face_t *face); +HB_EXTERN hb_position_t +hb_ot_layout_get_math_constant (hb_font_t *font, + hb_ot_math_constant_t constant); + HB_END_DECLS diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h new file mode 100644 index 000000000..7f0ec2713 --- /dev/null +++ b/src/hb-ot-math.h @@ -0,0 +1,100 @@ +/* + * 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 + */ + +#ifndef HB_OT_H_IN +#error "Include instead." +#endif + +#ifndef HB_OT_MATH_H +#define HB_OT_MATH_H + +#include "hb.h" + +HB_BEGIN_DECLS + + +typedef enum { + HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0, + HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1, + HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT = 2, + HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT = 3, + HB_OT_MATH_CONSTANT_MATH_LEADING = 4, + HB_OT_MATH_CONSTANT_AXIS_HEIGHT = 5, + HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT = 6, + HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT = 7, + HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN = 8, + HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX = 9, + HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN = 10, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP = 11, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED = 12, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN = 13, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX = 14, + HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN = 15, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT = 16, + HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT = 17, + HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN = 18, + HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN = 19, + HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN = 20, + HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN = 21, + HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP = 22, + HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP = 23, + HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN = 24, + HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN = 25, + HB_OT_MATH_CONSTANT_STACK_GAP_MIN = 26, + HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN = 27, + HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP = 28, + HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN = 29, + HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN = 30, + HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN = 31, + HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP = 32, + HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP = 33, + HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN = 34, + HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN = 35, + HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN = 36, + HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN = 37, + HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS = 38, + HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN = 39, + HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN = 40, + HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP = 41, + HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP = 42, + HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP = 43, + HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS = 44, + HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER = 45, + HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP = 46, + HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS = 47, + HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER = 48, + HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP = 49, + HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP = 50, + HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS = 51, + HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER = 52, + HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE = 53, + HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE = 54, + HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55 +} hb_ot_math_constant_t; + +HB_END_DECLS + +#endif /* HB_OT_MATH_H */ diff --git a/test/api/fonts/MathTestFontFull.otf b/test/api/fonts/MathTestFontFull.otf new file mode 100644 index 0000000000000000000000000000000000000000..6c7c9a9511ce10cad109816e6683bcdc4d5adaa4 GIT binary patch literal 25412 zcmeHvdwf*oo%i$1Et8WFAOf{EwFjgMHiWAnQIsK>KqNPlphEF7NhZnYWG2o`2*I>v zTVJK3h*n)|TT892t*c#^($-#Zt?Q*PYrDSQdRdn(t!u4qy%!Lv?DzXT=b1S(nSizX z*}i`?@S8c$?RUSOGn2G-cD9N#u~~Sn=6w+};;9ASJH!1xW!KbEjDy0% zS^VIP+8O8TD~qP=Qke9be#K7ku?+*C_eHr~_;I4#y9(p4>37d^afVzhfYM*8kKmR3 z*x3;;HVgZtyEQFmo_p|vIUD~tnj{`o@3@@on_)TEQcPMn-?{dPl7;QgwO3RxH2nI+ zq(xq5-jD0W&UFCSG3UBMoUrIVSXcVM=Zqjpt7|Fjg%h1?kEmF-U|BM>&D!ahk-Jjr%tCaPwF;g zt5M+QET697hH?zzoaUqp?{UlwE6qd{UuGv|Ph-u7JR1Npj3c58ujF?aWAe^b@){E7 zs_P82XBB8N4f$!6L7Yf~Q}P|hdlIvK&}l2qHz~bZV$NUXpXJhjn+S^*B~vTjJ8{(n z+tjJq4!n-1eH)z9(-y0jsn-pTFAicq zBY^R%d7;n76^1Tcr9gvNx!(q_CjJJok`$L>wj1kd<68E}WzvYFg9)Gaxk+QJj%S+R=

    WsnN!JE?xZBf> zrL||%4{2|$9ZE$XVQ$tsib5w`>%l)WcXVxNFPICdSeJ6rxih`yk8Amr&UlUXU+RR~ zAoto5)DN{s8>WDy95O z>(+3hHB9cQU3!W39(NTd70Q^418QJI#jD93`M#dxS6k(BSTLq^l*@kf7}_G|ImF6} zOl}y_IzHW;Q18Y14jX=u#3}09NEQKqgOF+jTF`in9NgOtj&i)@GNh57Rb2b6_WXQ4 zHRpPTa*;l5pYPQsThyZ(HK5A206GDzydB_b#!>pK8IB%$6<(cHs2jr#?Ubt_%nY<2 z_l>osJA&;ZounmJK_iTI$}kI9SnJ-M-i-$`+UY;6ee@ODFC{L+9OFf2pEPhXcN_1} zmejf1Qu;PILuc_M_NQ=yqnw1yFU$y(n7H%%FCCGbFSN4GHq3uIhtEL2kRP+|uCxU_ z(?7+jCUw&`TDnO1I3A$g!7iD7 zGWXlCDPurKDebLi*~2i}NL}wXyyo|&#Wn5TV-G>pQmlX9p+ZI+^d`E-*OQi>cVX?gQ)xsU;Jq;`f-O!4)T!(Gf=bb*cwtwbR(jAp>HJB{Fz0K_ zY1zr4>5Fomw)P$E3A{IrDla#7(=|R{>Ljo-577^_FIX69Eihx5>VIsx>4}<>?tM5m zo$iR!m*_0W6>T}gVXoWLYbGP`-1uD|_tN8ajbJ3l6=rkVJS8xDSntMm+O)TRqQE@o zj=o&A;QcjMa!*G{n>oKLd&g#^H=1JfnR^BkW!krxhnP=j1grk_h_ zpEbC~_cq-PG56%>7-FG3q)dAH-i-J2)KRg_Lrrrx?|BMyj*gvUWoq5o>uPU0`&=Kc zy;t)^TlG3sdV!Msz0(}eW_%`z@j-QiG^@8$l2zH+oX40ctF*<94= zj)5_*Ba@aizQAW#N!9J=_G^3TXNI~vW)@`qF}}~!I-88w$FtugMxM|bD(u*(g?#@s zT_5?RcIMz+-+>YrGt@@B7WQ`ih#PuI0{fZQSetWC=9umDGYaNrS~r#T%$yF``LpWq zl}|!ROWT*4q#s9%VrSkVx1`8-%^Ur(M^Q6(i#if=5@;^E6lT_ZdQq-p)%_8lqA;fO z@4l13OWt(HXy~~0Os!Ir?01QmvC8_YJL~-3O6S&;6FUo?tiif zrqi>E+zaLRqBWr0nT-vNL)U&jh0Ar#3CA|(o>M;wE6n-Y8|mA|Lv$~}EUmSpJ;hRf ztM5%rB`?HfEN$*F7b#nlS9+7dXSAJPx9U`68t793k0sWIAwv6H*I)s`sMIdQ+vlE=CWVrRi;$m|A9?IjhCnFHKi zHa&sXW+dut_->w3kQbxl93{6Gj(_j!#;?7L{-<*bEizuc)X!o5oabJ;zhHLIdUI1I zy<+wG=+C`!Uafok!Y3lE=hURGk9=lHE08*Cl$J5q<&O0U?LnQ{dzlsy%0AyZ+Gll) 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 saECM>-&HwHt(}POYX Date: Mon, 26 Sep 2016 11:15:59 +0100 Subject: [PATCH 04/32] [MATH] Fixups for math constants commit --- src/hb-ot-layout-math-table.hh | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 02a1d45d0..c215d3221 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -36,13 +36,10 @@ namespace OT { struct MathValueRecord { - inline hb_position_t get_value (hb_font_t *font, bool horizontal, - const void *base) const - { - return horizontal ? - font->em_scale_x (value) + (base+deviceTable).get_x_delta (font) : - font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); - } + inline hb_position_t get_x_value (hb_font_t *font, const void *base) const + { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); } + inline hb_position_t get_y_value (hb_font_t *font, const void *base) const + { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { @@ -57,7 +54,7 @@ protected: Suggested format for device table is 1. */ public: - DEFINE_SIZE_STATIC (2 * 2); + DEFINE_SIZE_STATIC (4); }; struct MathConstants @@ -90,7 +87,7 @@ struct MathConstants case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: - return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, true, this); + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this); case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: case HB_OT_MATH_CONSTANT_AXIS_HEIGHT: @@ -139,7 +136,7 @@ struct MathConstants case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: - return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, false, this); + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this); case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: @@ -147,6 +144,8 @@ struct MathConstants case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: return radicalDegreeBottomRaisePercent; + default: + return 0; } } From 6fd2fe418dc838743f0d4a8a2222cdcaf587500c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 11:24:39 +0100 Subject: [PATCH 05/32] [MATH] Fixup math constants commit a bit more --- src/hb-ot-layout-math-table.hh | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index c215d3221..e65680b5a 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -62,9 +62,7 @@ struct MathConstants inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - unsigned int count = - HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - - HB_OT_MATH_CONSTANT_MATH_LEADING + 1; + unsigned int count = ARRAY_LENGTH (mathValueRecords); for (unsigned int i = 0; i < count; i++) if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); return_trace (true); @@ -79,6 +77,11 @@ struct MathConstants inline hb_position_t get_value (hb_font_t *font, hb_ot_math_constant_t constant) const { switch (constant) { + + case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: + case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: + return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; + case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]); @@ -138,27 +141,22 @@ struct MathConstants case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this); - case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: - case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: - return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; - case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: return radicalDegreeBottomRaisePercent; + default: return 0; } } protected: - SHORT percentScaleDown[HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1]; - USHORT minHeight[HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT + 1]; - MathValueRecord mathValueRecords[HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1]; + SHORT percentScaleDown[2]; + USHORT minHeight[2]; + MathValueRecord mathValueRecords[51]; SHORT radicalDegreeBottomRaisePercent; public: - DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1) + - 4 * (HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1) + - 2); + DEFINE_SIZE_STATIC (214); }; /* From d7182d129612c619b9026ee9b15f2dcfada132db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Thu, 25 Aug 2016 11:15:31 +0200 Subject: [PATCH 06/32] MATH Table: Add API to access glyph info. --- src/hb-ot-layout-math-table.hh | 271 +++++++++++++++++++++++- src/hb-ot-layout.cc | 114 ++++++++++ src/hb-ot-layout.h | 18 ++ src/hb-ot-math.h | 7 + test/api/fonts/MathTestFontPartial1.otf | Bin 0 -> 14348 bytes test/api/fonts/MathTestFontPartial2.otf | Bin 0 -> 14356 bytes test/api/fonts/MathTestFontPartial3.otf | Bin 0 -> 14380 bytes test/api/test-ot-layout-math.c | 155 ++++++++++++++ 8 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 test/api/fonts/MathTestFontPartial1.otf create mode 100644 test/api/fonts/MathTestFontPartial2.otf create mode 100644 test/api/fonts/MathTestFontPartial3.otf diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index e65680b5a..2eb0d9228 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -159,6 +159,267 @@ public: DEFINE_SIZE_STATIC (214); }; +struct MathItalicsCorrectionInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + coverage.sanitize (c, this) && + italicsCorrection.sanitize (c, this)); + } + + inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, + hb_position_t &value) const + { + unsigned int index = (this+coverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= italicsCorrection.len)) return false; + value = italicsCorrection[index].get_x_value(font, this); + return true; + } + +protected: + OffsetTo coverage; /* Offset to Coverage table - + from the beginning of + MathItalicsCorrectionInfo + table. */ + ArrayOf italicsCorrection; /* Array of MathValueRecords + defining italics correction + values for each + covered glyph. */ + +public: + DEFINE_SIZE_ARRAY (2 + 2, italicsCorrection); +}; + +struct MathTopAccentAttachment +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + topAccentCoverage.sanitize (c, this) && + topAccentAttachment.sanitize (c, this)); + } + + inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, + hb_position_t &value) const + { + unsigned int index = (this+topAccentCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= topAccentAttachment.len)) return false; + value = topAccentAttachment[index].get_x_value(font, this); + return true; + } + +protected: + OffsetTo topAccentCoverage; /* Offset to Coverage table - + from the beginning of + MathTopAccentAttachment + table. */ + ArrayOf topAccentAttachment; /* Array of MathValueRecords + defining top accent + attachment points for each + covered glyph. */ + +public: + DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); +}; + +struct MathKern +{ + inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = 2 * heightCount + 1; + for (unsigned int i = 0; i < count; i++) + if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (mathValueRecords, + mathValueRecords[0].static_size, + 2 * heightCount + 1) && + sanitize_math_value_records (c)); + } + + inline hb_position_t get_value (hb_font_t *font, + hb_position_t &correction_height) const + { + const MathValueRecord* correctionHeight = mathValueRecords; + const MathValueRecord* kernValue = mathValueRecords + heightCount; + // The description of the MathKern table is a ambiguous, but interpreting + // "between the two heights found at those indexes" for 0 < i < len as + // + // correctionHeight[i-1] < correction_height <= correctionHeight[i] + // + // makes the result consistent with the limit cases and we can just use the + // binary search algorithm of std::upper_bound: + unsigned int count = heightCount; + unsigned int i = 0; + while (count > 0) { + unsigned int half = count / 2; + hb_position_t height = + correctionHeight[i + half].get_y_value(font, this); + if (height < correction_height) { + i += half + 1; + count -= half + 1; + } else + count = half; + } + return kernValue[i].get_x_value(font, this); + } + +protected: + USHORT heightCount; + MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at + which the kern value changes. + Sorted by the height value in + design units. */ + /* Array of kern values corresponding + to heights. */ + +public: + DEFINE_SIZE_ARRAY (2, mathValueRecords); +}; + +struct MathKernInfoRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathKern[HB_OT_MATH_KERN_TOP_RIGHT].sanitize (c, base) && + mathKern[HB_OT_MATH_KERN_TOP_LEFT].sanitize (c, base) && + mathKern[HB_OT_MATH_KERN_BOTTOM_RIGHT].sanitize (c, base) && + mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT].sanitize (c, base)); + } + + inline bool has_math_kern (hb_ot_math_kern_t kern) const { + return mathKern[kern] != 0; + } + inline const MathKern &get_math_kern (hb_ot_math_kern_t kern, + const void *base) const { + return base+mathKern[kern]; + } + +protected: + /* Offset to MathKern table for each corner - + from the beginning of MathKernInfo table. May be NULL. */ + OffsetTo mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT - + HB_OT_MATH_KERN_TOP_RIGHT + 1]; + +public: + DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_KERN_BOTTOM_LEFT - + HB_OT_MATH_KERN_TOP_RIGHT + 1)); +}; + +struct MathKernInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathKernCoverage.sanitize (c, this) && + mathKernInfoRecords.sanitize (c, this)); + } + + inline bool + get_math_kern_info_record (hb_codepoint_t glyph, + const MathKernInfoRecord *&record) const + { + unsigned int index = (this+mathKernCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= mathKernInfoRecords.len)) return false; + record = &mathKernInfoRecords[index]; + return true; + } + +protected: + OffsetTo mathKernCoverage; /* Offset to Coverage table - + from the beginning of the + MathKernInfo table. */ + ArrayOf mathKernInfoRecords; /* Array of + MathKernInfoRecords, + per-glyph information for + mathematical positioning + of subscripts and + superscripts. */ + +public: + DEFINE_SIZE_ARRAY (2 + 2, mathKernInfoRecords); +}; + +struct MathGlyphInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathItalicsCorrectionInfo.sanitize (c, this) && + mathTopAccentAttachment.sanitize (c, this) && + extendedShapeCoverage.sanitize (c, this) && + mathKernInfo.sanitize(c, this)); + } + + inline bool has_math_italics_correction_info (void) const { + return mathItalicsCorrectionInfo != 0; + } + inline const MathItalicsCorrectionInfo& + get_math_italics_correction_info (void) const { + return this+mathItalicsCorrectionInfo; + } + + inline bool has_math_top_accent_attachment (void) const { + return mathTopAccentAttachment != 0; + } + inline const MathTopAccentAttachment& + get_math_top_accent_attachment (void) const { + return this+mathTopAccentAttachment; + } + + inline bool is_extended_shape (hb_codepoint_t glyph) const + { + if (likely (extendedShapeCoverage == 0)) return false; + unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + return true; + } + + inline bool has_math_kern_info (void) const { return mathKernInfo != 0; } + inline const MathKernInfo &get_math_kern_info (void) const { + return this+mathKernInfo; + } + +protected: + /* Offset to MathItalicsCorrectionInfo table - + from the beginning of MathGlyphInfo table. */ + OffsetTo mathItalicsCorrectionInfo; + + /* Offset to MathTopAccentAttachment table - + from the beginning of MathGlyphInfo table. */ + OffsetTo mathTopAccentAttachment; + + /* Offset to coverage table for Extended Shape glyphs - + from the beginning of MathGlyphInfo table. When the left or right glyph of + a box is an extended shape variant, the (ink) box (and not the default + position defined by values in MathConstants table) should be used for + vertical positioning purposes. May be NULL.. */ + OffsetTo extendedShapeCoverage; + + /* Offset to MathKernInfo table - + from the beginning of MathGlyphInfo table. */ + OffsetTo mathKernInfo; + +public: + DEFINE_SIZE_STATIC (4 * 2); +}; + /* * MATH -- The MATH Table */ @@ -172,7 +433,8 @@ struct MATH TRACE_SANITIZE (this); return_trace (version.sanitize (c) && likely (version.major == 1) && - mathConstants.sanitize (c, this)); + mathConstants.sanitize (c, this) && + mathGlyphInfo.sanitize (c, this)); } inline bool has_math_constants (void) const { return mathConstants != 0; } @@ -180,13 +442,18 @@ struct MATH return this+mathConstants; } + inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; } + inline const MathGlyphInfo &get_math_glyph_info (void) const { + return this+mathGlyphInfo; + } protected: FixedVersion<>version; /* Version of the MATH table * initially set to 0x00010000u */ OffsetTo mathConstants; /* MathConstants table */ + OffsetTo mathGlyphInfo; /* MathGlyphInfo table */ public: - DEFINE_SIZE_STATIC (6); + DEFINE_SIZE_STATIC (8); }; } /* mathspace OT */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 2ae138876..f14611b47 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1269,3 +1269,117 @@ hb_ot_layout_get_math_constant (hb_font_t *font, return math.has_math_constants() ? math.get_math_constants().get_value(font, constant) : 0; } + +/** + * hb_ot_layout_get_math_italic_correction: + * + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * + * Return value: the italic correction of the glyph or 0 + * + * Since: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italic_correction (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + if (math.has_math_glyph_info()) { + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + if (glyphInfo.has_math_italics_correction_info()) { + hb_position_t value; + if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, + value)) + return value; + } + } + return 0; +} + +/** + * hb_ot_layout_get_math_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: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + if (math.has_math_glyph_info()) { + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + if (glyphInfo.has_math_top_accent_attachment()) { + hb_position_t value; + if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, + value)) + return value; + } + } + return 0; +} + +/** + * hb_ot_layout_is_math_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: ???? + **/ +HB_EXTERN hb_bool_t +hb_ot_layout_is_math_extended_shape (hb_face_t *face, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (face); + return math.has_math_glyph_info() && + math.get_math_glyph_info().is_extended_shape(glyph); +} + +/** + * hb_ot_layout_get_math_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: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_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); + if (math.has_math_glyph_info()) { + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + if (glyphInfo.has_math_kern_info()) { + const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); + const OT::MathKernInfoRecord *kernInfoRecord; + if (kernInfo.get_math_kern_info_record(glyph, kernInfoRecord) && + kernInfoRecord->has_math_kern(kern)) { + return kernInfoRecord-> + get_math_kern(kern, &kernInfo).get_value(font, correction_height); + } + } + } + + return 0; +} diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 501082e28..ffb6321c7 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -310,6 +310,24 @@ HB_EXTERN hb_position_t hb_ot_layout_get_math_constant (hb_font_t *font, hb_ot_math_constant_t constant); +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italic_correction (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_bool_t +hb_ot_layout_is_math_extended_shape (hb_face_t *face, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height); + HB_END_DECLS diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 7f0ec2713..a62b4b612 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -95,6 +95,13 @@ typedef enum { HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55 } hb_ot_math_constant_t; +typedef enum { + HB_OT_MATH_KERN_TOP_RIGHT = 0, + HB_OT_MATH_KERN_TOP_LEFT = 1, + HB_OT_MATH_KERN_BOTTOM_RIGHT = 2, + HB_OT_MATH_KERN_BOTTOM_LEFT = 3 +} hb_ot_math_kern_t; + HB_END_DECLS #endif /* HB_OT_MATH_H */ diff --git a/test/api/fonts/MathTestFontPartial1.otf b/test/api/fonts/MathTestFontPartial1.otf new file mode 100644 index 0000000000000000000000000000000000000000..b3bf36e33efb8a5b0f4f33f74f952fb26f34c42c GIT binary patch literal 14348 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 P{^9TW@B^CmujBp)n>Hxn literal 0 HcmV?d00001 diff --git a/test/api/fonts/MathTestFontPartial3.otf b/test/api/fonts/MathTestFontPartial3.otf new file mode 100644 index 0000000000000000000000000000000000000000..ca18a9a228facf9472f09122d6646eeeb3a0ff86 GIT binary patch literal 14380 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 a{<`%z^t-37;b#LsZ{UZYnTzdT&HWOy+$iAy literal 0 HcmV?d00001 diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index 219959b65..5ba583f1b 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -160,6 +160,157 @@ test_get_math_constant (void) cleanupFreeType(); } +static void +test_get_math_italic_correction (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. + g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 197); + g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 150); + g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 452); + closeFont(); + + cleanupFreeType(); + +} + +static void +test_get_math_top_accent_attachment (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathTopAccentAttachment empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // Glyph without top accent attachment. + g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374); + g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 346); + g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 318); + closeFont(); + + cleanupFreeType(); +} + +static void +test_is_math_extended_shape (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph)); + g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); + g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph)); + g_assert(hb_ot_layout_is_math_extended_shape (hb_face, glyph)); + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_math_kerning (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); + + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height + + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left + + closeFont(); + + cleanupFreeType(); +} + + int main (int argc, char **argv) { @@ -167,6 +318,10 @@ main (int argc, char **argv) hb_test_add (test_has_math_data); hb_test_add (test_get_math_constant); + hb_test_add (test_get_math_italic_correction); + hb_test_add (test_get_math_top_accent_attachment); + hb_test_add (test_is_math_extended_shape); + hb_test_add (test_get_math_kerning); return hb_test_run(); } From 8a8cfad9a0834fe278a747c1d755144bd78f564b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 11:47:05 +0100 Subject: [PATCH 07/32] [MATH] Cleanup previous commit a bit --- src/hb-ot-layout-math-table.hh | 186 ++++++++++++++++----------------- src/hb-ot-layout.cc | 30 +++--- src/hb-ot-layout.h | 14 +-- 3 files changed, 113 insertions(+), 117 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 2eb0d9228..7f6c6b09c 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -48,10 +48,10 @@ struct MathValueRecord } protected: - SHORT value; /* The X or Y value in design units */ - OffsetTo deviceTable; /* Offset to the device table - from the - beginning of parent table. May be NULL. - Suggested format for device table is 1. */ + SHORT value; /* The X or Y value in design units */ + OffsetTo deviceTable; /* Offset to the device table - from the + * beginning of parent table. May be NULL. + * Suggested format for device table is 1. */ public: DEFINE_SIZE_STATIC (4); @@ -62,9 +62,12 @@ struct MathConstants inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); + unsigned int count = ARRAY_LENGTH (mathValueRecords); for (unsigned int i = 0; i < count; i++) - if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); + if (!mathValueRecords[i].sanitize (c, this)) + return_trace (false); + return_trace (true); } @@ -165,12 +168,12 @@ struct MathItalicsCorrectionInfo { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - coverage.sanitize (c, this) && - italicsCorrection.sanitize (c, this)); + coverage.sanitize (c, this) && + italicsCorrection.sanitize (c, this)); } inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, - hb_position_t &value) const + hb_position_t &value) const { unsigned int index = (this+coverage).get_coverage (glyph); if (likely (index == NOT_COVERED)) return false; @@ -180,17 +183,17 @@ struct MathItalicsCorrectionInfo } protected: - OffsetTo coverage; /* Offset to Coverage table - - from the beginning of - MathItalicsCorrectionInfo - table. */ - ArrayOf italicsCorrection; /* Array of MathValueRecords - defining italics correction - values for each - covered glyph. */ + OffsetTo coverage; /* Offset to Coverage table - + * from the beginning of + * MathItalicsCorrectionInfo + * table. */ + ArrayOf italicsCorrection; /* Array of MathValueRecords + * defining italics correction + * values for each + * covered glyph. */ public: - DEFINE_SIZE_ARRAY (2 + 2, italicsCorrection); + DEFINE_SIZE_ARRAY (4, italicsCorrection); }; struct MathTopAccentAttachment @@ -199,12 +202,12 @@ struct MathTopAccentAttachment { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - topAccentCoverage.sanitize (c, this) && - topAccentAttachment.sanitize (c, this)); + topAccentCoverage.sanitize (c, this) && + topAccentAttachment.sanitize (c, this)); } inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, - hb_position_t &value) const + hb_position_t &value) const { unsigned int index = (this+topAccentCoverage).get_coverage (glyph); if (likely (index == NOT_COVERED)) return false; @@ -215,13 +218,13 @@ struct MathTopAccentAttachment protected: OffsetTo topAccentCoverage; /* Offset to Coverage table - - from the beginning of - MathTopAccentAttachment - table. */ + * from the beginning of + * MathTopAccentAttachment + * table. */ ArrayOf topAccentAttachment; /* Array of MathValueRecords - defining top accent - attachment points for each - covered glyph. */ + * defining top accent + * attachment points for each + * covered glyph. */ public: DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); @@ -242,14 +245,14 @@ struct MathKern { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - c->check_array (mathValueRecords, - mathValueRecords[0].static_size, - 2 * heightCount + 1) && - sanitize_math_value_records (c)); + c->check_array (mathValueRecords, + mathValueRecords[0].static_size, + 2 * heightCount + 1) && + sanitize_math_value_records (c)); } inline hb_position_t get_value (hb_font_t *font, - hb_position_t &correction_height) const + hb_position_t &correction_height) const { const MathValueRecord* correctionHeight = mathValueRecords; const MathValueRecord* kernValue = mathValueRecords + heightCount; @@ -265,12 +268,12 @@ struct MathKern while (count > 0) { unsigned int half = count / 2; hb_position_t height = - correctionHeight[i + half].get_y_value(font, this); + correctionHeight[i + half].get_y_value(font, this); if (height < correction_height) { - i += half + 1; - count -= half + 1; + i += half + 1; + count -= half + 1; } else - count = half; + count = half; } return kernValue[i].get_x_value(font, this); } @@ -278,11 +281,11 @@ struct MathKern protected: USHORT heightCount; MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at - which the kern value changes. - Sorted by the height value in - design units. */ - /* Array of kern values corresponding - to heights. */ + * which the kern value changes. + * Sorted by the height value in + * design units. */ + /* Array of kern values corresponding + * to heights. */ public: DEFINE_SIZE_ARRAY (2, mathValueRecords); @@ -293,30 +296,30 @@ struct MathKernInfoRecord inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - mathKern[HB_OT_MATH_KERN_TOP_RIGHT].sanitize (c, base) && - mathKern[HB_OT_MATH_KERN_TOP_LEFT].sanitize (c, base) && - mathKern[HB_OT_MATH_KERN_BOTTOM_RIGHT].sanitize (c, base) && - mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT].sanitize (c, base)); + + unsigned int count = ARRAY_LENGTH (mathKern); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!mathKern[i].sanitize (c, base))) + return_trace (false); + + return_trace (true); } - inline bool has_math_kern (hb_ot_math_kern_t kern) const { - return mathKern[kern] != 0; - } inline const MathKern &get_math_kern (hb_ot_math_kern_t kern, - const void *base) const { - return base+mathKern[kern]; + const void *base) const + { + unsigned int idx = kern; + if (unlikely (idx > ARRAY_LENGTH (mathKern))) return Null(MathKern); + return base+mathKern[idx]; } protected: /* Offset to MathKern table for each corner - - from the beginning of MathKernInfo table. May be NULL. */ - OffsetTo mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT - - HB_OT_MATH_KERN_TOP_RIGHT + 1]; + * from the beginning of MathKernInfo table. May be NULL. */ + OffsetTo mathKern[4]; public: - DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_KERN_BOTTOM_LEFT - - HB_OT_MATH_KERN_TOP_RIGHT + 1)); + DEFINE_SIZE_STATIC (8); }; struct MathKernInfo @@ -325,34 +328,30 @@ struct MathKernInfo { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - mathKernCoverage.sanitize (c, this) && - mathKernInfoRecords.sanitize (c, this)); + mathKernCoverage.sanitize (c, this) && + mathKernInfoRecords.sanitize (c, this)); } - inline bool - get_math_kern_info_record (hb_codepoint_t glyph, - const MathKernInfoRecord *&record) const + inline const MathKernInfoRecord& + get_math_kern_info_record (hb_codepoint_t glyph) const { unsigned int index = (this+mathKernCoverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; - if (unlikely (index >= mathKernInfoRecords.len)) return false; - record = &mathKernInfoRecords[index]; - return true; + return mathKernInfoRecords[index]; } protected: - OffsetTo mathKernCoverage; /* Offset to Coverage table - - from the beginning of the - MathKernInfo table. */ - ArrayOf mathKernInfoRecords; /* Array of - MathKernInfoRecords, - per-glyph information for - mathematical positioning - of subscripts and - superscripts. */ + OffsetTo mathKernCoverage; /* Offset to Coverage table - + * from the beginning of the + * MathKernInfo table. */ + ArrayOf mathKernInfoRecords; /* Array of + * MathKernInfoRecords, + * per-glyph information for + * mathematical positioning + * of subscripts and + * superscripts. */ public: - DEFINE_SIZE_ARRAY (2 + 2, mathKernInfoRecords); + DEFINE_SIZE_ARRAY (4, mathKernInfoRecords); }; struct MathGlyphInfo @@ -361,10 +360,10 @@ struct MathGlyphInfo { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - mathItalicsCorrectionInfo.sanitize (c, this) && - mathTopAccentAttachment.sanitize (c, this) && - extendedShapeCoverage.sanitize (c, this) && - mathKernInfo.sanitize(c, this)); + mathItalicsCorrectionInfo.sanitize (c, this) && + mathTopAccentAttachment.sanitize (c, this) && + extendedShapeCoverage.sanitize (c, this) && + mathKernInfo.sanitize(c, this)); } inline bool has_math_italics_correction_info (void) const { @@ -398,28 +397,29 @@ struct MathGlyphInfo protected: /* Offset to MathItalicsCorrectionInfo table - - from the beginning of MathGlyphInfo table. */ + * from the beginning of MathGlyphInfo table. */ OffsetTo mathItalicsCorrectionInfo; /* Offset to MathTopAccentAttachment table - - from the beginning of MathGlyphInfo table. */ + * from the beginning of MathGlyphInfo table. */ OffsetTo mathTopAccentAttachment; /* Offset to coverage table for Extended Shape glyphs - - from the beginning of MathGlyphInfo table. When the left or right glyph of - a box is an extended shape variant, the (ink) box (and not the default - position defined by values in MathConstants table) should be used for - vertical positioning purposes. May be NULL.. */ + * from the beginning of MathGlyphInfo table. When the left or right glyph of + * a box is an extended shape variant, the (ink) box (and not the default + * position defined by values in MathConstants table) should be used for + * vertical positioning purposes. May be NULL.. */ OffsetTo extendedShapeCoverage; /* Offset to MathKernInfo table - - from the beginning of MathGlyphInfo table. */ + * from the beginning of MathGlyphInfo table. */ OffsetTo mathKernInfo; public: - DEFINE_SIZE_STATIC (4 * 2); + DEFINE_SIZE_STATIC (8); }; + /* * MATH -- The MATH Table */ @@ -432,9 +432,9 @@ struct MATH { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && - likely (version.major == 1) && - mathConstants.sanitize (c, this) && - mathGlyphInfo.sanitize (c, this)); + likely (version.major == 1) && + mathConstants.sanitize (c, this) && + mathGlyphInfo.sanitize (c, this)); } inline bool has_math_constants (void) const { return mathConstants != 0; } @@ -447,10 +447,10 @@ struct MATH return this+mathGlyphInfo; } protected: - FixedVersion<>version; /* Version of the MATH table - * initially set to 0x00010000u */ - OffsetTo mathConstants; /* MathConstants table */ - OffsetTo mathGlyphInfo; /* MathGlyphInfo table */ + FixedVersion<>version; /* Version of the MATH table + * initially set to 0x00010000u */ + OffsetTo mathConstants;/* MathConstants table */ + OffsetTo mathGlyphInfo;/* MathGlyphInfo table */ public: DEFINE_SIZE_STATIC (8); diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index f14611b47..3dcdfb697 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1263,7 +1263,7 @@ hb_ot_layout_has_math_data (hb_face_t *face) **/ hb_position_t hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant) + hb_ot_math_constant_t constant) { const OT::MATH &math = _get_math (font->face); return math.has_math_constants() ? @@ -1282,7 +1282,7 @@ hb_ot_layout_get_math_constant (hb_font_t *font, **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_italic_correction (hb_font_t *font, - hb_codepoint_t glyph) + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); if (math.has_math_glyph_info()) { @@ -1290,8 +1290,8 @@ hb_ot_layout_get_math_italic_correction (hb_font_t *font, if (glyphInfo.has_math_italics_correction_info()) { hb_position_t value; if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, - value)) - return value; + value)) + return value; } } return 0; @@ -1309,7 +1309,7 @@ hb_ot_layout_get_math_italic_correction (hb_font_t *font, **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph) + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); if (math.has_math_glyph_info()) { @@ -1317,8 +1317,8 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, if (glyphInfo.has_math_top_accent_attachment()) { hb_position_t value; if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, - value)) - return value; + value)) + return value; } } return 0; @@ -1336,7 +1336,7 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, **/ HB_EXTERN hb_bool_t hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph) + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (face); return math.has_math_glyph_info() && @@ -1363,21 +1363,17 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face, **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_kerning (hb_font_t *font, - hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height) + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height) { const OT::MATH &math = _get_math (font->face); if (math.has_math_glyph_info()) { const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); if (glyphInfo.has_math_kern_info()) { const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); - const OT::MathKernInfoRecord *kernInfoRecord; - if (kernInfo.get_math_kern_info_record(glyph, kernInfoRecord) && - kernInfoRecord->has_math_kern(kern)) { - return kernInfoRecord-> - get_math_kern(kern, &kernInfo).get_value(font, correction_height); - } + const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph); + return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height); } } diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index ffb6321c7..f9ed2d82d 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -308,25 +308,25 @@ hb_ot_layout_has_math_data (hb_face_t *face); HB_EXTERN hb_position_t hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant); + hb_ot_math_constant_t constant); HB_EXTERN hb_position_t hb_ot_layout_get_math_italic_correction (hb_font_t *font, - hb_codepoint_t glyph); + hb_codepoint_t glyph); HB_EXTERN hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph); + hb_codepoint_t glyph); HB_EXTERN hb_bool_t hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph); + hb_codepoint_t glyph); HB_EXTERN hb_position_t hb_ot_layout_get_math_kerning (hb_font_t *font, - hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height); + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height); HB_END_DECLS From 54c0cc38fba24fa4370231408ba121589b190a28 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 11:56:40 +0100 Subject: [PATCH 08/32] [MATH] Clean up get_math_constant implementation --- src/hb-ot-layout-math-table.hh | 10 +++++----- src/hb-ot-layout.cc | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 7f6c6b09c..cbdee485f 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -77,7 +77,8 @@ struct MathConstants return_trace (c->check_struct (this) && sanitize_math_value_records(c)); } - inline hb_position_t get_value (hb_font_t *font, hb_ot_math_constant_t constant) const + inline hb_position_t get_value (hb_ot_math_constant_t constant, + hb_font_t *font) const { switch (constant) { @@ -437,10 +438,9 @@ struct MATH mathGlyphInfo.sanitize (c, this)); } - inline bool has_math_constants (void) const { return mathConstants != 0; } - inline const MathConstants &get_math_constants (void) const { - return this+mathConstants; - } + inline hb_position_t get_constant (hb_ot_math_constant_t constant, + hb_font_t *font) const + { return (this+mathConstants).get_value (constant, font); } inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; } inline const MathGlyphInfo &get_math_glyph_info (void) const { diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 3dcdfb697..359d94185 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1259,15 +1259,14 @@ hb_ot_layout_has_math_data (hb_face_t *face) * * Return value: the requested constant or 0 * - * Since: ???? + * Since: 1.4 **/ hb_position_t hb_ot_layout_get_math_constant (hb_font_t *font, hb_ot_math_constant_t constant) { const OT::MATH &math = _get_math (font->face); - return math.has_math_constants() ? - math.get_math_constants().get_value(font, constant) : 0; + return math.get_constant(constant, font); } /** From 06003f71ba0d0327fb1a17098a9d7faa8fb336f0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 12:07:29 +0100 Subject: [PATCH 09/32] [MATH] Clean up a bit more --- src/hb-ot-layout-math-table.hh | 12 +------ src/hb-ot-layout.cc | 57 +++++++++++++--------------------- 2 files changed, 22 insertions(+), 47 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index cbdee485f..53038e3ec 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -367,17 +367,11 @@ struct MathGlyphInfo mathKernInfo.sanitize(c, this)); } - inline bool has_math_italics_correction_info (void) const { - return mathItalicsCorrectionInfo != 0; - } inline const MathItalicsCorrectionInfo& get_math_italics_correction_info (void) const { return this+mathItalicsCorrectionInfo; } - inline bool has_math_top_accent_attachment (void) const { - return mathTopAccentAttachment != 0; - } inline const MathTopAccentAttachment& get_math_top_accent_attachment (void) const { return this+mathTopAccentAttachment; @@ -385,13 +379,10 @@ struct MathGlyphInfo inline bool is_extended_shape (hb_codepoint_t glyph) const { - if (likely (extendedShapeCoverage == 0)) return false; unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; - return true; + return index != NOT_COVERED; } - inline bool has_math_kern_info (void) const { return mathKernInfo != 0; } inline const MathKernInfo &get_math_kern_info (void) const { return this+mathKernInfo; } @@ -442,7 +433,6 @@ struct MATH hb_font_t *font) const { return (this+mathConstants).get_value (constant, font); } - inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; } inline const MathGlyphInfo &get_math_glyph_info (void) const { return this+mathGlyphInfo; } diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 359d94185..6fa61a44a 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1277,23 +1277,19 @@ hb_ot_layout_get_math_constant (hb_font_t *font, * * Return value: the italic correction of the glyph or 0 * - * Since: ???? + * Since: 1.4 **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_italic_correction (hb_font_t *font, hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); - if (math.has_math_glyph_info()) { - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - if (glyphInfo.has_math_italics_correction_info()) { - hb_position_t value; - if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, - value)) - return value; - } - } - return 0; + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + hb_position_t value; + if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, value)) + return value; + else + return 0; } /** @@ -1304,23 +1300,19 @@ hb_ot_layout_get_math_italic_correction (hb_font_t *font, * * Return value: the top accent attachment of the glyph or 0 * - * Since: ???? + * Since: 1.4 **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); - if (math.has_math_glyph_info()) { - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - if (glyphInfo.has_math_top_accent_attachment()) { - hb_position_t value; - if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, - value)) - return value; - } - } - return 0; + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + hb_position_t value; + if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, value)) + return value; + else + return 0; // XXX font->get_glyph_h_advance (glyph) / 2; } /** @@ -1331,15 +1323,14 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, * * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise * - * Since: ???? + * Since: 1.4 **/ HB_EXTERN hb_bool_t hb_ot_layout_is_math_extended_shape (hb_face_t *face, hb_codepoint_t glyph) { const OT::MATH &math = _get_math (face); - return math.has_math_glyph_info() && - math.get_math_glyph_info().is_extended_shape(glyph); + return math.get_math_glyph_info().is_extended_shape(glyph); } /** @@ -1358,7 +1349,7 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face, * * Return value: requested kerning or 0 * - * Since: ???? + * Since: 1.4 **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_kerning (hb_font_t *font, @@ -1367,14 +1358,8 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, hb_position_t correction_height) { const OT::MATH &math = _get_math (font->face); - if (math.has_math_glyph_info()) { - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - if (glyphInfo.has_math_kern_info()) { - const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); - const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph); - return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height); - } - } - - return 0; + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); + const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph); + return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height); } From 8bcf517fe59608d2247a8974445b3ff0f4b4b4ac Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 12:12:41 +0100 Subject: [PATCH 10/32] [MATH] Clean up get_italics_correction() --- src/hb-ot-layout-math-table.hh | 16 ++++++++-------- src/hb-ot-layout.cc | 17 ++++++----------- src/hb-ot-layout.h | 4 ++-- test/api/test-ot-layout-math.c | 18 +++++++++--------- 4 files changed, 25 insertions(+), 30 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 53038e3ec..3899b1612 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -173,13 +173,11 @@ struct MathItalicsCorrectionInfo italicsCorrection.sanitize (c, this)); } - inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, - hb_position_t &value) const + inline hb_position_t get_value (hb_codepoint_t glyph, + hb_font_t *font) const { unsigned int index = (this+coverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; - if (unlikely (index >= italicsCorrection.len)) return false; - value = italicsCorrection[index].get_x_value(font, this); + return italicsCorrection[index].get_x_value (font, this); return true; } @@ -367,9 +365,11 @@ struct MathGlyphInfo mathKernInfo.sanitize(c, this)); } - inline const MathItalicsCorrectionInfo& - get_math_italics_correction_info (void) const { - return this+mathItalicsCorrectionInfo; + inline hb_position_t + get_italics_correction (hb_codepoint_t glyph, + hb_font_t *font) const + { + return (this+mathItalicsCorrectionInfo).get_value (glyph, font); } inline const MathTopAccentAttachment& diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 6fa61a44a..5f171ca2b 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1270,26 +1270,21 @@ hb_ot_layout_get_math_constant (hb_font_t *font, } /** - * hb_ot_layout_get_math_italic_correction: + * hb_ot_layout_get_math_italics_correction: * * @font: #hb_font_t from which to retrieve the value * @glyph: glyph index from which to retrieve the value * - * Return value: the italic correction of the glyph or 0 + * Return value: the italics correction of the glyph or 0 * * Since: 1.4 **/ HB_EXTERN hb_position_t -hb_ot_layout_get_math_italic_correction (hb_font_t *font, - hb_codepoint_t glyph) +hb_ot_layout_get_math_italics_correction (hb_font_t *font, + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - hb_position_t value; - if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, value)) - return value; - else - return 0; + return math.get_math_glyph_info().get_italics_correction (glyph, font); } /** @@ -1330,7 +1325,7 @@ hb_ot_layout_is_math_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); + return math.get_math_glyph_info().is_extended_shape (glyph); } /** diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index f9ed2d82d..9c1c57bb4 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -311,8 +311,8 @@ hb_ot_layout_get_math_constant (hb_font_t *font, hb_ot_math_constant_t constant); HB_EXTERN hb_position_t -hb_ot_layout_get_math_italic_correction (hb_font_t *font, - hb_codepoint_t glyph); +hb_ot_layout_get_math_italics_correction (hb_font_t *font, + hb_codepoint_t glyph); HB_EXTERN hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index 5ba583f1b..a6f4453cc 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -161,35 +161,35 @@ test_get_math_constant (void) } static void -test_get_math_italic_correction (void) +test_get_math_italics_correction (void) { hb_codepoint_t glyph; initFreeType(); openFont("fonts/MathTestFontEmpty.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available closeFont(); openFont("fonts/MathTestFontPartial1.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty closeFont(); openFont("fonts/MathTestFontPartial2.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty closeFont(); openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 197); + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 197); g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 150); + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 150); g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 452); + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 452); closeFont(); cleanupFreeType(); @@ -318,7 +318,7 @@ main (int argc, char **argv) hb_test_add (test_has_math_data); hb_test_add (test_get_math_constant); - hb_test_add (test_get_math_italic_correction); + hb_test_add (test_get_math_italics_correction); hb_test_add (test_get_math_top_accent_attachment); hb_test_add (test_is_math_extended_shape); hb_test_add (test_get_math_kerning); From 17ff30e9afde79e41c17786223293e867b49ebba Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 12:18:32 +0100 Subject: [PATCH 11/32] [MATH] Clean up get_top_accent_attachment() Note, the function now returns "half of horizontal advance width" if top accent attachment for glyph is not explicitly defined. This is what the spec requires. Updated tests. --- src/hb-ot-layout-math-table.hh | 31 +++++++++++-------------------- src/hb-ot-layout.cc | 7 +------ test/api/test-ot-layout-math.c | 8 ++++---- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 3899b1612..8f7ce3db2 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -178,7 +178,6 @@ struct MathItalicsCorrectionInfo { unsigned int index = (this+coverage).get_coverage (glyph); return italicsCorrection[index].get_x_value (font, this); - return true; } protected: @@ -205,14 +204,13 @@ struct MathTopAccentAttachment topAccentAttachment.sanitize (c, this)); } - inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, - hb_position_t &value) const + inline hb_position_t get_value (hb_codepoint_t glyph, + hb_font_t *font) const { unsigned int index = (this+topAccentCoverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; - if (unlikely (index >= topAccentAttachment.len)) return false; - value = topAccentAttachment[index].get_x_value(font, this); - return true; + if (index == NOT_COVERED) + return font->get_glyph_h_advance (glyph) / 2; + return topAccentAttachment[index].get_x_value(font, this); } protected: @@ -366,22 +364,15 @@ struct MathGlyphInfo } inline hb_position_t - get_italics_correction (hb_codepoint_t glyph, - hb_font_t *font) const - { - return (this+mathItalicsCorrectionInfo).get_value (glyph, font); - } + get_italics_correction (hb_codepoint_t glyph, hb_font_t *font) const + { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); } - inline const MathTopAccentAttachment& - get_math_top_accent_attachment (void) const { - return this+mathTopAccentAttachment; - } + inline hb_position_t + get_top_accent_attachment (hb_codepoint_t glyph, hb_font_t *font) const + { return (this+mathTopAccentAttachment).get_value (glyph, font); } inline bool is_extended_shape (hb_codepoint_t glyph) const - { - unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph); - return index != NOT_COVERED; - } + { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; } inline const MathKernInfo &get_math_kern_info (void) const { return this+mathKernInfo; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 5f171ca2b..6d6cf5bc6 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1302,12 +1302,7 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - hb_position_t value; - if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, value)) - return value; - else - return 0; // XXX font->get_glyph_h_advance (glyph) / 2; + return math.get_math_glyph_info().get_top_accent_attachment (glyph, font); } /** diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index a6f4453cc..d7121a2a2 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -204,22 +204,22 @@ test_get_math_top_accent_attachment (void) openFont("fonts/MathTestFontEmpty.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available closeFont(); openFont("fonts/MathTestFontPartial1.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo empty + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty closeFont(); openFont("fonts/MathTestFontPartial2.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathTopAccentAttachment empty + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty closeFont(); openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // Glyph without top accent attachment. + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment. g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374); g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); From 94f5df5626b223ad92d0c167f560c1f2e2f19042 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 13:31:47 +0100 Subject: [PATCH 12/32] [MATH] Clean up get_kerning() --- src/hb-ot-layout-math-table.hh | 29 +++++++++++++++++------------ src/hb-ot-layout.cc | 5 +---- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 8f7ce3db2..4600eab32 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -248,8 +248,7 @@ struct MathKern sanitize_math_value_records (c)); } - inline hb_position_t get_value (hb_font_t *font, - hb_position_t &correction_height) const + inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const { const MathValueRecord* correctionHeight = mathValueRecords; const MathValueRecord* kernValue = mathValueRecords + heightCount; @@ -302,12 +301,14 @@ struct MathKernInfoRecord return_trace (true); } - inline const MathKern &get_math_kern (hb_ot_math_kern_t kern, - const void *base) const + inline hb_position_t get_kerning (hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font, + const void *base) const { unsigned int idx = kern; - if (unlikely (idx > ARRAY_LENGTH (mathKern))) return Null(MathKern); - return base+mathKern[idx]; + if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0; + return (base+mathKern[idx]).get_value (correction_height, font); } protected: @@ -329,11 +330,13 @@ struct MathKernInfo mathKernInfoRecords.sanitize (c, this)); } - inline const MathKernInfoRecord& - get_math_kern_info_record (hb_codepoint_t glyph) const + inline hb_position_t get_kerning (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font) const { unsigned int index = (this+mathKernCoverage).get_coverage (glyph); - return mathKernInfoRecords[index]; + return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); } protected: @@ -374,9 +377,11 @@ struct MathGlyphInfo inline bool is_extended_shape (hb_codepoint_t glyph) const { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; } - inline const MathKernInfo &get_math_kern_info (void) const { - return this+mathKernInfo; - } + inline hb_position_t get_kerning (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font) const + { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } protected: /* Offset to MathItalicsCorrectionInfo table - diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 6d6cf5bc6..3d87b506a 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1348,8 +1348,5 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, hb_position_t correction_height) { const OT::MATH &math = _get_math (font->face); - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); - const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph); - return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height); + return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } From 8d58e3433e242bd9dd18aa08f55ab0a406583fb0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 13:39:58 +0100 Subject: [PATCH 13/32] [MATH] Fix get_kerning() with negative y-scale --- src/hb-ot-layout-math-table.hh | 36 ++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 4600eab32..7686bf1fc 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -252,20 +252,24 @@ struct MathKern { const MathValueRecord* correctionHeight = mathValueRecords; const MathValueRecord* kernValue = mathValueRecords + heightCount; - // The description of the MathKern table is a ambiguous, but interpreting - // "between the two heights found at those indexes" for 0 < i < len as - // - // correctionHeight[i-1] < correction_height <= correctionHeight[i] - // - // makes the result consistent with the limit cases and we can just use the - // binary search algorithm of std::upper_bound: - unsigned int count = heightCount; + int sign = font->y_scale < 0 ? -1 : +1; + + /* The description of the MathKern table is a ambiguous, but interpreting + * "between the two heights found at those indexes" for 0 < i < len as + * + * correctionHeight[i-1] < correction_height <= correctionHeight[i] + * + * makes the result consistent with the limit cases and we can just use the + * binary search algorithm of std::upper_bound: + */ unsigned int i = 0; - while (count > 0) { + unsigned int count = heightCount; + while (count > 0) + { unsigned int half = count / 2; - hb_position_t height = - correctionHeight[i + half].get_y_value(font, this); - if (height < correction_height) { + hb_position_t height = correctionHeight[i + half].get_y_value(font, this); + if (sign * height < sign * correction_height) + { i += half + 1; count -= half + 1; } else @@ -279,9 +283,11 @@ protected: MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at * which the kern value changes. * Sorted by the height value in - * design units. */ - /* Array of kern values corresponding - * to heights. */ + * design units (heightCount entries), + * Followed by: + * Array of kern values corresponding + * to heights. (heightCount+1 entries). + */ public: DEFINE_SIZE_ARRAY (2, mathValueRecords); From 722e620f20fa2225cf874f4aeb115a064142fcf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Mon, 26 Sep 2016 11:51:36 +0200 Subject: [PATCH 14/32] Use G_TEST_DIST to build the path of math test fonts --- test/api/Makefile.am | 2 ++ test/api/test-ot-layout-math.c | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/api/Makefile.am b/test/api/Makefile.am index 322cd7d2a..27520ffe8 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -83,6 +83,8 @@ TESTS_ENVIRONMENT = \ G_DEBUG=gc-friendly \ G_SLICE=always-malloc \ srcdir=$(srcdir) \ + G_TEST_SRCDIR=$(abs_srcdir) \ + G_TEST_BUILDDIR=$(abs_builddir) \ $(NULL) diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index d7121a2a2..93dab740a 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -54,12 +54,16 @@ cleanupFreeType (void) static void openFont(const char* fontFile) { + gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL); + FT_Error ft_error; - if ((ft_error = FT_New_Face (ft_library, fontFile, 0, &ft_face))) + if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) { + g_free(path); abort(); + } + g_free(path); #define fontSize 1000 - if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) abort(); hb_font = hb_ft_font_create (ft_face, NULL); From 51da7a1cd672aada84bdbb3a2a8dd77ab1134249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Thu, 25 Aug 2016 11:17:50 +0200 Subject: [PATCH 15/32] MATH table: Add API to access math variants. --- src/hb-ot-layout-math-table.hh | 253 +++++++++++++++++++++++- src/hb-ot-layout-private.hh | 10 + src/hb-ot-layout.cc | 54 +++++ test/api/fonts/MathTestFontPartial4.otf | Bin 0 -> 14360 bytes test/api/test-ot-layout-math.c | 51 +++++ 5 files changed, 364 insertions(+), 4 deletions(-) create mode 100644 test/api/fonts/MathTestFontPartial4.otf diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 7686bf1fc..784f5c1a8 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -279,7 +279,7 @@ struct MathKern } protected: - USHORT heightCount; + USHORT heightCount; MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at * which the kern value changes. * Sorted by the height value in @@ -413,6 +413,243 @@ public: DEFINE_SIZE_STATIC (8); }; +struct MathGlyphVariantRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + hb_codepoint_t get_glyph() const { return variantGlyph; } + inline hb_position_t get_advance_measurement (hb_font_t *font, + bool horizontal) const + { + return horizontal ? + font->em_scale_x (advanceMeasurement) : + font->em_scale_y (advanceMeasurement); + } + +protected: + GlyphID variantGlyph; /* Glyph ID for the variant. */ + USHORT advanceMeasurement; /* Advance width/height, in design units, of the + * variant, in the direction of requested + * glyph extension. */ + +public: + DEFINE_SIZE_STATIC (2 + 2); +}; + +struct PartFlags : USHORT +{ + enum Flags { + Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ + }; + +public: + DEFINE_SIZE_STATIC (2); +}; + +struct GlyphPartRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + hb_codepoint_t get_glyph() const { return glyph; } + + inline hb_position_t + get_start_connector_length (hb_font_t *font, bool horizontal) const + { + return horizontal ? + font->em_scale_x (startConnectorLength) : + font->em_scale_y (startConnectorLength); + } + + inline hb_position_t + get_end_connector_length (hb_font_t *font, bool horizontal) const + { + return horizontal ? + font->em_scale_x (endConnectorLength) : + font->em_scale_y (endConnectorLength); + } + + inline hb_position_t + get_full_advance (hb_font_t *font, bool horizontal) const + { + return horizontal ? + font->em_scale_x (fullAdvance) : + font->em_scale_y (fullAdvance); + } + + inline bool is_extender() const { + return partFlags & PartFlags::Flags::Extender; + } + +protected: + GlyphID glyph; /* Glyph ID for the part. */ + USHORT startConnectorLength; /* Advance width/ height of the straight bar + * connector material, in design units, is at + * the beginning of the glyph, in the + * direction of the extension. */ + USHORT endConnectorLength; /* Advance width/ height of the straight bar + * connector material, in design units, is at + * the end of the glyph, in the direction of + * the extension. */ + USHORT fullAdvance; /* Full advance width/height for this part, + * in the direction of the extension. + * In design units. */ + PartFlags partFlags; /* Part qualifiers. */ + +public: + DEFINE_SIZE_STATIC (5 * 2); +}; + +struct GlyphAssembly +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + italicsCorrection.sanitize(c, this) && + partRecords.sanitize(c)); + } + + inline hb_position_t get_italic_correction (hb_font_t *font) const + { return italicsCorrection.get_x_value(font, this); } + + inline unsigned int part_record_count() const { return partRecords.len; } + inline const GlyphPartRecord &get_part_record(unsigned int i) const { + assert(i < partRecords.len); + return partRecords[i]; + } + +protected: + MathValueRecord italicsCorrection; /* Italics correction of this + * GlyphAssembly. Should not + * depend on the assembly size. */ + ArrayOf partRecords; /* Array of part records, from + * left to right and bottom to + * top. */ + +public: + DEFINE_SIZE_ARRAY (4 + 2, partRecords); +}; + +struct MathGlyphConstruction +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + glyphAssembly.sanitize(c, this) && + mathGlyphVariantRecord.sanitize(c)); + } + + inline bool has_glyph_assembly (void) const { return glyphAssembly != 0; } + inline const GlyphAssembly &get_glyph_assembly (void) const { + return this+glyphAssembly; + } + + inline unsigned int glyph_variant_count() const { + return mathGlyphVariantRecord.len; + } + inline const MathGlyphVariantRecord &get_glyph_variant(unsigned int i) const { + assert(i < mathGlyphVariantRecord.len); + return mathGlyphVariantRecord[i]; + } + +protected: + /* Offset to GlyphAssembly table for this shape - from the beginning of + MathGlyphConstruction table. May be NULL. */ + OffsetTo glyphAssembly; + + /* MathGlyphVariantRecords for alternative variants of the glyphs. */ + ArrayOf mathGlyphVariantRecord; + +public: + DEFINE_SIZE_ARRAY (2 + 2, mathGlyphVariantRecord); +}; + +struct MathVariants +{ + inline bool sanitize_offsets (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = vertGlyphCount + horizGlyphCount; + for (unsigned int i = 0; i < count; i++) + if (!glyphConstruction[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + vertGlyphCoverage.sanitize (c, this) && + horizGlyphCoverage.sanitize (c, this) && + c->check_array (glyphConstruction, + glyphConstruction[0].static_size, + vertGlyphCount + horizGlyphCount) && + sanitize_offsets (c)); + } + + inline hb_position_t get_min_connector_overlap (hb_font_t *font, + bool horizontal) const + { + return horizontal ? + font->em_scale_x (minConnectorOverlap) : + font->em_scale_y (minConnectorOverlap); + } + + inline bool + get_glyph_construction (hb_codepoint_t glyph, + hb_bool_t horizontal, + const MathGlyphConstruction *&glyph_construction) const { + unsigned int index = + horizontal ? + (this+horizGlyphCoverage).get_coverage (glyph) : + (this+vertGlyphCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + + USHORT glyphCount = horizontal ? horizGlyphCount : vertGlyphCount; + if (unlikely (index >= glyphCount)) return false; + + if (horizontal) + index += vertGlyphCount; + + glyph_construction = &(this + glyphConstruction[index]); + return true; + } + +protected: + USHORT minConnectorOverlap; /* Minimum overlap of connecting + * glyphs during glyph construction, + * in design units. */ + OffsetTo vertGlyphCoverage; /* Offset to Coverage table - + * from the beginning of MathVariants + * table. */ + OffsetTo horizGlyphCoverage; /* Offset to Coverage table - + * from the beginning of MathVariants + * table. */ + USHORT vertGlyphCount; /* Number of glyphs for which + * information is provided for + * vertically growing variants. */ + USHORT horizGlyphCount; /* Number of glyphs for which + * information is provided for + * horizontally growing variants. */ + + /* Array of offsets to MathGlyphConstruction tables - from the beginning of + the MathVariants table, for shapes growing in vertical/horizontal + direction. */ + OffsetTo glyphConstruction[VAR]; + +public: + DEFINE_SIZE_ARRAY (5 * 2, glyphConstruction); +}; + /* * MATH -- The MATH Table @@ -428,24 +665,32 @@ struct MATH return_trace (version.sanitize (c) && likely (version.major == 1) && mathConstants.sanitize (c, this) && - mathGlyphInfo.sanitize (c, this)); + mathGlyphInfo.sanitize (c, this) && + mathVariants.sanitize (c, this)); } inline hb_position_t get_constant (hb_ot_math_constant_t constant, - hb_font_t *font) const + hb_font_t *font) const { return (this+mathConstants).get_value (constant, font); } inline const MathGlyphInfo &get_math_glyph_info (void) const { return this+mathGlyphInfo; } + + inline bool has_math_variants (void) const { return mathVariants != 0; } + inline const MathVariants &get_math_variants (void) const { + return this+mathVariants; + } + protected: FixedVersion<>version; /* Version of the MATH table * initially set to 0x00010000u */ OffsetTo mathConstants;/* MathConstants table */ OffsetTo mathGlyphInfo;/* MathGlyphInfo table */ + OffsetTo mathVariants; /* MathVariants table */ public: - DEFINE_SIZE_STATIC (8); + DEFINE_SIZE_STATIC (10); }; } /* mathspace OT */ diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index a4272de63..775261a49 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -617,5 +617,15 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer) #undef lig_props #undef glyph_props +namespace OT { + struct MathGlyphConstruction; +}; + +HB_INTERNAL hb_bool_t +hb_ot_layout_get_math_glyph_construction (hb_font_t *font, + hb_codepoint_t glyph, + hb_bool_t horizontal, + hb_position_t &minConnectorOverlap, + const OT::MathGlyphConstruction *&glyph_construction); #endif /* HB_OT_LAYOUT_PRIVATE_HH */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 3d87b506a..e92d38b0b 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1350,3 +1350,57 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, const OT::MATH &math = _get_math (font->face); return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } + +#if 0 +/** + * hb_ot_layout_get_math_italic_correction_for_glyph_assembly: + * @font: an #hb_font_t with an OpenType MATH table + * @base_glyph: index of the glyph to stretch + * @horizontal: direction of the stretching + * + * This function tries and get the italic correction associated to the glyph + * assembly used to stretch the base glyph in the specified direction. + * + * Return value: the italic correction of the glyph assembly or 0 + * + * Since: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font_t *font, + hb_codepoint_t base_glyph, + hb_bool_t horizontal) +{ + const OT::MATH &math = _get_math (font->face); + + if (math.has_math_variants()) { + const OT::MathGlyphConstruction* glyph_construction; + if (math.get_math_variants(). + get_glyph_construction(base_glyph, horizontal, glyph_construction) && + glyph_construction->has_glyph_assembly()) + return glyph_construction-> + get_glyph_assembly().get_italic_correction(font); + } + + return 0; +} + +HB_INTERNAL hb_bool_t +hb_ot_layout_get_math_glyph_construction (hb_font_t *font, + hb_codepoint_t glyph, + hb_bool_t horizontal, + hb_position_t &minConnectorOverlap, + const OT::MathGlyphConstruction *&glyph_construction) +{ + const OT::MATH &math = _get_math (font->face); + + if (!math.has_math_variants()) return false; + + const OT::MathVariants &mathVariants = math.get_math_variants(); + if (!mathVariants.get_glyph_construction(glyph, horizontal, + glyph_construction)) return false; + + minConnectorOverlap = mathVariants.get_min_connector_overlap(font, horizontal); + + return true; +} +#endif diff --git a/test/api/fonts/MathTestFontPartial4.otf b/test/api/fonts/MathTestFontPartial4.otf new file mode 100644 index 0000000000000000000000000000000000000000..cda3057f8360d61154b3fad650c77e413e3d97f0 GIT binary patch literal 14360 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 OKcR?G6mRw~ Date: Mon, 26 Sep 2016 16:10:08 +0100 Subject: [PATCH 16/32] [MATH] Clean up math variants --- src/hb-ot-layout-math-table.hh | 35 +++++++++------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 784f5c1a8..bec53f36d 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -437,7 +437,7 @@ protected: * glyph extension. */ public: - DEFINE_SIZE_STATIC (2 + 2); + DEFINE_SIZE_STATIC (4); }; struct PartFlags : USHORT @@ -504,7 +504,7 @@ protected: PartFlags partFlags; /* Part qualifiers. */ public: - DEFINE_SIZE_STATIC (5 * 2); + DEFINE_SIZE_STATIC (10); }; struct GlyphAssembly @@ -522,7 +522,6 @@ struct GlyphAssembly inline unsigned int part_record_count() const { return partRecords.len; } inline const GlyphPartRecord &get_part_record(unsigned int i) const { - assert(i < partRecords.len); return partRecords[i]; } @@ -535,7 +534,7 @@ protected: * top. */ public: - DEFINE_SIZE_ARRAY (4 + 2, partRecords); + DEFINE_SIZE_ARRAY (6, partRecords); }; struct MathGlyphConstruction @@ -548,19 +547,6 @@ struct MathGlyphConstruction mathGlyphVariantRecord.sanitize(c)); } - inline bool has_glyph_assembly (void) const { return glyphAssembly != 0; } - inline const GlyphAssembly &get_glyph_assembly (void) const { - return this+glyphAssembly; - } - - inline unsigned int glyph_variant_count() const { - return mathGlyphVariantRecord.len; - } - inline const MathGlyphVariantRecord &get_glyph_variant(unsigned int i) const { - assert(i < mathGlyphVariantRecord.len); - return mathGlyphVariantRecord[i]; - } - protected: /* Offset to GlyphAssembly table for this shape - from the beginning of MathGlyphConstruction table. May be NULL. */ @@ -570,7 +556,7 @@ protected: ArrayOf mathGlyphVariantRecord; public: - DEFINE_SIZE_ARRAY (2 + 2, mathGlyphVariantRecord); + DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord); }; struct MathVariants @@ -647,7 +633,7 @@ protected: OffsetTo glyphConstruction[VAR]; public: - DEFINE_SIZE_ARRAY (5 * 2, glyphConstruction); + DEFINE_SIZE_ARRAY (10, glyphConstruction); }; @@ -673,14 +659,11 @@ struct MATH hb_font_t *font) const { return (this+mathConstants).get_value (constant, font); } - inline const MathGlyphInfo &get_math_glyph_info (void) const { - return this+mathGlyphInfo; - } + inline const MathGlyphInfo &get_math_glyph_info (void) const + { return this+mathGlyphInfo; } - inline bool has_math_variants (void) const { return mathVariants != 0; } - inline const MathVariants &get_math_variants (void) const { - return this+mathVariants; - } + inline const MathVariants &get_math_variants (void) const + { return this+mathVariants; } protected: FixedVersion<>version; /* Version of the MATH table From 7fe0e28c22331a353d396f8bc1e3a60f1580a96d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 17:51:47 +0100 Subject: [PATCH 17/32] [MATH] Start fleshing out glyph variant API --- src/hb-font-private.hh | 4 ++ src/hb-ot-layout-math-table.hh | 10 ++--- src/hb-ot-layout.cc | 75 ++++++++++++---------------------- src/hb-ot-layout.h | 20 +++++++++ src/hb-ot-math.h | 18 ++++++++ 5 files changed, 72 insertions(+), 55 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 0b7557794..07bc90093 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -118,6 +118,10 @@ struct hb_font_t { /* Convert from font-space to user-space */ inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); } inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); } + inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) + { return em_scale (v, + HB_DIRECTION_IS_VERTICAL(direction) ? + this->y_scale : this->x_scale); } /* Convert from parent-font user-space to our user-space */ inline hb_position_t parent_scale_x_distance (hb_position_t v) { diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index bec53f36d..81fc1b009 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -582,13 +582,9 @@ struct MathVariants sanitize_offsets (c)); } - inline hb_position_t get_min_connector_overlap (hb_font_t *font, - bool horizontal) const - { - return horizontal ? - font->em_scale_x (minConnectorOverlap) : - font->em_scale_y (minConnectorOverlap); - } + inline hb_position_t get_min_connector_overlap (hb_direction_t direction, + hb_font_t *font) const + { return font->em_scale_dir (minConnectorOverlap, direction); } inline bool get_glyph_construction (hb_codepoint_t glyph, diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index e92d38b0b..eeebb5d77 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1279,7 +1279,7 @@ hb_ot_layout_get_math_constant (hb_font_t *font, * * Since: 1.4 **/ -HB_EXTERN hb_position_t +hb_position_t hb_ot_layout_get_math_italics_correction (hb_font_t *font, hb_codepoint_t glyph) { @@ -1297,7 +1297,7 @@ hb_ot_layout_get_math_italics_correction (hb_font_t *font, * * Since: 1.4 **/ -HB_EXTERN hb_position_t +hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, hb_codepoint_t glyph) { @@ -1315,7 +1315,7 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, * * Since: 1.4 **/ -HB_EXTERN hb_bool_t +hb_bool_t hb_ot_layout_is_math_extended_shape (hb_face_t *face, hb_codepoint_t glyph) { @@ -1351,56 +1351,35 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } -#if 0 -/** - * hb_ot_layout_get_math_italic_correction_for_glyph_assembly: - * @font: an #hb_font_t with an OpenType MATH table - * @base_glyph: index of the glyph to stretch - * @horizontal: direction of the stretching - * - * This function tries and get the italic correction associated to the glyph - * assembly used to stretch the base glyph in the specified direction. - * - * Return value: the italic correction of the glyph assembly or 0 - * - * Since: ???? - **/ -HB_EXTERN hb_position_t -hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font_t *font, - hb_codepoint_t base_glyph, - hb_bool_t horizontal) +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_variants (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variant_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */) { const OT::MATH &math = _get_math (font->face); - - if (math.has_math_variants()) { - const OT::MathGlyphConstruction* glyph_construction; - if (math.get_math_variants(). - get_glyph_construction(base_glyph, horizontal, glyph_construction) && - glyph_construction->has_glyph_assembly()) - return glyph_construction-> - get_glyph_assembly().get_italic_correction(font); - } - return 0; } -HB_INTERNAL hb_bool_t -hb_ot_layout_get_math_glyph_construction (hb_font_t *font, - hb_codepoint_t glyph, - hb_bool_t horizontal, - hb_position_t &minConnectorOverlap, - const OT::MathGlyphConstruction *&glyph_construction) +hb_position_t +hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, + hb_direction_t direction) { const OT::MATH &math = _get_math (font->face); - - if (!math.has_math_variants()) return false; - - const OT::MathVariants &mathVariants = math.get_math_variants(); - if (!mathVariants.get_glyph_construction(glyph, horizontal, - glyph_construction)) return false; - - minConnectorOverlap = mathVariants.get_min_connector_overlap(font, horizontal); - - return true; + return math.get_math_variants().get_min_connector_overlap (direction, font); +} + +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italic_correction /* OUT */) +{ + const OT::MATH &math = _get_math (font->face); + return 0; } -#endif diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 9c1c57bb4..8eb8d6cbd 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -328,6 +328,26 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, hb_ot_math_kern_t kern, hb_position_t correction_height); +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_variants (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variant_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, + hb_direction_t direction); + +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italic_correction /* OUT */); HB_END_DECLS diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index a62b4b612..bf37975d2 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -102,6 +102,24 @@ typedef enum { HB_OT_MATH_KERN_BOTTOM_LEFT = 3 } hb_ot_math_kern_t; +typedef struct hb_math_glyph_variant_t { + hb_codepoint_t glyph; + hb_position_t advance; +} hb_math_glyph_variant_t; + +typedef enum { /*< flags >*/ + HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ +} hb_math_glyph_part_flags_t; + +typedef struct hb_math_glyph_part_t { + hb_codepoint_t glyph; + hb_position_t start_connector_length; + hb_position_t end_connector_length; + hb_position_t full_advance; + hb_math_glyph_part_flags_t flags; +} hb_math_glyph_part_t; + + HB_END_DECLS #endif /* HB_OT_MATH_H */ From 353f455af7ccbc1af8338dcb0c8ab87aef866c79 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 21:22:48 +0200 Subject: [PATCH 18/32] [MATH] Wire up get_glyph_variants() --- src/hb-font-private.hh | 11 +- src/hb-ot-layout-math-table.hh | 178 ++++++++++++++++----------------- src/hb-ot-layout.cc | 7 +- src/hb-ot-layout.h | 2 +- 4 files changed, 95 insertions(+), 103 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 07bc90093..6d5012ec1 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -116,12 +116,12 @@ struct hb_font_t { /* Convert from font-space to user-space */ - inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); } - inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); } + inline int dir_scale (hb_direction_t direction) + { 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_scale_dir (int16_t v, hb_direction_t direction) - { return em_scale (v, - HB_DIRECTION_IS_VERTICAL(direction) ? - this->y_scale : this->x_scale); } + { return em_scale (v, dir_scale (direction)); } /* Convert from parent-font user-space to our user-space */ inline hb_position_t parent_scale_x_distance (hb_position_t v) { @@ -508,7 +508,6 @@ struct hb_font_t { return false; } - private: inline hb_position_t em_scale (int16_t v, int scale) { int upem = face->get_upem (); diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 81fc1b009..da65c3886 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -47,13 +47,13 @@ struct MathValueRecord return_trace (c->check_struct (this) && deviceTable.sanitize (c, base)); } -protected: + protected: SHORT value; /* The X or Y value in design units */ OffsetTo deviceTable; /* Offset to the device table - from the * beginning of parent table. May be NULL. * Suggested format for device table is 1. */ -public: + public: DEFINE_SIZE_STATIC (4); }; @@ -153,13 +153,13 @@ struct MathConstants } } -protected: + protected: SHORT percentScaleDown[2]; USHORT minHeight[2]; MathValueRecord mathValueRecords[51]; SHORT radicalDegreeBottomRaisePercent; -public: + public: DEFINE_SIZE_STATIC (214); }; @@ -180,7 +180,7 @@ struct MathItalicsCorrectionInfo return italicsCorrection[index].get_x_value (font, this); } -protected: + protected: OffsetTo coverage; /* Offset to Coverage table - * from the beginning of * MathItalicsCorrectionInfo @@ -190,7 +190,7 @@ protected: * values for each * covered glyph. */ -public: + public: DEFINE_SIZE_ARRAY (4, italicsCorrection); }; @@ -213,7 +213,7 @@ struct MathTopAccentAttachment return topAccentAttachment[index].get_x_value(font, this); } -protected: + protected: OffsetTo topAccentCoverage; /* Offset to Coverage table - * from the beginning of * MathTopAccentAttachment @@ -223,7 +223,7 @@ protected: * attachment points for each * covered glyph. */ -public: + public: DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); }; @@ -278,7 +278,7 @@ struct MathKern return kernValue[i].get_x_value(font, this); } -protected: + protected: USHORT heightCount; MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at * which the kern value changes. @@ -289,7 +289,7 @@ protected: * to heights. (heightCount+1 entries). */ -public: + public: DEFINE_SIZE_ARRAY (2, mathValueRecords); }; @@ -317,12 +317,12 @@ struct MathKernInfoRecord return (base+mathKern[idx]).get_value (correction_height, font); } -protected: + protected: /* Offset to MathKern table for each corner - * from the beginning of MathKernInfo table. May be NULL. */ OffsetTo mathKern[4]; -public: + public: DEFINE_SIZE_STATIC (8); }; @@ -345,7 +345,7 @@ struct MathKernInfo return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); } -protected: + protected: OffsetTo mathKernCoverage; /* Offset to Coverage table - * from the beginning of the * MathKernInfo table. */ @@ -356,7 +356,7 @@ protected: * of subscripts and * superscripts. */ -public: + public: DEFINE_SIZE_ARRAY (4, mathKernInfoRecords); }; @@ -389,7 +389,7 @@ struct MathGlyphInfo hb_font_t *font) const { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } -protected: + protected: /* Offset to MathItalicsCorrectionInfo table - * from the beginning of MathGlyphInfo table. */ OffsetTo mathItalicsCorrectionInfo; @@ -409,34 +409,27 @@ protected: * from the beginning of MathGlyphInfo table. */ OffsetTo mathKernInfo; -public: + public: DEFINE_SIZE_STATIC (8); }; struct MathGlyphVariantRecord { + friend struct MathGlyphConstruction; + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } - hb_codepoint_t get_glyph() const { return variantGlyph; } - inline hb_position_t get_advance_measurement (hb_font_t *font, - bool horizontal) const - { - return horizontal ? - font->em_scale_x (advanceMeasurement) : - font->em_scale_y (advanceMeasurement); - } - -protected: + protected: GlyphID variantGlyph; /* Glyph ID for the variant. */ USHORT advanceMeasurement; /* Advance width/height, in design units, of the * variant, in the direction of requested * glyph extension. */ -public: + public: DEFINE_SIZE_STATIC (4); }; @@ -446,49 +439,21 @@ struct PartFlags : USHORT Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ }; -public: + public: DEFINE_SIZE_STATIC (2); }; -struct GlyphPartRecord +struct MathGlyphPartRecord { + friend struct MathGlyphAssembly; + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } - hb_codepoint_t get_glyph() const { return glyph; } - - inline hb_position_t - get_start_connector_length (hb_font_t *font, bool horizontal) const - { - return horizontal ? - font->em_scale_x (startConnectorLength) : - font->em_scale_y (startConnectorLength); - } - - inline hb_position_t - get_end_connector_length (hb_font_t *font, bool horizontal) const - { - return horizontal ? - font->em_scale_x (endConnectorLength) : - font->em_scale_y (endConnectorLength); - } - - inline hb_position_t - get_full_advance (hb_font_t *font, bool horizontal) const - { - return horizontal ? - font->em_scale_x (fullAdvance) : - font->em_scale_y (fullAdvance); - } - - inline bool is_extender() const { - return partFlags & PartFlags::Flags::Extender; - } - -protected: + protected: GlyphID glyph; /* Glyph ID for the part. */ USHORT startConnectorLength; /* Advance width/ height of the straight bar * connector material, in design units, is at @@ -503,11 +468,11 @@ protected: * In design units. */ PartFlags partFlags; /* Part qualifiers. */ -public: + public: DEFINE_SIZE_STATIC (10); }; -struct GlyphAssembly +struct MathGlyphAssembly { inline bool sanitize (hb_sanitize_context_t *c) const { @@ -520,20 +485,15 @@ struct GlyphAssembly inline hb_position_t get_italic_correction (hb_font_t *font) const { return italicsCorrection.get_x_value(font, this); } - inline unsigned int part_record_count() const { return partRecords.len; } - inline const GlyphPartRecord &get_part_record(unsigned int i) const { - return partRecords[i]; - } - -protected: + protected: MathValueRecord italicsCorrection; /* Italics correction of this - * GlyphAssembly. Should not + * MathGlyphAssembly. Should not * depend on the assembly size. */ - ArrayOf partRecords; /* Array of part records, from + ArrayOf partRecords; /* Array of part records, from * left to right and bottom to * top. */ -public: + public: DEFINE_SIZE_ARRAY (6, partRecords); }; @@ -547,15 +507,36 @@ struct MathGlyphConstruction mathGlyphVariantRecord.sanitize(c)); } -protected: - /* Offset to GlyphAssembly table for this shape - from the beginning of + inline unsigned int get_variants (hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */) const + { + if (variants_count) + { + int scale = font->dir_scale (direction); + const MathGlyphVariantRecord *arr = + mathGlyphVariantRecord.sub_array (start_offset, variants_count); + unsigned int count = *variants_count; + for (unsigned int i = 0; i < count; i++) + { + variants[i].glyph = arr[i].variantGlyph; + variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale); + } + } + return mathGlyphVariantRecord.len; + } + + protected: + /* Offset to MathGlyphAssembly table for this shape - from the beginning of MathGlyphConstruction table. May be NULL. */ - OffsetTo glyphAssembly; + OffsetTo glyphAssembly; /* MathGlyphVariantRecords for alternative variants of the glyphs. */ ArrayOf mathGlyphVariantRecord; -public: + public: DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord); }; @@ -586,27 +567,36 @@ struct MathVariants hb_font_t *font) const { return font->em_scale_dir (minConnectorOverlap, direction); } - inline bool - get_glyph_construction (hb_codepoint_t glyph, - hb_bool_t horizontal, - const MathGlyphConstruction *&glyph_construction) const { - unsigned int index = - horizontal ? - (this+horizGlyphCoverage).get_coverage (glyph) : - (this+vertGlyphCoverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; + inline unsigned int get_glyph_variants (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */) const + { return get_glyph_construction (glyph, direction, font) + .get_variants (direction, font, start_offset, variants_count, variants); } - USHORT glyphCount = horizontal ? horizGlyphCount : vertGlyphCount; - if (unlikely (index >= glyphCount)) return false; + private: + inline const MathGlyphConstruction & + get_glyph_construction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font) const + { + bool vertical = HB_DIRECTION_IS_VERTICAL (direction); + unsigned int count = vertical ? vertGlyphCount : horizGlyphCount; + const OffsetTo &coverage = vertical ? vertGlyphCoverage + : horizGlyphCoverage; - if (horizontal) + unsigned int index = (this+coverage).get_coverage (glyph); + if (unlikely (index >= count)) return Null(MathGlyphConstruction); + + if (!vertical) index += vertGlyphCount; - glyph_construction = &(this + glyphConstruction[index]); - return true; + return this+glyphConstruction[index]; } -protected: + protected: USHORT minConnectorOverlap; /* Minimum overlap of connecting * glyphs during glyph construction, * in design units. */ @@ -626,9 +616,9 @@ protected: /* Array of offsets to MathGlyphConstruction tables - from the beginning of the MathVariants table, for shapes growing in vertical/horizontal direction. */ - OffsetTo glyphConstruction[VAR]; + OffsetTo glyphConstruction[VAR]; -public: + public: DEFINE_SIZE_ARRAY (10, glyphConstruction); }; @@ -661,14 +651,14 @@ struct MATH inline const MathVariants &get_math_variants (void) const { return this+mathVariants; } -protected: + protected: FixedVersion<>version; /* Version of the MATH table * initially set to 0x00010000u */ OffsetTo mathConstants;/* MathConstants table */ OffsetTo mathGlyphInfo;/* MathGlyphInfo table */ OffsetTo mathVariants; /* MathVariants table */ -public: + public: DEFINE_SIZE_STATIC (10); }; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index eeebb5d77..0d3f19bef 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1356,11 +1356,14 @@ hb_ot_layout_get_math_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, unsigned int start_offset, - unsigned int *variant_count, /* IN/OUT */ + unsigned int *variants_count, /* IN/OUT */ hb_math_glyph_variant_t *variants /* OUT */) { const OT::MATH &math = _get_math (font->face); - return 0; + return math.get_math_variants().get_glyph_variants (glyph, direction, font, + start_offset, + variants_count, + variants); } hb_position_t diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 8eb8d6cbd..4c01d6310 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -333,7 +333,7 @@ hb_ot_layout_get_math_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, unsigned int start_offset, - unsigned int *variant_count, /* IN/OUT */ + unsigned int *variants_count, /* IN/OUT */ hb_math_glyph_variant_t *variants /* OUT */); HB_EXTERN hb_position_t From 559eb564472575ae4d87a241314b8a3ca24418c4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 21:46:05 +0200 Subject: [PATCH 19/32] [MATH] Wire up get_glyph_assembly() --- src/hb-ot-layout-math-table.hh | 64 +++++++++++++++++++++++++++++++--- src/hb-ot-layout.cc | 26 ++++++++------ src/hb-ot-layout.h | 14 ++++---- 3 files changed, 81 insertions(+), 23 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index da65c3886..886ed2dca 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -436,7 +436,9 @@ struct MathGlyphVariantRecord struct PartFlags : USHORT { enum Flags { - Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ + Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ + + Defined = 0x0001u, /* All defined flags. */ }; public: @@ -445,14 +447,30 @@ struct PartFlags : USHORT struct MathGlyphPartRecord { - friend struct MathGlyphAssembly; - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } + inline void extract (hb_math_glyph_part_t &out, + int scale, + hb_font_t *font) const + { + out.glyph = glyph; + + out.start_connector_length = font->em_scale (startConnectorLength, scale); + out.end_connector_length = font->em_scale (endConnectorLength, scale); + out.full_advance = font->em_scale (fullAdvance, scale); + + ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER == + (unsigned int) PartFlags::Extender); + + out.flags = (hb_math_glyph_part_flags_t) + (unsigned int) + (partFlags & PartFlags::Defined); + } + protected: GlyphID glyph; /* Glyph ID for the part. */ USHORT startConnectorLength; /* Advance width/ height of the straight bar @@ -482,8 +500,28 @@ struct MathGlyphAssembly partRecords.sanitize(c)); } - inline hb_position_t get_italic_correction (hb_font_t *font) const - { return italicsCorrection.get_x_value(font, this); } + inline unsigned int get_parts (hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts /* OUT */, + hb_position_t *italics_correction /* OUT */) const + { + if (parts_count) + { + int scale = font->dir_scale (direction); + const MathGlyphPartRecord *arr = + partRecords.sub_array (start_offset, parts_count); + unsigned int count = *parts_count; + for (unsigned int i = 0; i < count; i++) + arr[i].extract (parts[i], scale, font); + } + + if (italics_correction) + *italics_correction = italicsCorrection.get_x_value (font, this); + + return partRecords.len; + } protected: MathValueRecord italicsCorrection; /* Italics correction of this @@ -507,6 +545,9 @@ struct MathGlyphConstruction mathGlyphVariantRecord.sanitize(c)); } + inline const MathGlyphAssembly &get_assembly (void) const + { return this+glyphAssembly; } + inline unsigned int get_variants (hb_direction_t direction, hb_font_t *font, unsigned int start_offset, @@ -576,6 +617,19 @@ struct MathVariants { return get_glyph_construction (glyph, direction, font) .get_variants (direction, font, start_offset, variants_count, variants); } + inline unsigned int get_glyph_parts (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts /* OUT */, + hb_position_t *italics_correction /* OUT */) const + { return get_glyph_construction (glyph, direction, font) + .get_assembly () + .get_parts (direction, font, + start_offset, parts_count, parts, + italics_correction); } + private: inline const MathGlyphConstruction & get_glyph_construction (hb_codepoint_t glyph, diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 0d3f19bef..942158e80 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1341,7 +1341,7 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face, * * Since: 1.4 **/ -HB_EXTERN hb_position_t +hb_position_t hb_ot_layout_get_math_kerning (hb_font_t *font, hb_codepoint_t glyph, hb_ot_math_kern_t kern, @@ -1351,7 +1351,7 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } -HB_EXTERN unsigned int +unsigned int hb_ot_layout_get_math_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, @@ -1374,15 +1374,19 @@ hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, return math.get_math_variants().get_min_connector_overlap (direction, font); } -HB_EXTERN unsigned int -hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italic_correction /* OUT */) +unsigned int +hb_ot_layout_get_math_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_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */) { const OT::MATH &math = _get_math (font->face); - return 0; + return math.get_math_variants().get_glyph_parts (glyph, direction, font, + start_offset, + parts_count, + parts, + italics_correction); } diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 4c01d6310..b6fbd00a5 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -341,13 +341,13 @@ hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, hb_direction_t direction); HB_EXTERN unsigned int -hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italic_correction /* OUT */); +hb_ot_layout_get_math_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_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */); HB_END_DECLS From 97b72da6006d8d6355ee90d514f627e6604a4936 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 21:53:25 +0200 Subject: [PATCH 20/32] Whitespace --- src/hb-ot-layout-math-table.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 886ed2dca..efffd2b53 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -514,7 +514,7 @@ struct MathGlyphAssembly partRecords.sub_array (start_offset, parts_count); unsigned int count = *parts_count; for (unsigned int i = 0; i < count; i++) - arr[i].extract (parts[i], scale, font); + arr[i].extract (parts[i], scale, font); } if (italics_correction) From 1ba767cd4e3606beb9dc59806b83b1e61f5958d4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 21:57:14 +0200 Subject: [PATCH 21/32] [MATH] Move API from hb-ot-layout.h to hb-ot-math.h --- src/hb-ot-layout.h | 52 ------------------------------------------ src/hb-ot-math.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++ src/hb-ot.h | 1 + 3 files changed, 57 insertions(+), 52 deletions(-) diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index b6fbd00a5..eb23d45b6 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -33,7 +33,6 @@ #include "hb.h" -#include "hb-ot-math.h" #include "hb-ot-tag.h" HB_BEGIN_DECLS @@ -43,7 +42,6 @@ HB_BEGIN_DECLS #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B') #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S') #define HB_OT_TAG_JSTF HB_TAG('J','S','T','F') -#define HB_OT_TAG_MATH HB_TAG('M','A','T','H') /* @@ -299,56 +297,6 @@ hb_ot_layout_get_size_params (hb_face_t *face, unsigned int *range_end /* OUT. May be NULL */); -/* - * MATH - */ - -HB_EXTERN hb_bool_t -hb_ot_layout_has_math_data (hb_face_t *face); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_italics_correction (hb_font_t *font, - hb_codepoint_t glyph); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph); - -HB_EXTERN hb_bool_t -hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_kerning (hb_font_t *font, - hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height); - -HB_EXTERN unsigned int -hb_ot_layout_get_math_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_math_glyph_variant_t *variants /* OUT */); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, - hb_direction_t direction); - -HB_EXTERN unsigned int -hb_ot_layout_get_math_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_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italics_correction /* OUT */); - HB_END_DECLS #endif /* HB_OT_LAYOUT_H */ diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index bf37975d2..5ff19fd24 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -36,6 +36,14 @@ HB_BEGIN_DECLS +/* + * MATH + */ + +#define HB_OT_TAG_MATH HB_TAG('M','A','T','H') + +/* Types */ + typedef enum { HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1, @@ -119,6 +127,54 @@ typedef struct hb_math_glyph_part_t { hb_math_glyph_part_flags_t flags; } hb_math_glyph_part_t; +/* Methods */ + +HB_EXTERN hb_bool_t +hb_ot_layout_has_math_data (hb_face_t *face); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_constant (hb_font_t *font, + hb_ot_math_constant_t constant); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italics_correction (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_bool_t +hb_ot_layout_is_math_extended_shape (hb_face_t *face, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height); + +HB_EXTERN unsigned int +hb_ot_layout_get_math_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_math_glyph_variant_t *variants /* OUT */); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, + hb_direction_t direction); + +HB_EXTERN unsigned int +hb_ot_layout_get_math_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_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */); + HB_END_DECLS diff --git a/src/hb-ot.h b/src/hb-ot.h index 47c92a58e..113e37b08 100644 --- a/src/hb-ot.h +++ b/src/hb-ot.h @@ -32,6 +32,7 @@ #include "hb-ot-font.h" #include "hb-ot-layout.h" +#include "hb-ot-math.h" #include "hb-ot-tag.h" #include "hb-ot-shape.h" From 86106c7528d9bff8de6bc3e1487be780c31ea4fd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 22:12:48 +0200 Subject: [PATCH 22/32] [MATH] Rename all API to hb_ot_math_* --- src/hb-ot-layout-private.hh | 10 - src/hb-ot-layout.cc | 69 +++--- src/hb-ot-math.h | 58 ++--- test/api/Makefile.am | 6 +- test/api/test-ot-layout-math.c | 382 --------------------------------- test/api/test-ot-math.c | 381 ++++++++++++++++++++++++++++++++ 6 files changed, 448 insertions(+), 458 deletions(-) delete mode 100644 test/api/test-ot-layout-math.c create mode 100644 test/api/test-ot-math.c diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 775261a49..a4272de63 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -617,15 +617,5 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer) #undef lig_props #undef glyph_props -namespace OT { - struct MathGlyphConstruction; -}; - -HB_INTERNAL hb_bool_t -hb_ot_layout_get_math_glyph_construction (hb_font_t *font, - hb_codepoint_t glyph, - hb_bool_t horizontal, - hb_position_t &minConnectorOverlap, - const OT::MathGlyphConstruction *&glyph_construction); #endif /* HB_OT_LAYOUT_PRIVATE_HH */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 942158e80..588f5ab00 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1225,9 +1225,10 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, /* * MATH */ +/* TODO Move this to hb-ot-math.cc and separate it from hb_ot_layout_t. */ /** - * hb_ot_layout_has_math_data: + * hb_ot_math_has_data: * * @face: #hb_face_t to test * @@ -1240,13 +1241,13 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, * Since: 1.4 **/ hb_bool_t -hb_ot_layout_has_math_data (hb_face_t *face) +hb_ot_math_has_data (hb_face_t *face) { return &_get_math (face) != &OT::Null(OT::MATH); } /** - * hb_ot_layout_get_math_constant: + * 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 @@ -1262,15 +1263,15 @@ hb_ot_layout_has_math_data (hb_face_t *face) * Since: 1.4 **/ hb_position_t -hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant) +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_layout_get_math_italics_correction: + * 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 @@ -1280,15 +1281,15 @@ hb_ot_layout_get_math_constant (hb_font_t *font, * Since: 1.4 **/ hb_position_t -hb_ot_layout_get_math_italics_correction (hb_font_t *font, - hb_codepoint_t glyph) +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_layout_get_math_top_accent_attachment: + * 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 @@ -1298,15 +1299,15 @@ hb_ot_layout_get_math_italics_correction (hb_font_t *font, * Since: 1.4 **/ hb_position_t -hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph) +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_layout_is_math_extended_shape: + * hb_ot_math_is_glyph_extended_shape: * * @font: a #hb_font_t to test * @glyph: a glyph index to test @@ -1316,15 +1317,15 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, * Since: 1.4 **/ hb_bool_t -hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph) +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_layout_get_math_kerning: + * 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 @@ -1342,22 +1343,22 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face, * Since: 1.4 **/ hb_position_t -hb_ot_layout_get_math_kerning (hb_font_t *font, - hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height) +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); } unsigned int -hb_ot_layout_get_math_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_math_glyph_variant_t *variants /* OUT */) +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_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, @@ -1367,21 +1368,21 @@ hb_ot_layout_get_math_glyph_variants (hb_font_t *font, } hb_position_t -hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, - hb_direction_t direction) +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); } unsigned int -hb_ot_layout_get_math_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_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italics_correction /* OUT */) +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_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, diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 5ff19fd24..ad8bf14e5 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -130,50 +130,50 @@ typedef struct hb_math_glyph_part_t { /* Methods */ HB_EXTERN hb_bool_t -hb_ot_layout_has_math_data (hb_face_t *face); +hb_ot_math_has_data (hb_face_t *face); HB_EXTERN hb_position_t -hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant); +hb_ot_math_get_constant (hb_font_t *font, + hb_ot_math_constant_t constant); HB_EXTERN hb_position_t -hb_ot_layout_get_math_italics_correction (hb_font_t *font, - hb_codepoint_t glyph); +hb_ot_math_get_glyph_italics_correction (hb_font_t *font, + hb_codepoint_t glyph); HB_EXTERN hb_position_t -hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph); +hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph); HB_EXTERN hb_bool_t -hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph); +hb_ot_math_is_glyph_extended_shape (hb_face_t *face, + hb_codepoint_t glyph); HB_EXTERN hb_position_t -hb_ot_layout_get_math_kerning (hb_font_t *font, +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); + +HB_EXTERN unsigned int +hb_ot_math_get_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height); - -HB_EXTERN unsigned int -hb_ot_layout_get_math_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_math_glyph_variant_t *variants /* OUT */); + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */); HB_EXTERN hb_position_t -hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, - hb_direction_t direction); +hb_ot_math_get_min_connector_overlap (hb_font_t *font, + hb_direction_t direction); HB_EXTERN unsigned int -hb_ot_layout_get_math_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_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italics_correction /* OUT */); +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_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */); HB_END_DECLS diff --git a/test/api/Makefile.am b/test/api/Makefile.am index 27520ffe8..58f49146a 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -50,10 +50,10 @@ TEST_PROGS += \ if HAVE_FREETYPE TEST_PROGS += \ - test-ot-layout-math \ + test-ot-math \ $(NULL) -test_ot_layout_math_LDADD = $(LDADD) $(FREETYPE_LIBS) -test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS) +test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS) +test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS) endif # HAVE_FREETYPE endif # HAVE_OT diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c deleted file mode 100644 index 34ed0fc06..000000000 --- a/test/api/test-ot-layout-math.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * 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-test.h" - -#include "hb-ft.h" -#include "hb-ot.h" - -/* Unit tests for hb-ot-layout.h - OpenType MATH table */ - -static FT_Library ft_library; -static FT_Face ft_face; -static hb_font_t *hb_font; -static hb_face_t *hb_face; - -static inline void -initFreeType (void) -{ - FT_Error ft_error; - if ((ft_error = FT_Init_FreeType (&ft_library))) - abort(); -} - -static inline void -cleanupFreeType (void) -{ - FT_Done_FreeType (ft_library); -} - -static void -openFont(const char* fontFile) -{ - gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL); - - FT_Error ft_error; - if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) { - g_free(path); - abort(); - } - g_free(path); - -#define fontSize 1000 - if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) - abort(); - hb_font = hb_ft_font_create (ft_face, NULL); - hb_face = hb_ft_face_create_cached(ft_face); -} - -static inline void -closeFont (void) -{ - hb_font_destroy (hb_font); - FT_Done_Face (ft_face); -} - -static void -test_has_math_data (void) -{ - initFreeType(); - - openFont("fonts/MathTestFontNone.otf"); - g_assert(!hb_ot_layout_has_math_data (hb_face)); // MATH table not available - closeFont(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_ot_layout_has_math_data (hb_face)); // MATH table available - closeFont(); - - cleanupFreeType(); -} - -static void -test_get_math_constant (void) -{ - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert_cmpint(hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65); - closeFont(); - - cleanupFreeType(); -} - -static void -test_get_math_italics_correction (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available - closeFont(); - - openFont("fonts/MathTestFontPartial1.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty - closeFont(); - - openFont("fonts/MathTestFontPartial2.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. - g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 197); - g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 150); - g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 452); - closeFont(); - - cleanupFreeType(); - -} - -static void -test_get_math_top_accent_attachment (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available - closeFont(); - - openFont("fonts/MathTestFontPartial1.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty - closeFont(); - - openFont("fonts/MathTestFontPartial2.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment. - g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374); - g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 346); - g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 318); - closeFont(); - - cleanupFreeType(); -} - -static void -test_is_math_extended_shape (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo not available - closeFont(); - - openFont("fonts/MathTestFontPartial1.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo empty - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph)); - g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); - g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph)); - g_assert(hb_ot_layout_is_math_extended_shape (hb_face, glyph)); - closeFont(); - - cleanupFreeType(); -} - -static void -test_get_math_kerning (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available - closeFont(); - - openFont("fonts/MathTestFontPartial2.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty - closeFont(); - - openFont("fonts/MathTestFontPartial3.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); - - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height - - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left - - closeFont(); - - cleanupFreeType(); -} - - -#if 0 -static void -test_get_math_italic_correction_for_glyph_assembly (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available - closeFont(); - - openFont("fonts/MathTestFontPartial1.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent - closeFont(); - - openFont("fonts/MathTestFontPartial2.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty - closeFont(); - - openFont("fonts/MathTestFontPartial3.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty - closeFont(); - - openFont("fonts/MathTestFontPartial4.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); - g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331); - closeFont(); - - cleanupFreeType(); -} -#endif - -int -main (int argc, char **argv) -{ - hb_test_init (&argc, &argv); - - hb_test_add (test_has_math_data); - hb_test_add (test_get_math_constant); - hb_test_add (test_get_math_italics_correction); - hb_test_add (test_get_math_top_accent_attachment); - hb_test_add (test_is_math_extended_shape); - hb_test_add (test_get_math_kerning); - //hb_test_add (test_get_math_italic_correction_for_glyph_assembly); - - return hb_test_run(); -} diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c new file mode 100644 index 000000000..23c19eff3 --- /dev/null +++ b/test/api/test-ot-math.c @@ -0,0 +1,381 @@ +/* + * 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-test.h" + +#include "hb-ft.h" +#include "hb-ot.h" + +/* Unit tests for hb-ot-math.h - OpenType MATH table */ + +static FT_Library ft_library; +static FT_Face ft_face; +static hb_font_t *hb_font; +static hb_face_t *hb_face; + +static inline void +initFreeType (void) +{ + FT_Error ft_error; + if ((ft_error = FT_Init_FreeType (&ft_library))) + abort(); +} + +static inline void +cleanupFreeType (void) +{ + FT_Done_FreeType (ft_library); +} + +static void +openFont(const char* fontFile) +{ + gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL); + + FT_Error ft_error; + if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) { + g_free(path); + abort(); + } + g_free(path); + +#define fontSize 1000 + if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) + abort(); + hb_font = hb_ft_font_create (ft_face, NULL); + hb_face = hb_ft_face_create_cached(ft_face); +} + +static inline void +closeFont (void) +{ + hb_font_destroy (hb_font); + FT_Done_Face (ft_face); +} + +static void +test_has_data (void) +{ + initFreeType(); + + openFont("fonts/MathTestFontNone.otf"); + g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available + closeFont(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_ot_math_has_data (hb_face)); // MATH table available + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_constant (void) +{ + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert_cmpint(hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65); + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_glyph_italics_correction (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. + g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 197); + g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 150); + g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 452); + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_glyph_top_accent_attachment (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment. + g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 374); + g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 346); + g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 318); + closeFont(); + + cleanupFreeType(); +} + +static void +test_is_glyph_extended_shape (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph)); + g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); + g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph)); + g_assert(hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_glyph_kerning (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); + + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height + + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left + + closeFont(); + + cleanupFreeType(); +} + + +#if 0 +static void +test_get_math_italic_correction_for_glyph_assembly (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty + closeFont(); + + openFont("fonts/MathTestFontPartial4.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331); + closeFont(); + + cleanupFreeType(); +} +#endif + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_has_data); + hb_test_add (test_get_constant); + hb_test_add (test_get_glyph_italics_correction); + hb_test_add (test_get_glyph_top_accent_attachment); + hb_test_add (test_is_glyph_extended_shape); + hb_test_add (test_get_glyph_kerning); + //hb_test_add (test_get_math_italic_correction_for_glyph_assembly); + + return hb_test_run(); +} From cdc9eef7da934ae71578694f29665e439686c3bd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 22:18:41 +0200 Subject: [PATCH 23/32] [MATH] Enable tests for glyph-assembly italics-correction --- test/api/test-ot-math.c | 49 +++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 23c19eff3..4a7968129 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -314,55 +314,66 @@ test_get_glyph_kerning (void) } -#if 0 -static void -test_get_math_italic_correction_for_glyph_assembly (void) +static hb_position_t +get_glyph_assembly_italics_correction (hb_font_t *font, + hb_codepoint_t glyph, + hb_bool_t horizontal) +{ + hb_position_t corr; + unsigned int count = 0; + hb_ot_math_get_glyph_assembly (font, glyph, + horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB, + 0, &count, NULL, + &corr); + return corr; +} + +test_get_glyph_assembly_italics_correction (void) { hb_codepoint_t glyph; initFreeType(); openFont("fonts/MathTestFontEmpty.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // MathVariants not available + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // MathVariants not available closeFont(); openFont("fonts/MathTestFontPartial1.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent closeFont(); openFont("fonts/MathTestFontPartial2.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty closeFont(); openFont("fonts/MathTestFontPartial3.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty closeFont(); openFont("fonts/MathTestFontPartial4.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); closeFont(); openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 124); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 331); closeFont(); cleanupFreeType(); } -#endif int main (int argc, char **argv) @@ -375,7 +386,7 @@ main (int argc, char **argv) hb_test_add (test_get_glyph_top_accent_attachment); hb_test_add (test_is_glyph_extended_shape); hb_test_add (test_get_glyph_kerning); - //hb_test_add (test_get_math_italic_correction_for_glyph_assembly); + hb_test_add (test_get_glyph_assembly_italics_correction); return hb_test_run(); } From bc19f7fe20e89823dba07a46c3d48c7406b781b6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 10:58:08 +0200 Subject: [PATCH 24/32] [MATH] Add HB_OT_MATH_SCRIPT --- src/hb-ot-math.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index ad8bf14e5..814e40424 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -42,6 +42,9 @@ HB_BEGIN_DECLS #define HB_OT_TAG_MATH HB_TAG('M','A','T','H') +/* Use with hb_buffer_set_script() for math shaping. */ +#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h') + /* Types */ typedef enum { From edcfa789bf92c18f5badad31c0ad04a6a77d7226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 27 Sep 2016 11:02:08 +0200 Subject: [PATCH 25/32] test-ot-math: Use different scales for vertical and horizontal directions and add test for hb_ot_math_get_min_connector_overlap. (#327) --- test/api/test-ot-math.c | 79 +++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 4a7968129..4bffcc049 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -63,8 +63,7 @@ openFont(const char* fontFile) } g_free(path); -#define fontSize 1000 - if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) + if ((ft_error = FT_Set_Char_Size (ft_face, 2000, 1000, 0, 0))) abort(); hb_font = hb_ft_font_create (ft_face, NULL); hb_face = hb_ft_face_create_cached(ft_face); @@ -118,7 +117,7 @@ test_get_constant (void) g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600); - g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 3400); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200); @@ -142,7 +141,7 @@ test_get_constant (void) g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200); - g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 8600); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600); @@ -154,8 +153,8 @@ test_get_constant (void) g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400); - g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500); - g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 11000); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 11200); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65); @@ -189,11 +188,11 @@ test_get_glyph_italics_correction (void) g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 197); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 394); g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 150); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 300); g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 452); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 904); closeFont(); cleanupFreeType(); @@ -207,28 +206,28 @@ test_get_glyph_top_accent_attachment (void) openFont("fonts/MathTestFontEmpty.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo not available closeFont(); openFont("fonts/MathTestFontPartial1.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo empty closeFont(); openFont("fonts/MathTestFontPartial2.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathTopAccentAttachment empty closeFont(); openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment. + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // Glyph without top accent attachment. g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 374); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 748); g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 346); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 692); g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 318); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 636); closeFont(); cleanupFreeType(); @@ -293,20 +292,20 @@ test_get_glyph_kerning (void) openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 62); // lower than min heigth + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 62); // equal to min height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 104); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 104); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 146); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 146); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 398); // equal to max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 440); // larger than max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 440); // larger than max height - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 188); // top right + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 110); // top left + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 44); // bottom right + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 100); // bottom left closeFont(); @@ -365,11 +364,28 @@ test_get_glyph_assembly_italics_correction (void) openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); - g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 124); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 248); g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 331); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 662); + closeFont(); + + cleanupFreeType(); +} + +test_get_min_connector_overlap (void) +{ + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, FALSE), ==, 0); // MathVariants not available + g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, TRUE), ==, 0); // MathVariants not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 108); + g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 54); closeFont(); cleanupFreeType(); @@ -387,6 +403,7 @@ main (int argc, char **argv) hb_test_add (test_is_glyph_extended_shape); hb_test_add (test_get_glyph_kerning); hb_test_add (test_get_glyph_assembly_italics_correction); + hb_test_add (test_get_min_connector_overlap); return hb_test_run(); } From a5629a2ed9c2e69f2b4ebb74d85fbe0b5ba2be67 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 11:30:44 +0200 Subject: [PATCH 26/32] [MATH] Simplify test --- test/api/test-ot-math.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 4bffcc049..668cc97ec 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -319,10 +319,9 @@ get_glyph_assembly_italics_correction (hb_font_t *font, hb_bool_t horizontal) { hb_position_t corr; - unsigned int count = 0; hb_ot_math_get_glyph_assembly (font, glyph, horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB, - 0, &count, NULL, + 0, NULL, NULL, &corr); return corr; } From 485e4873fb7cacfa9d853272c2275bbc5826023e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 27 Sep 2016 13:18:00 +0200 Subject: [PATCH 27/32] Add tests for hb_ot_math_get_glyph_variants (#328) --- test/api/test-ot-math.c | 126 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 668cc97ec..99993e063 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -326,6 +326,7 @@ get_glyph_assembly_italics_correction (hb_font_t *font, return corr; } +static void test_get_glyph_assembly_italics_correction (void) { hb_codepoint_t glyph; @@ -373,6 +374,7 @@ test_get_glyph_assembly_italics_correction (void) cleanupFreeType(); } +static void test_get_min_connector_overlap (void) { initFreeType(); @@ -390,6 +392,129 @@ test_get_min_connector_overlap (void) cleanupFreeType(); } +static void +test_get_glyph_variants (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial4.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_BTT, + 0, + NULL, + NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_RTL, + 0, + NULL, + NULL), ==, 3); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_BTT, + 0, + NULL, + NULL), ==, 4); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_RTL, + 0, + NULL, + NULL), ==, 0); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); + hb_math_glyph_variant_t variants[20]; + unsigned variantsSize = sizeof (variants) / sizeof (variants[0]); + unsigned int count; + unsigned int offset = 0; + do { + count = variantsSize; + hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_RTL, + offset, + &count, + variants); + offset += count; + } while (count == variantsSize); + g_assert_cmpint(offset, ==, 3); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size2", -1, &glyph)); + g_assert_cmpint(variants[0].glyph, ==, glyph); + g_assert_cmpint(variants[0].advance, ==, 4302); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size3", -1, &glyph)); + g_assert_cmpint(variants[1].glyph, ==, glyph); + g_assert_cmpint(variants[1].advance, ==, 4802); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size4", -1, &glyph)); + g_assert_cmpint(variants[2].glyph, ==, glyph); + g_assert_cmpint(variants[2].advance, ==, 5802); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); + offset = 0; + do { + count = variantsSize; + hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_BTT, + offset, + &count, + variants); + offset += count; + } while (count == variantsSize); + g_assert_cmpint(offset, ==, 4); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size2", -1, &glyph)); + g_assert_cmpint(variants[0].glyph, ==, glyph); + g_assert_cmpint(variants[0].advance, ==, 2251); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size3", -1, &glyph)); + g_assert_cmpint(variants[1].glyph, ==, glyph); + g_assert_cmpint(variants[1].advance, ==, 2501); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size4", -1, &glyph)); + g_assert_cmpint(variants[2].glyph, ==, glyph); + g_assert_cmpint(variants[2].advance, ==, 3001); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size5", -1, &glyph)); + g_assert_cmpint(variants[3].glyph, ==, glyph); + g_assert_cmpint(variants[3].advance, ==, 3751); + + closeFont(); + + cleanupFreeType(); +} + int main (int argc, char **argv) { @@ -403,6 +528,7 @@ main (int argc, char **argv) hb_test_add (test_get_glyph_kerning); hb_test_add (test_get_glyph_assembly_italics_correction); hb_test_add (test_get_min_connector_overlap); + hb_test_add (test_get_glyph_variants); return hb_test_run(); } From 8d622f1114d6a0eca1786b94c7fc1a0bcd87f74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 27 Sep 2016 13:53:34 +0200 Subject: [PATCH 28/32] Add tests for get_mathvariant (#329) --- test/api/test-ot-math.c | 160 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 99993e063..4d6f67bcd 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -515,6 +515,165 @@ test_get_glyph_variants (void) cleanupFreeType(); } +static void +test_get_glyph_assembly (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial4.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_BTT, + 0, + NULL, + NULL, + NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_RTL, + 0, + NULL, + NULL, + NULL), ==, 3); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_BTT, + 0, + NULL, + NULL, + NULL), ==, 5); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_RTL, + 0, + NULL, + NULL, + NULL), ==, 0); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph)); + hb_math_glyph_part_t parts[20]; + unsigned partsSize = sizeof (parts) / sizeof (parts[0]); + unsigned int count; + unsigned int offset = 0; + do { + count = partsSize; + hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_RTL, + offset, + &count, + parts, + NULL); + offset += count; + } while (count == partsSize); + g_assert_cmpint(offset, ==, 3); + g_assert(hb_font_get_glyph_from_name (hb_font, "left", -1, &glyph)); + g_assert_cmpint(parts[0].glyph, ==, glyph); + g_assert_cmpint(parts[0].start_connector_length, ==, 800); + g_assert_cmpint(parts[0].end_connector_length, ==, 384); + g_assert_cmpint(parts[0].full_advance, ==, 2000); + g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(hb_font_get_glyph_from_name (hb_font, "horizontal", -1, &glyph)); + g_assert_cmpint(parts[1].glyph, ==, glyph); + g_assert_cmpint(parts[1].start_connector_length, ==, 524); + g_assert_cmpint(parts[1].end_connector_length, ==, 800); + g_assert_cmpint(parts[1].full_advance, ==, 2000); + g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); + g_assert(hb_font_get_glyph_from_name (hb_font, "right", -1, &glyph)); + g_assert_cmpint(parts[2].glyph, ==, glyph); + g_assert_cmpint(parts[2].start_connector_length, ==, 316); + g_assert_cmpint(parts[2].end_connector_length, ==, 454); + g_assert_cmpint(parts[2].full_advance, ==, 2000); + g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph)); + offset = 0; + do { + count = partsSize; + hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_BTT, + offset, + &count, + parts, + NULL); + offset += count; + } while (count == partsSize); + g_assert_cmpint(offset, ==, 5); + g_assert(hb_font_get_glyph_from_name (hb_font, "bottom", -1, &glyph)); + g_assert_cmpint(parts[0].glyph, ==, glyph); + g_assert_cmpint(parts[0].start_connector_length, ==, 365); + g_assert_cmpint(parts[0].end_connector_length, ==, 158); + g_assert_cmpint(parts[0].full_advance, ==, 1000); + g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph)); + g_assert_cmpint(parts[1].glyph, ==, glyph); + g_assert_cmpint(parts[1].glyph, ==, glyph); + g_assert_cmpint(parts[1].start_connector_length, ==, 227); + g_assert_cmpint(parts[1].end_connector_length, ==, 365); + g_assert_cmpint(parts[1].full_advance, ==, 1000); + g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); + g_assert(hb_font_get_glyph_from_name (hb_font, "center", -1, &glyph)); + g_assert_cmpint(parts[2].glyph, ==, glyph); + g_assert_cmpint(parts[2].start_connector_length, ==, 54); + g_assert_cmpint(parts[2].end_connector_length, ==, 158); + g_assert_cmpint(parts[2].full_advance, ==, 1000); + g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph)); + g_assert_cmpint(parts[3].glyph, ==, glyph); + g_assert_cmpint(parts[3].glyph, ==, glyph); + g_assert_cmpint(parts[3].glyph, ==, glyph); + g_assert_cmpint(parts[3].start_connector_length, ==, 400); + g_assert_cmpint(parts[3].end_connector_length, ==, 296); + g_assert_cmpint(parts[3].full_advance, ==, 1000); + g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); + g_assert(hb_font_get_glyph_from_name (hb_font, "top", -1, &glyph)); + g_assert_cmpint(parts[4].glyph, ==, glyph); + g_assert_cmpint(parts[4].start_connector_length, ==, 123); + g_assert_cmpint(parts[4].end_connector_length, ==, 192); + g_assert_cmpint(parts[4].full_advance, ==, 1000); + g_assert(!(parts[4].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + + closeFont(); + + cleanupFreeType(); +} + int main (int argc, char **argv) { @@ -529,6 +688,7 @@ main (int argc, char **argv) hb_test_add (test_get_glyph_assembly_italics_correction); hb_test_add (test_get_min_connector_overlap); hb_test_add (test_get_glyph_variants); + hb_test_add (test_get_glyph_assembly); return hb_test_run(); } From 0762b35474c47171e5661904e93851eb73a44e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 27 Sep 2016 15:28:35 +0200 Subject: [PATCH 29/32] Document API for MathVariants (#330) --- src/hb-ot-layout.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 588f5ab00..210af505d 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1352,6 +1352,26 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, 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_math_glyph_variant_t structs. + * + * Return value: the total number of size variants available or 0 + * + * Since: 1.4 + **/ unsigned int hb_ot_math_get_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, @@ -1367,6 +1387,21 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, 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.4 + **/ hb_position_t hb_ot_math_get_min_connector_overlap (hb_font_t *font, hb_direction_t direction) @@ -1375,6 +1410,27 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font, 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_math_glyph_part_t. + * + * Return value: the total number of parts in the glyph assembly + * + * Since: 1.4 + **/ unsigned int hb_ot_math_get_glyph_assembly (hb_font_t *font, hb_codepoint_t glyph, From db5ebcf10f8595d1f4a9df27befd6cb5e76ca94d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 16:42:25 +0200 Subject: [PATCH 30/32] Update docs --- docs/harfbuzz-docs.xml | 9 +++++++++ docs/harfbuzz-sections.txt | 30 ++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml index 2c43c4687..ea99732ca 100644 --- a/docs/harfbuzz-docs.xml +++ b/docs/harfbuzz-docs.xml @@ -80,6 +80,7 @@ + @@ -175,6 +176,14 @@ Index of new symbols in 1.1.3 + + Index of new symbols in 1.2.3 + + + + Index of new symbols in 1.4.0 + + Index of deprecated API diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index e0dc23d9c..d94cf703e 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -144,6 +144,8 @@ uint8_t HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_SCRIPT_CANADIAN_ABORIGINAL +hb_font_funcs_set_glyph_func +hb_font_get_glyph_func_t

    @@ -193,7 +195,6 @@ hb_font_funcs_reference hb_font_funcs_set_glyph_contour_point_func hb_font_funcs_set_glyph_extents_func hb_font_funcs_set_glyph_from_name_func -hb_font_funcs_set_glyph_func hb_font_funcs_set_glyph_h_advance_func hb_font_funcs_set_glyph_h_kerning_func hb_font_funcs_set_glyph_h_origin_func @@ -201,7 +202,9 @@ hb_font_funcs_set_glyph_name_func hb_font_funcs_set_glyph_v_advance_func hb_font_funcs_set_glyph_v_kerning_func hb_font_funcs_set_glyph_v_origin_func +hb_font_funcs_set_nominal_glyph_func hb_font_funcs_set_user_data +hb_font_funcs_set_variation_glyph_func hb_font_funcs_t hb_font_get_empty hb_font_get_face @@ -216,7 +219,6 @@ hb_font_get_glyph_extents_for_origin hb_font_get_glyph_extents_func_t hb_font_get_glyph_from_name hb_font_get_glyph_from_name_func_t -hb_font_get_glyph_func_t hb_font_get_glyph_h_advance hb_font_get_glyph_h_advance_func_t hb_font_get_glyph_h_kerning @@ -235,10 +237,14 @@ hb_font_get_glyph_v_kerning hb_font_get_glyph_v_kerning_func_t hb_font_get_glyph_v_origin hb_font_get_glyph_v_origin_func_t +hb_font_get_nominal_glyph +hb_font_get_nominal_glyph_func_t hb_font_get_parent hb_font_get_ppem hb_font_get_scale hb_font_get_user_data +hb_font_get_variation_glyph +hb_font_get_variation_glyph_func_t hb_font_glyph_from_string hb_font_glyph_to_string hb_font_is_immutable @@ -416,6 +422,26 @@ Xhb_ot_layout_lookup_position Xhb_ot_layout_lookup_substitute
    +
    +hb-ot-math +HB_OT_TAG_MATH +HB_OT_MATH_SCRIPT +hb_math_glyph_part_flags_t +hb_math_glyph_part_t +hb_math_glyph_variant_t +hb_ot_math_constant_t +hb_ot_math_get_constant +hb_ot_math_get_glyph_assembly +hb_ot_math_get_glyph_italics_correction +hb_ot_math_get_glyph_kerning +hb_ot_math_get_glyph_top_accent_attachment +hb_ot_math_get_glyph_variants +hb_ot_math_get_min_connector_overlap +hb_ot_math_has_data +hb_ot_math_is_glyph_extended_shape +hb_ot_math_kern_t +
    +
    hb-ot-tag HB_OT_TAG_DEFAULT_LANGUAGE From 46cc4a3a2a529c80677babe38ca1542f9c773ac0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 16:44:22 +0200 Subject: [PATCH 31/32] [MATH] Rename hb_math_*_t types to hb_ot_math_*_t With this, I believe MATH table API is not ready to be merged. --- docs/harfbuzz-sections.txt | 6 +++--- src/hb-ot-layout-math-table.hh | 12 ++++++------ src/hb-ot-layout.cc | 8 ++++---- src/hb-ot-math.h | 16 ++++++++-------- test/api/test-ot-math.c | 4 ++-- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index d94cf703e..75d749293 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -426,10 +426,10 @@ Xhb_ot_layout_lookup_substitute hb-ot-math HB_OT_TAG_MATH HB_OT_MATH_SCRIPT -hb_math_glyph_part_flags_t -hb_math_glyph_part_t -hb_math_glyph_variant_t hb_ot_math_constant_t +hb_ot_math_glyph_part_flags_t +hb_ot_math_glyph_part_t +hb_ot_math_glyph_variant_t hb_ot_math_get_constant hb_ot_math_get_glyph_assembly hb_ot_math_get_glyph_italics_correction diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index efffd2b53..b52b1215d 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -453,7 +453,7 @@ struct MathGlyphPartRecord return_trace (c->check_struct (this)); } - inline void extract (hb_math_glyph_part_t &out, + inline void extract (hb_ot_math_glyph_part_t &out, int scale, hb_font_t *font) const { @@ -466,7 +466,7 @@ struct MathGlyphPartRecord ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER == (unsigned int) PartFlags::Extender); - out.flags = (hb_math_glyph_part_flags_t) + out.flags = (hb_ot_math_glyph_part_flags_t) (unsigned int) (partFlags & PartFlags::Defined); } @@ -504,7 +504,7 @@ struct MathGlyphAssembly hb_font_t *font, unsigned int start_offset, unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts /* OUT */, + hb_ot_math_glyph_part_t *parts /* OUT */, hb_position_t *italics_correction /* OUT */) const { if (parts_count) @@ -552,7 +552,7 @@ struct MathGlyphConstruction hb_font_t *font, unsigned int start_offset, unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */) const + hb_ot_math_glyph_variant_t *variants /* OUT */) const { if (variants_count) { @@ -613,7 +613,7 @@ struct MathVariants hb_font_t *font, unsigned int start_offset, unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */) const + hb_ot_math_glyph_variant_t *variants /* OUT */) const { return get_glyph_construction (glyph, direction, font) .get_variants (direction, font, start_offset, variants_count, variants); } @@ -622,7 +622,7 @@ struct MathVariants hb_font_t *font, unsigned int start_offset, unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts /* OUT */, + hb_ot_math_glyph_part_t *parts /* OUT */, hb_position_t *italics_correction /* OUT */) const { return get_glyph_construction (glyph, direction, font) .get_assembly () diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 210af505d..49c75b0be 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1366,7 +1366,7 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, * 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_math_glyph_variant_t structs. + * 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 * @@ -1378,7 +1378,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, hb_direction_t direction, unsigned int start_offset, unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* 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, @@ -1425,7 +1425,7 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font, * 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_math_glyph_part_t. + * assembly as an array of #hb_ot_math_glyph_part_t. * * Return value: the total number of parts in the glyph assembly * @@ -1437,7 +1437,7 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font, hb_direction_t direction, unsigned int start_offset, unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ + hb_ot_math_glyph_part_t *parts, /* OUT */ hb_position_t *italics_correction /* OUT */) { const OT::MATH &math = _get_math (font->face); diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 814e40424..e186fa989 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -113,22 +113,22 @@ typedef enum { HB_OT_MATH_KERN_BOTTOM_LEFT = 3 } hb_ot_math_kern_t; -typedef struct hb_math_glyph_variant_t { +typedef struct hb_ot_math_glyph_variant_t { hb_codepoint_t glyph; hb_position_t advance; -} hb_math_glyph_variant_t; +} hb_ot_math_glyph_variant_t; typedef enum { /*< flags >*/ HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ -} hb_math_glyph_part_flags_t; +} hb_ot_math_glyph_part_flags_t; -typedef struct hb_math_glyph_part_t { +typedef struct hb_ot_math_glyph_part_t { hb_codepoint_t glyph; hb_position_t start_connector_length; hb_position_t end_connector_length; hb_position_t full_advance; - hb_math_glyph_part_flags_t flags; -} hb_math_glyph_part_t; + hb_ot_math_glyph_part_flags_t flags; +} hb_ot_math_glyph_part_t; /* Methods */ @@ -163,7 +163,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, hb_direction_t direction, unsigned int start_offset, unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */); + hb_ot_math_glyph_variant_t *variants /* OUT */); HB_EXTERN hb_position_t hb_ot_math_get_min_connector_overlap (hb_font_t *font, @@ -175,7 +175,7 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font, hb_direction_t direction, unsigned int start_offset, unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ + hb_ot_math_glyph_part_t *parts, /* OUT */ hb_position_t *italics_correction /* OUT */); diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 4d6f67bcd..5f4ccb7fc 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -459,7 +459,7 @@ test_get_glyph_variants (void) NULL), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); - hb_math_glyph_variant_t variants[20]; + hb_ot_math_glyph_variant_t variants[20]; unsigned variantsSize = sizeof (variants) / sizeof (variants[0]); unsigned int count; unsigned int offset = 0; @@ -586,7 +586,7 @@ test_get_glyph_assembly (void) NULL), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph)); - hb_math_glyph_part_t parts[20]; + hb_ot_math_glyph_part_t parts[20]; unsigned partsSize = sizeof (parts) / sizeof (parts[0]); unsigned int count; unsigned int offset = 0; From c3e21a6620c35500afa350d11620f69802920df3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 16:51:38 +0200 Subject: [PATCH 32/32] [MATH] Fix more docs --- src/hb-ot-layout.cc | 18 +++++++++--------- src/hb-ot-math.h | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 49c75b0be..6c8a9c498 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1238,7 +1238,7 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, * * Return value: #TRUE if face has a MATH table and #FALSE otherwise * - * Since: 1.4 + * Since: 1.4.0 **/ hb_bool_t hb_ot_math_has_data (hb_face_t *face) @@ -1260,7 +1260,7 @@ hb_ot_math_has_data (hb_face_t *face) * * Return value: the requested constant or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_constant (hb_font_t *font, @@ -1278,7 +1278,7 @@ hb_ot_math_get_constant (hb_font_t *font, * * Return value: the italics correction of the glyph or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_glyph_italics_correction (hb_font_t *font, @@ -1296,7 +1296,7 @@ hb_ot_math_get_glyph_italics_correction (hb_font_t *font, * * Return value: the top accent attachment of the glyph or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, @@ -1314,7 +1314,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, * * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise * - * Since: 1.4 + * Since: 1.4.0 **/ hb_bool_t hb_ot_math_is_glyph_extended_shape (hb_face_t *face, @@ -1340,7 +1340,7 @@ hb_ot_math_is_glyph_extended_shape (hb_face_t *face, * * Return value: requested kerning or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_glyph_kerning (hb_font_t *font, @@ -1370,7 +1370,7 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, * * Return value: the total number of size variants available or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ unsigned int hb_ot_math_get_glyph_variants (hb_font_t *font, @@ -1400,7 +1400,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, * * Return value: requested min connector overlap or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_min_connector_overlap (hb_font_t *font, @@ -1429,7 +1429,7 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font, * * Return value: the total number of parts in the glyph assembly * - * Since: 1.4 + * Since: 1.4.0 **/ unsigned int hb_ot_math_get_glyph_assembly (hb_font_t *font, diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index e186fa989..0fc251b55 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -47,6 +47,11 @@ HB_BEGIN_DECLS /* Types */ +/** + * hb_ot_math_constant_t: + * + * Since: 1.4.0 + */ typedef enum { HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1, @@ -106,6 +111,11 @@ typedef enum { HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55 } hb_ot_math_constant_t; +/** + * hb_ot_math_kern_t: + * + * Since: 1.4.0 + */ typedef enum { HB_OT_MATH_KERN_TOP_RIGHT = 0, HB_OT_MATH_KERN_TOP_LEFT = 1, @@ -113,15 +123,30 @@ typedef enum { HB_OT_MATH_KERN_BOTTOM_LEFT = 3 } hb_ot_math_kern_t; +/** + * hb_ot_math_glyph_variant_t: + * + * Since: 1.4.0 + */ typedef struct hb_ot_math_glyph_variant_t { hb_codepoint_t glyph; hb_position_t advance; } hb_ot_math_glyph_variant_t; +/** + * hb_ot_math_glyph_part_flags_t: + * + * Since: 1.4.0 + */ typedef enum { /*< flags >*/ HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ } hb_ot_math_glyph_part_flags_t; +/** + * hb_ot_math_glyph_part_t: + * + * Since: 1.4.0 + */ typedef struct hb_ot_math_glyph_part_t { hb_codepoint_t glyph; hb_position_t start_connector_length;