diff --git a/CMakeLists.txt b/CMakeLists.txt index c41579c1c..ac857ef8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ if (APPLE) endif () if (WIN32) option(HB_HAVE_UNISCRIBE "Enable Uniscribe shaper backend on Windows" OFF) + option(HB_HAVE_GDI "Enable GDI integration helpers on Windows" OFF) option(HB_HAVE_DIRECTWRITE "Enable DirectWrite shaper backend on Windows" OFF) endif () option(HB_BUILD_UTILS "Build harfbuzz utils, needs cairo, freetype, and glib properly be installed" OFF) @@ -77,6 +78,7 @@ if (HB_CHECK) set (HB_HAVE_GRAPHITE2 ON) if (WIN32) set (HB_HAVE_UNISCRIBE ON) + set (HB_HAVE_GDI ON) set (HB_HAVE_DIRECTWRITE ON) elseif (APPLE) set (HB_HAVE_CORETEXT ON) @@ -305,6 +307,12 @@ if (APPLE AND HB_HAVE_CORETEXT) endif () endif () +if (WIN32 AND HB_HAVE_GDI) + add_definitions(-DHAVE_GDI) + list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-gdi.h) + list(APPEND THIRD_PARTY_LIBS gdi32) +endif () + if (WIN32 AND HB_HAVE_UNISCRIBE) add_definitions(-DHAVE_UNISCRIBE) list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h) diff --git a/appveyor.yml b/appveyor.yml index 236bb1b12..6daf8d225 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -73,7 +73,7 @@ build_script: - 'if "%compiler%"=="msvc2" cmake --build build --config %configuration%' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"' - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"' + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --with-gdi --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"' cache: - c:\tools\vcpkg\installed\ diff --git a/configure.ac b/configure.ac index 09ce4e6ec..cebb10adf 100644 --- a/configure.ac +++ b/configure.ac @@ -361,6 +361,28 @@ AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe) dnl =========================================================================== +AC_ARG_WITH(gdi, + [AS_HELP_STRING([--with-gdi=@<:@yes/no/auto@:>@], + [Provide GDI integration helpers @<:@default=no@:>@])],, + [with_gdi=no]) +have_gdi=false +if test "x$with_gdi" = "xyes" -o "x$with_gdi" = "xauto"; then + AC_CHECK_HEADERS(windows.h, have_gdi=true) +fi +if test "x$with_gdi" = "xyes" -a "x$have_gdi" != "xtrue"; then + AC_MSG_ERROR([gdi support requested but not found]) +fi +if $have_gdi; then + GDI_CFLAGS= + GDI_LIBS="-lgdi32" + AC_SUBST(GDI_CFLAGS) + AC_SUBST(GDI_LIBS) + AC_DEFINE(HAVE_GDI, 1, [Have GDI library]) +fi +AM_CONDITIONAL(HAVE_GDI, $have_gdi) + +dnl =========================================================================== + AC_ARG_WITH(directwrite, [AS_HELP_STRING([--with-directwrite=@<:@yes/no/auto@:>@], [Use the DirectWrite library (experimental) @<:@default=no@:>@])],, @@ -510,6 +532,7 @@ Additional shapers (the more the merrier): Platform shapers (not normally needed): CoreText: ${have_coretext} DirectWrite: ${have_directwrite} + GDI: ${have_gdi} Uniscribe: ${have_uniscribe} Other features: diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 4be248d30..43fd76115 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -1,6 +1,7 @@ HB_H_IN HB_OT_H_IN +HB_AAT_H_IN
@@ -179,6 +180,7 @@ HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_SCRIPT_CANADIAN_ABORIGINAL hb_font_funcs_set_glyph_func hb_font_get_glyph_func_t +HB_MATH_GLYPH_PART_FLAG_EXTENDER hb_ot_layout_table_choose_script hb_ot_layout_table_find_script hb_ot_tag_from_language @@ -367,6 +369,11 @@ hb_ft_font_get_load_flags hb_ft_font_set_funcs
+
+hb-gdi +hb_gdi_face_create +
+
hb-glib hb_glib_get_unicode_funcs @@ -600,6 +607,15 @@ hb_ot_math_get_min_connector_overlap hb_ot_math_get_glyph_assembly
+
+hb-ot-metrics +hb_ot_metrics_t +hb_ot_metrics_get_position +hb_ot_metrics_get_variation +hb_ot_metrics_get_x_variation +hb_ot_metrics_get_y_variation +
+
hb-ot-shape hb_ot_shape_glyphs_closure diff --git a/src/Makefile.am b/src/Makefile.am index 1e79483c9..54e4a02cf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,6 +82,13 @@ HBSOURCES += $(HB_DIRECTWRITE_sources) HBHEADERS += $(HB_DIRECTWRITE_headers) endif +if HAVE_GDI +HBCFLAGS += $(GDI_CXXFLAGS) +HBNONPCLIBS += $(GDI_LIBS) +HBSOURCES += $(HB_GDI_sources) +HBHEADERS += $(HB_GDI_headers) +endif + if HAVE_CORETEXT HBCFLAGS += $(CORETEXT_CFLAGS) HBNONPCLIBS += $(CORETEXT_LIBS) @@ -313,6 +320,7 @@ harfbuzz.cc: Makefile.sources $(HB_FT_sources) \ $(HB_GRAPHITE2_sources) \ $(HB_UNISCRIBE_sources) \ + $(HB_GDI_sources) \ $(HB_DIRECTWRITE_sources) \ $(HB_CORETEXT_sources) \ ; do echo '#include "'$$f'"'; done | \ diff --git a/src/Makefile.sources b/src/Makefile.sources index b48b2f2d5..985301af2 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -89,6 +89,9 @@ HB_BASE_sources = \ hb-ot-math-table.hh \ hb-ot-math.cc \ hb-ot-maxp-table.hh \ + hb-ot-meta-table.hh \ + hb-ot-metrics.cc \ + hb-ot-metrics.hh \ hb-ot-name-language-static.hh \ hb-ot-name-language.hh \ hb-ot-name-table.hh \ @@ -193,6 +196,7 @@ HB_BASE_headers = \ hb-ot-font.h \ hb-ot-layout.h \ hb-ot-math.h \ + hb-ot-metrics.h \ hb-ot-name.h \ hb-ot-shape.h \ hb-ot-var.h \ @@ -224,6 +228,9 @@ HB_CORETEXT_headers = hb-coretext.h HB_DIRECTWRITE_sources = hb-directwrite.cc HB_DIRECTWRITE_headers = hb-directwrite.h +HB_GDI_sources = hb-gdi.cc +HB_GDI_headers = hb-gdi.h + HB_UNISCRIBE_sources = hb-uniscribe.cc HB_UNISCRIBE_headers = hb-uniscribe.h diff --git a/src/harfbuzz.cc b/src/harfbuzz.cc index 5e6527f13..0701b7024 100644 --- a/src/harfbuzz.cc +++ b/src/harfbuzz.cc @@ -17,6 +17,7 @@ #include "hb-ot-layout.cc" #include "hb-ot-map.cc" #include "hb-ot-math.cc" +#include "hb-ot-metrics.cc" #include "hb-ot-name.cc" #include "hb-ot-shape-complex-arabic.cc" #include "hb-ot-shape-complex-default.cc" @@ -47,5 +48,6 @@ #include "hb-ft.cc" #include "hb-graphite2.cc" #include "hb-uniscribe.cc" +#include "hb-gdi.cc" #include "hb-directwrite.cc" #include "hb-coretext.cc" diff --git a/src/hb-config.hh b/src/hb-config.hh index adf2b3348..bd440050e 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -66,6 +66,7 @@ #define HB_NO_LAYOUT_COLLECT_GLYPHS #define HB_NO_LAYOUT_UNUSED #define HB_NO_MATH +#define HB_NO_METRICS #define HB_NO_MMAP #define HB_NO_NAME #define HB_NO_OPEN diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 810c5e553..c14e9d2be 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -539,11 +539,6 @@ protected: Run mRunHead; }; -static inline uint16_t hb_dw_uint16_swap (const uint16_t v) -{ return (v >> 8) | (v << 8); } -static inline uint32_t hb_dw_uint32_swap (const uint32_t v) -{ return (hb_dw_uint16_swap (v) << 16) | hb_dw_uint16_swap (v >> 16); } - /* * shaper */ @@ -653,7 +648,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan, for (unsigned int i = 0; i < num_features; ++i) { typographic_features.features[i].nameTag = (DWRITE_FONT_FEATURE_TAG) - hb_dw_uint32_swap (features[i].tag); + hb_uint32_swap (features[i].tag); typographic_features.features[i].parameter = features[i].value; } } @@ -941,7 +936,7 @@ _hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void * uint32_t length; void *table_context; BOOL exists; - if (!dw_face || FAILED (dw_face->TryGetFontTable (hb_dw_uint32_swap (tag), &data, + if (!dw_face || FAILED (dw_face->TryGetFontTable (hb_uint32_swap (tag), &data, &length, &table_context, &exists))) return nullptr; diff --git a/src/hb-gdi.cc b/src/hb-gdi.cc new file mode 100644 index 000000000..526f1cd9e --- /dev/null +++ b/src/hb-gdi.cc @@ -0,0 +1,73 @@ +/* + * Copyright © 2019 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb.hh" + +#ifdef HAVE_GDI + +#include "hb-gdi.h" + +static hb_blob_t * +_hb_gdi_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) +{ + char *buffer = nullptr; + DWORD length = 0; + + HDC hdc = GetDC (nullptr); + if (unlikely (!SelectObject (hdc, (HFONT) user_data))) goto fail; + + length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length); + if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc; + + buffer = (char *) malloc (length); + if (unlikely (!buffer)) goto fail_with_releasedc; + length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length); + if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc_and_free; + ReleaseDC (nullptr, hdc); + + return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, free); + +fail_with_releasedc_and_free: + free (buffer); +fail_with_releasedc: + ReleaseDC (nullptr, hdc); +fail: + return hb_blob_get_empty (); +} + +/** + * hb_gdi_face_create: + * @hdc: a HFONT object. + * + * Return value: #hb_face_t object corresponding to the given input + * + * Since: REPLACEME + **/ +hb_face_t * +hb_gdi_face_create (HFONT hfont) +{ + return hb_face_create_for_tables (_hb_gdi_reference_table, (void *) hfont, nullptr); +} + +#endif diff --git a/src/hb-gdi.h b/src/hb-gdi.h new file mode 100644 index 000000000..68cc43917 --- /dev/null +++ b/src/hb-gdi.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2019 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_GDI_H +#define HB_GDI_H + +#include "hb.h" + +#include + +HB_BEGIN_DECLS + +HB_EXTERN hb_face_t * +hb_gdi_face_create (HFONT hfont); + +HB_END_DECLS + +#endif /* HB_GDI_H */ diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index 9b725c46e..8a915a661 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -235,9 +235,9 @@ struct sbix const PNGHeader &png = *blob->as(); extents->x_bearing = x_offset; - extents->y_bearing = y_offset; + extents->y_bearing = png.IHDR.height + y_offset; extents->width = png.IHDR.width; - extents->height = png.IHDR.height; + extents->height = -png.IHDR.height; /* Convert to font units. */ if (strike_ppem) diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index ac7052751..4ec622c57 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -50,9 +50,10 @@ HB_OT_TABLE (OT, head) #if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT) HB_OT_ACCELERATOR (OT, cmap) #endif +HB_OT_TABLE (OT, hhea) HB_OT_ACCELERATOR (OT, hmtx) HB_OT_TABLE (OT, OS2) -#ifndef HB_NO_OT_FONT_GLYPH_NAMES +#if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS) HB_OT_ACCELERATOR (OT, post) #endif #ifndef HB_NO_NAME @@ -61,8 +62,10 @@ HB_OT_ACCELERATOR (OT, name) #ifndef HB_NO_STAT HB_OT_TABLE (OT, STAT) #endif +//HB_OT_TABLE (OT, meta) /* Vertical layout. */ +HB_OT_TABLE (OT, vhea) HB_OT_ACCELERATOR (OT, vmtx) /* TrueType outlines. */ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 4b447d000..2470f233b 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -231,32 +231,24 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, static hb_bool_t hb_ot_get_font_h_extents (hb_font_t *font, - void *font_data, + void *font_data HB_UNUSED, hb_font_extents_t *metrics, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; - const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; - metrics->ascender = font->em_scale_y (hmtx.ascender); - metrics->descender = font->em_scale_y (hmtx.descender); - metrics->line_gap = font->em_scale_y (hmtx.line_gap); - // TODO Hook up variations. - return hmtx.has_font_extents; + return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_HORIZONTAL_ASCENDER, &metrics->ascender) && + _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_HORIZONTAL_DESCENDER, &metrics->descender) && + _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_HORIZONTAL_LINE_GAP, &metrics->line_gap); } static hb_bool_t hb_ot_get_font_v_extents (hb_font_t *font, - void *font_data, + void *font_data HB_UNUSED, hb_font_extents_t *metrics, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; - const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; - metrics->ascender = font->em_scale_x (vmtx.ascender); - metrics->descender = font->em_scale_x (vmtx.descender); - metrics->line_gap = font->em_scale_x (vmtx.line_gap); - // TODO Hook up variations. - return vmtx.has_font_extents; + return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_VERTICAL_ASCENDER, &metrics->ascender) && + _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_VERTICAL_DESCENDER, &metrics->descender) && + _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_VERTICAL_LINE_GAP, &metrics->line_gap); } #if HB_USE_ATEXIT diff --git a/src/hb-ot-hhea-table.hh b/src/hb-ot-hhea-table.hh index c3155b79e..778b6c513 100644 --- a/src/hb-ot-hhea-table.hh +++ b/src/hb-ot-hhea-table.hh @@ -45,6 +45,8 @@ namespace OT { template struct _hea { + bool has_data () const { return version.major; } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index bae18b807..240aac636 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -29,8 +29,8 @@ #include "hb-open-type.hh" #include "hb-ot-hhea-table.hh" -#include "hb-ot-os2-table.hh" #include "hb-ot-var-hvar-table.hh" +#include "hb-ot-metrics.hh" /* * hmtx -- Horizontal Metrics @@ -169,28 +169,7 @@ struct hmtxvmtx memset (this, 0, sizeof (*this)); default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face); - bool got_font_extents = false; - if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ()) - { - ascender = abs (face->table.OS2->sTypoAscender); - descender = -abs (face->table.OS2->sTypoDescender); - line_gap = face->table.OS2->sTypoLineGap; - got_font_extents = (ascender | descender) != 0; - } - - hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table (face); - const H *_hea_table = _hea_blob->as (); - num_advances = _hea_table->numberOfLongMetrics; - if (!got_font_extents) - { - ascender = abs (_hea_table->ascender); - descender = -abs (_hea_table->descender); - line_gap = _hea_table->lineGap; - got_font_extents = (ascender | descender) != 0; - } - hb_blob_destroy (_hea_blob); - - has_font_extents = got_font_extents; + num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics; table = hb_sanitize_context_t().reference_table (face, T::tableTag); @@ -307,12 +286,6 @@ struct hmtxvmtx return get_advance (old_gid); } - public: - bool has_font_extents; - int ascender; - int descender; - int line_gap; - protected: unsigned int num_metrics; unsigned int num_advances; @@ -352,12 +325,12 @@ struct hmtxvmtx struct hmtx : hmtxvmtx { static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx; static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR; - static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2; + static constexpr bool is_horizontal = true; }; struct vmtx : hmtxvmtx { static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx; static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR; - static constexpr hb_tag_t os2Tag = HB_TAG_NONE; + static constexpr bool is_horizontal = false; }; struct hmtx_accelerator_t : hmtx::accelerator_t {}; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 98cd10923..f493005bc 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -43,12 +43,12 @@ #include "hb-map.hh" #include "hb-ot-kern-table.hh" -#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise. +#include "hb-ot-meta-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-name-table.hh" #include "hb-ot-os2-table.hh" @@ -109,7 +109,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face) * * Tests whether a face has any cross-stream kerning (i.e., kerns * that make adjustments perpendicular to the direction of the text - * flow: Y adjustments in horizontal text or X adjustments in + * flow: Y adjustments in horizontal text or X adjustments in * vertical text) in the 'kern' table. * * Does NOT examine the GPOS table. @@ -286,7 +286,7 @@ hb_ot_layout_has_glyph_classes (hb_face_t *face) * * Fetches the GDEF class of the requested glyph in the specified face. * - * Return value: The #hb_ot_layout_glyph_class_t glyph class of the given code + * Return value: The #hb_ot_layout_glyph_class_t glyph class of the given code * point in the GDEF table of the face. * * Since: 0.9.7 @@ -330,7 +330,7 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face, * @point_array: (out) (array length=point_count): The array of attachment points found for the query * * Fetches a list of all attachment points for the specified glyph in the GDEF - * table of the face. The list returned will begin at the offset provided. + * table of the face. The list returned will begin at the offset provided. * * Useful if the client program wishes to cache the list. * @@ -980,7 +980,7 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, * @face: #hb_face_t to work upon * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * - * Fetches the total number of lookups enumerated in the specified + * Fetches the total number of lookups enumerated in the specified * face's GSUB table or GPOS table. * * Since: 0.9.22 @@ -1188,7 +1188,7 @@ hb_ot_layout_collect_features (hb_face_t *face, * table or GPOS table, underneath the specified scripts, languages, and * features. If no list of scripts is provided, all scripts will be queried. * If no list of languages is provided, all languages will be queried. If no - * list of features is provided, all features will be queried. + * list of features is provided, all features will be queried. * * Since: 0.9.8 **/ @@ -1582,7 +1582,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) * as used here are defined as pertaining only to fonts within a font family that differ * specifically in their respective size ranges; other ways to differentiate fonts within * a subfamily are not covered by the `size` feature. - * + * * For more information on this distinction, see the `size` documentation at * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-39size39 * @@ -1724,7 +1724,7 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face, * returned. This function can be called with incrementally larger start_offset * until the char_count output value is lower than its input value, or the size * of the characters array can be increased. - * + * * Return value: Number of total sample characters in the cvXX feature. * * Since: 2.0.0 diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 7b2befbce..ad864a762 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -158,7 +158,7 @@ typedef enum { /*< flags >*/ * hb_ot_math_glyph_part_t: * @glyph: The glyph index of the variant part * @start_connector_length: The length of the connector on the starting side of the variant part - * @end_connection_length: The length of the connector on the ending side of the variant part + * @end_connector_length: The length of the connector on the ending side of the variant part * @full_advance: The total advance of the part * @flags: #hb_ot_math_glyph_part_flags_t flags for the part * diff --git a/src/hb-ot-meta-table.hh b/src/hb-ot-meta-table.hh new file mode 100644 index 000000000..dac55e47f --- /dev/null +++ b/src/hb-ot-meta-table.hh @@ -0,0 +1,89 @@ +/* + * Copyright © 2019 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_OT_META_TABLE_HH +#define HB_OT_META_TABLE_HH + +#include "hb-open-type.hh" + +/* + * meta -- Metadata Table + * https://docs.microsoft.com/en-us/typography/opentype/spec/meta + * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html + */ +#define HB_OT_TAG_meta HB_TAG('m','e','t','a') + + +namespace OT { + + +struct DataMap +{ + bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + dataZ.sanitize (c, base, dataLength))); + } + + protected: + Tag tag; /* A tag indicating the type of metadata. */ + LOffsetTo> + dataZ; /* Offset in bytes from the beginning of the + * metadata table to the data for this tag. */ + HBUINT32 dataLength; /* Length of the data. The data is not required to + * be padded to any byte boundary. */ + public: + DEFINE_SIZE_STATIC (12); +}; + +struct meta +{ + static constexpr hb_tag_t tableTag = HB_OT_TAG_meta; + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + version == 1 && + dataMaps.sanitize (c, this))); + } + + protected: + HBUINT32 version; /* Version number of the metadata table — set to 1. */ + HBUINT32 flags; /* Flags — currently unused; set to 0. */ + HBUINT32 dataOffset; /* Per Apple specification: + * Offset from the beginning of the table to the data. + * Per OT specification: + * Reserved. Not used; should be set to 0. */ + LArrayOf + dataMaps; /* Array of data map records. */ + public: + DEFINE_SIZE_ARRAY (16, dataMaps); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_META_TABLE_HH */ diff --git a/src/hb-ot-metrics.cc b/src/hb-ot-metrics.cc new file mode 100644 index 000000000..910d826b9 --- /dev/null +++ b/src/hb-ot-metrics.cc @@ -0,0 +1,215 @@ +/* + * Copyright © 2018-2019 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb.hh" + +#include "hb-ot-var-mvar-table.hh" +#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise. +#include "hb-ot-os2-table.hh" +#include "hb-ot-post-table.hh" +#include "hb-ot-hhea-table.hh" +#include "hb-ot-metrics.hh" +#include "hb-ot-face.hh" + + +static float +_fix_ascender_descender (float value, hb_ot_metrics_t metrics_tag) +{ + if (metrics_tag == HB_OT_METRICS_HORIZONTAL_ASCENDER || + metrics_tag == HB_OT_METRICS_VERTICAL_ASCENDER) + return fabs ((double) value); + if (metrics_tag == HB_OT_METRICS_HORIZONTAL_DESCENDER || + metrics_tag == HB_OT_METRICS_VERTICAL_DESCENDER) + return -fabs ((double) value); + return value; +} + +/* The common part of _get_position logic needed on hb-ot-font and here + to be able to have slim builds without the not always needed parts */ +bool +_hb_ot_metrics_get_position_common (hb_font_t *font, + hb_ot_metrics_t metrics_tag, + hb_position_t *position /* OUT. May be NULL. */) +{ + hb_face_t *face = font->face; + switch ((unsigned int) metrics_tag) + { +#ifndef HB_NO_VAR +#define GET_VAR face->table.MVAR->get_var (metrics_tag, font->coords, font->num_coords) +#else +#define GET_VAR .0f +#endif +#define GET_METRIC_X(TABLE, ATTR) \ + (face->table.TABLE->has_data () && \ + (position && (*position = font->em_scalef_x (_fix_ascender_descender ( \ + face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true)) +#define GET_METRIC_Y(TABLE, ATTR) \ + (face->table.TABLE->has_data () && \ + (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \ + face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true)) + case HB_OT_METRICS_HORIZONTAL_ASCENDER: + return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) || + GET_METRIC_Y (hhea, ascender); + case HB_OT_METRICS_HORIZONTAL_DESCENDER: + return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoDescender)) || + GET_METRIC_Y (hhea, descender); + case HB_OT_METRICS_HORIZONTAL_LINE_GAP: + return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoLineGap)) || + GET_METRIC_Y (hhea, lineGap); + case HB_OT_METRICS_VERTICAL_ASCENDER: return GET_METRIC_X (vhea, ascender); + case HB_OT_METRICS_VERTICAL_DESCENDER: return GET_METRIC_X (vhea, descender); + case HB_OT_METRICS_VERTICAL_LINE_GAP: return GET_METRIC_X (vhea, lineGap); +#undef GET_METRIC_Y +#undef GET_METRIC_X +#undef GET_VAR + default: assert (0); return false; + } +} + +#ifndef HB_NO_METRICS + +#if 0 +static bool +_get_gasp (hb_face_t *face, float *result, hb_ot_metrics_t metrics_tag) +{ + const OT::GaspRange& range = face->table.gasp->get_gasp_range (metrics_tag - HB_TAG ('g','s','p','0')); + if (&range == &Null (OT::GaspRange)) return false; + if (result) *result = range.rangeMaxPPEM + font->face->table.MVAR->get_var (metrics_tag, font->coords, font->num_coords); + return true; +} +#endif + +/** + * hb_ot_metrics_get_position: + * @font: a #hb_font_t object. + * @metrics_tag: tag of metrics value you like to fetch. + * @position: (out) (optional): result of metrics value from the font. + * + * It fetches metrics value corresponding to a given tag from a font. + * + * Returns: Whether found the requested metrics in the font. + * Since: REPLACEME + **/ +hb_bool_t +hb_ot_metrics_get_position (hb_font_t *font, + hb_ot_metrics_t metrics_tag, + hb_position_t *position /* OUT. May be NULL. */) +{ + hb_face_t *face = font->face; + switch (metrics_tag) + { + case HB_OT_METRICS_HORIZONTAL_ASCENDER: + case HB_OT_METRICS_HORIZONTAL_DESCENDER: + case HB_OT_METRICS_HORIZONTAL_LINE_GAP: + case HB_OT_METRICS_VERTICAL_ASCENDER: + case HB_OT_METRICS_VERTICAL_DESCENDER: + case HB_OT_METRICS_VERTICAL_LINE_GAP: return _hb_ot_metrics_get_position_common (font, metrics_tag, position); +#ifndef HB_NO_VAR +#define GET_VAR hb_ot_metrics_get_variation (font, metrics_tag) +#else +#define GET_VAR 0 +#endif +#define GET_METRIC_X(TABLE, ATTR) \ + (face->table.TABLE->has_data () && \ + (position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR)), true)) +#define GET_METRIC_Y(TABLE, ATTR) \ + (face->table.TABLE->has_data () && \ + (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true)) + case HB_OT_METRICS_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent); + case HB_OT_METRICS_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent); + case HB_OT_METRICS_HORIZONTAL_CARET_RISE: return GET_METRIC_Y (hhea, caretSlopeRise); + case HB_OT_METRICS_HORIZONTAL_CARET_RUN: return GET_METRIC_X (hhea, caretSlopeRun); + case HB_OT_METRICS_HORIZONTAL_CARET_OFFSET: return GET_METRIC_X (hhea, caretOffset); + case HB_OT_METRICS_VERTICAL_CARET_RISE: return GET_METRIC_X (vhea, caretSlopeRise); + case HB_OT_METRICS_VERTICAL_CARET_RUN: return GET_METRIC_Y (vhea, caretSlopeRun); + case HB_OT_METRICS_VERTICAL_CARET_OFFSET: return GET_METRIC_Y (vhea, caretOffset); + case HB_OT_METRICS_X_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sxHeight); + case HB_OT_METRICS_CAP_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sCapHeight); + case HB_OT_METRICS_SUBSCRIPT_EM_X_SIZE: return GET_METRIC_X (OS2, ySubscriptXSize); + case HB_OT_METRICS_SUBSCRIPT_EM_Y_SIZE: return GET_METRIC_Y (OS2, ySubscriptYSize); + case HB_OT_METRICS_SUBSCRIPT_EM_X_OFFSET: return GET_METRIC_X (OS2, ySubscriptXOffset); + case HB_OT_METRICS_SUBSCRIPT_EM_Y_OFFSET: return GET_METRIC_Y (OS2, ySubscriptYOffset); + case HB_OT_METRICS_SUPERSCRIPT_EM_X_SIZE: return GET_METRIC_X (OS2, ySuperscriptXSize); + case HB_OT_METRICS_SUPERSCRIPT_EM_Y_SIZE: return GET_METRIC_Y (OS2, ySuperscriptYSize); + case HB_OT_METRICS_SUPERSCRIPT_EM_X_OFFSET: return GET_METRIC_X (OS2, ySuperscriptXOffset); + case HB_OT_METRICS_SUPERSCRIPT_EM_Y_OFFSET: return GET_METRIC_Y (OS2, ySuperscriptYOffset); + case HB_OT_METRICS_STRIKEOUT_SIZE: return GET_METRIC_Y (OS2, yStrikeoutSize); + case HB_OT_METRICS_STRIKEOUT_OFFSET: return GET_METRIC_Y (OS2, yStrikeoutPosition); + case HB_OT_METRICS_UNDERLINE_SIZE: return GET_METRIC_Y (post->table, underlineThickness); + case HB_OT_METRICS_UNDERLINE_OFFSET: return GET_METRIC_Y (post->table, underlinePosition); +#undef GET_METRIC_Y +#undef GET_METRIC_X +#undef GET_VAR + default: return false; + } +} + +#ifndef HB_NO_VAR +/** + * hb_ot_metrics_get_variation: + * @font: + * @metrics_tag: + * + * Returns: + * + * Since: REPLACEME + **/ +float +hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag) +{ + return font->face->table.MVAR->get_var (metrics_tag, font->coords, font->num_coords); +} + +/** + * hb_ot_metrics_get_x_variation: + * @font: + * @metrics_tag: + * + * Returns: + * + * Since: REPLACEME + **/ +hb_position_t +hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag) +{ + return font->em_scalef_x (hb_ot_metrics_get_variation (font, metrics_tag)); +} + +/** + * hb_ot_metrics_get_y_variation: + * @font: + * @metrics_tag: + * + * Returns: + * + * Since: REPLACEME + **/ +hb_position_t +hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag) +{ + return font->em_scalef_y (hb_ot_metrics_get_variation (font, metrics_tag)); +} +#endif + +#endif diff --git a/src/hb-ot-metrics.h b/src/hb-ot-metrics.h new file mode 100644 index 000000000..4d22837f2 --- /dev/null +++ b/src/hb-ot-metrics.h @@ -0,0 +1,92 @@ +/* + * Copyright © 2018 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_OT_H_IN +#error "Include instead." +#endif + +#ifndef HB_OT_METRICS_H +#define HB_OT_METRICS_H + +#include "hb.h" +#include "hb-ot-name.h" + +HB_BEGIN_DECLS + + +/** + * hb_ot_metrics_t: + * + * From https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags + * + * Since: REPLACEME + **/ +typedef enum { + HB_OT_METRICS_HORIZONTAL_ASCENDER = HB_TAG ('h','a','s','c'), + HB_OT_METRICS_HORIZONTAL_DESCENDER = HB_TAG ('h','d','s','c'), + HB_OT_METRICS_HORIZONTAL_LINE_GAP = HB_TAG ('h','l','g','p'), + HB_OT_METRICS_HORIZONTAL_CLIPPING_ASCENT = HB_TAG ('h','c','l','a'), + HB_OT_METRICS_HORIZONTAL_CLIPPING_DESCENT = HB_TAG ('h','c','l','d'), + HB_OT_METRICS_VERTICAL_ASCENDER = HB_TAG ('v','a','s','c'), + HB_OT_METRICS_VERTICAL_DESCENDER = HB_TAG ('v','d','s','c'), + HB_OT_METRICS_VERTICAL_LINE_GAP = HB_TAG ('v','l','g','p'), + HB_OT_METRICS_HORIZONTAL_CARET_RISE = HB_TAG ('h','c','r','s'), + HB_OT_METRICS_HORIZONTAL_CARET_RUN = HB_TAG ('h','c','r','n'), + HB_OT_METRICS_HORIZONTAL_CARET_OFFSET = HB_TAG ('h','c','o','f'), + HB_OT_METRICS_VERTICAL_CARET_RISE = HB_TAG ('v','c','r','s'), + HB_OT_METRICS_VERTICAL_CARET_RUN = HB_TAG ('v','c','r','n'), + HB_OT_METRICS_VERTICAL_CARET_OFFSET = HB_TAG ('v','c','o','f'), + HB_OT_METRICS_X_HEIGHT = HB_TAG ('x','h','g','t'), + HB_OT_METRICS_CAP_HEIGHT = HB_TAG ('c','p','h','t'), + HB_OT_METRICS_SUBSCRIPT_EM_X_SIZE = HB_TAG ('s','b','x','s'), + HB_OT_METRICS_SUBSCRIPT_EM_Y_SIZE = HB_TAG ('s','b','y','s'), + HB_OT_METRICS_SUBSCRIPT_EM_X_OFFSET = HB_TAG ('s','b','x','o'), + HB_OT_METRICS_SUBSCRIPT_EM_Y_OFFSET = HB_TAG ('s','b','y','o'), + HB_OT_METRICS_SUPERSCRIPT_EM_X_SIZE = HB_TAG ('s','p','x','s'), + HB_OT_METRICS_SUPERSCRIPT_EM_Y_SIZE = HB_TAG ('s','p','y','s'), + HB_OT_METRICS_SUPERSCRIPT_EM_X_OFFSET = HB_TAG ('s','p','x','o'), + HB_OT_METRICS_SUPERSCRIPT_EM_Y_OFFSET = HB_TAG ('s','p','y','o'), + HB_OT_METRICS_STRIKEOUT_SIZE = HB_TAG ('s','t','r','s'), + HB_OT_METRICS_STRIKEOUT_OFFSET = HB_TAG ('s','t','r','o'), + HB_OT_METRICS_UNDERLINE_SIZE = HB_TAG ('u','n','d','s'), + HB_OT_METRICS_UNDERLINE_OFFSET = HB_TAG ('u','n','d','o') +} hb_ot_metrics_t; + +HB_EXTERN hb_bool_t +hb_ot_metrics_get_position (hb_font_t *font, + hb_ot_metrics_t metrics_tag, + hb_position_t *position /* OUT. May be NULL. */); + +HB_EXTERN float +hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag); + +HB_EXTERN hb_position_t +hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag); + +HB_EXTERN hb_position_t +hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_t metrics_tag); + +HB_END_DECLS + +#endif /* HB_OT_METRICS_H */ diff --git a/src/hb-ot-metrics.hh b/src/hb-ot-metrics.hh new file mode 100644 index 000000000..f9ae46fc9 --- /dev/null +++ b/src/hb-ot-metrics.hh @@ -0,0 +1,35 @@ +/* + * Copyright © 2018 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_OT_METRICS_HH +#define HB_OT_METRICS_HH + +#include "hb.hh" + +HB_INTERNAL bool +_hb_ot_metrics_get_position_common (hb_font_t *font, + hb_ot_metrics_t metrics_tag, + hb_position_t *position /* OUT. May be NULL. */); + +#endif /* HB_OT_METRICS_HH */ diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh index 16e29caf3..67f21eb34 100644 --- a/src/hb-ot-os2-table.hh +++ b/src/hb-ot-os2-table.hh @@ -59,6 +59,10 @@ struct OS2V1Tail struct OS2V2Tail { + bool has_data () const { return this != &Null (OS2V2Tail); } + + const OS2V2Tail * operator -> () const { return this; } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -113,9 +117,9 @@ struct OS2 OBLIQUE = 1u<<9 }; - bool is_italic () const { return fsSelection & ITALIC; } - bool is_oblique () const { return fsSelection & OBLIQUE; } - bool is_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; } + bool is_italic () const { return fsSelection & ITALIC; } + bool is_oblique () const { return fsSelection & OBLIQUE; } + bool use_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; } enum width_class_t { FWIDTH_ULTRA_CONDENSED = 1, /* 50% */ @@ -192,13 +196,14 @@ struct OS2 } static void find_min_and_max_codepoint (const hb_set_t *codepoints, - uint16_t *min_cp, /* OUT */ - uint16_t *max_cp /* OUT */) + uint16_t *min_cp, /* OUT */ + uint16_t *max_cp /* OUT */) { *min_cp = codepoints->get_min (); *max_cp = codepoints->get_max (); } + /* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 */ enum font_page_t { HEBREW_FONT_PAGE = 0xB100, // Hebrew Windows 3.1 font page SIMP_ARABIC_FONT_PAGE = 0xB200, // Simplified Arabic Windows 3.1 font page @@ -208,8 +213,6 @@ struct OS2 TRAD_FARSI_FONT_PAGE = 0xBB00, // Traditional Farsi Windows 3.1 font page THAI_FONT_PAGE = 0xDE00 // Thai Windows 3.1 font page }; - - // https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 font_page_t get_font_page () const { return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); } diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh index 720e03bac..fb826cd35 100644 --- a/src/hb-ot-post-table.hh +++ b/src/hb-ot-post-table.hh @@ -178,6 +178,8 @@ struct post return false; } + hb_blob_ptr_t table; + protected: unsigned int get_glyph_count () const @@ -237,7 +239,6 @@ struct post } private: - hb_blob_ptr_t table; uint32_t version; const ArrayOf *glyphNameIndex; hb_vector_t index_to_offset; @@ -245,6 +246,8 @@ struct post hb_atomic_ptr_t gids_sorted_by_name; }; + bool has_data () const { return version.to_int (); } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-ot.h b/src/hb-ot.h index db784694c..d00ee80ae 100644 --- a/src/hb-ot.h +++ b/src/hb-ot.h @@ -35,6 +35,7 @@ #include "hb-ot-font.h" #include "hb-ot-layout.h" #include "hb-ot-math.h" +#include "hb-ot-metrics.h" #include "hb-ot-name.h" #include "hb-ot-shape.h" #include "hb-ot-var.h" diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh index 9b181c11c..0c355f111 100644 --- a/src/hb-unicode.hh +++ b/src/hb-unicode.hh @@ -105,9 +105,6 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE unsigned int modified_combining_class (hb_codepoint_t u) { - /* XXX This hack belongs to the Myanmar shaper. */ - if (unlikely (u == 0x1037u)) u = 0x103Au; - /* XXX This hack belongs to the USE shaper (for Tai Tham): * Reorder SAKOT to ensure it comes after any tone marks. */ if (unlikely (u == 0x1A60u)) return 254; diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index b113ed4cf..289a3477f 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -58,13 +58,6 @@ * Functions for using HarfBuzz with the Windows fonts. **/ - -static inline uint16_t hb_uint16_swap (const uint16_t v) -{ return (v >> 8) | (v << 8); } -static inline uint32_t hb_uint32_swap (const uint32_t v) -{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } - - typedef HRESULT (WINAPI *SIOT) /*ScriptItemizeOpenType*/( const WCHAR *pwcInChars, int cInChars, diff --git a/src/hb.hh b/src/hb.hh index f8b5e70a8..8dcd5aa88 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -318,7 +318,8 @@ extern "C" void hb_free_impl(void *ptr); # define HB_FALLTHROUGH /* FALLTHROUGH */ #endif -#ifdef __clang__ +/* https://github.com/harfbuzz/harfbuzz/issues/1852 */ +#if defined(__clang__) && !(defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))) /* Disable certain sanitizer errors. */ /* https://github.com/harfbuzz/harfbuzz/issues/1247 */ #define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow"))) @@ -476,6 +477,11 @@ static_assert ((sizeof (hb_var_int_t) == 4), ""); /* Size signifying variable-sized array */ #define VAR 1 +/* Endian swap, used in Windows related backends */ +static inline uint16_t hb_uint16_swap (const uint16_t v) +{ return (v >> 8) | (v << 8); } +static inline uint32_t hb_uint32_swap (const uint32_t v) +{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } /* * Big-endian integers. Here because fundamental. diff --git a/test/api/Makefile.am b/test/api/Makefile.am index 85f2f6fd1..b95d8c9ac 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -90,6 +90,7 @@ TEST_PROGS += \ test-ot-color \ test-ot-ligature-carets \ test-ot-name \ + test-ot-metrics \ test-ot-tag \ test-ot-extents-cff \ test-ot-metrics-tt-var \ diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index c0cbd77b9..d646f7371 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -426,9 +426,9 @@ test_hb_ot_color_png (void) g_assert (strncmp (data + 1, "PNG", 3) == 0); hb_font_get_glyph_extents (sbix_font, 1, &extents); g_assert_cmpint (extents.x_bearing, ==, 0); - g_assert_cmpint (extents.y_bearing, ==, 0); + g_assert_cmpint (extents.y_bearing, ==, 800); g_assert_cmpint (extents.width, ==, 800); - g_assert_cmpint (extents.height, ==, 800); + g_assert_cmpint (extents.height, ==, -800); hb_blob_destroy (blob); hb_font_destroy (sbix_font); diff --git a/test/api/test-ot-metrics.c b/test/api/test-ot-metrics.c new file mode 100644 index 000000000..91dd7f5e1 --- /dev/null +++ b/test/api/test-ot-metrics.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2018 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb-test.h" + +#include + +#include + +/* Unit tests for hb-ot-metrics.h */ + +static void +test_ot_metrics_get (void) +{ + hb_face_t *face = hb_test_open_font_file ("fonts/cpal-v0.ttf"); + hb_font_t *font = hb_font_create (face); + hb_position_t value; + g_assert (hb_ot_metrics_get_position (font, HB_OT_METRICS_HORIZONTAL_ASCENDER, &value)); + g_assert_cmpint (value, ==, 1000); + g_assert_cmpint (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0); + g_assert_cmpint (hb_ot_metrics_get_y_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0); + // g_assert_cmpint ((int) hb_ot_metrics_get_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0); + hb_font_destroy (font); + hb_face_destroy (face); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + hb_test_add (test_ot_metrics_get); + return hb_test_run (); +} diff --git a/test/fuzzing/run-shape-fuzzer-tests.py b/test/fuzzing/run-shape-fuzzer-tests.py index ba480dd52..6d36c2cfe 100755 --- a/test/fuzzing/run-shape-fuzzer-tests.py +++ b/test/fuzzing/run-shape-fuzzer-tests.py @@ -5,41 +5,41 @@ from __future__ import print_function, division, absolute_import import sys, os, subprocess, tempfile, threading -def which(program): +def which (program): # https://stackoverflow.com/a/377028 - def is_exe(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + def is_exe (fpath): + return os.path.isfile (fpath) and os.access (fpath, os.X_OK) - fpath, _ = os.path.split(program) + fpath, _ = os.path.split (program) if fpath: - if is_exe(program): + if is_exe (program): return program else: - for path in os.environ["PATH"].split(os.pathsep): - exe_file = os.path.join(path, program) - if is_exe(exe_file): + for path in os.environ["PATH"].split (os.pathsep): + exe_file = os.path.join (path, program) + if is_exe (exe_file): return exe_file return None -def cmd(command): +def cmd (command): # https://stackoverflow.com/a/4408409 # https://stackoverflow.com/a/10012262 - with tempfile.TemporaryFile() as tempf: + with tempfile.TemporaryFile () as tempf: p = subprocess.Popen (command, stderr=tempf) is_killed = {'value': False} - def timeout(p, is_killed): + def timeout (p, is_killed): is_killed['value'] = True - p.kill() + p.kill () timer = threading.Timer (2, timeout, [p, is_killed]) try: timer.start() p.wait () tempf.seek (0) - text = tempf.read().decode ("utf-8").strip () + text = tempf.read ().decode ("utf-8").strip () returncode = p.returncode finally: timer.cancel() @@ -67,9 +67,9 @@ please provide it as the first argument to the tool""") print ('hb_shape_fuzzer:', hb_shape_fuzzer) fails = 0 -libtool = os.environ.get('LIBTOOL') +libtool = os.environ.get ('LIBTOOL') valgrind = None -if os.environ.get('RUN_VALGRIND', ''): +if os.environ.get ('RUN_VALGRIND', ''): valgrind = which ('valgrind') if valgrind is None: print ("""Valgrind requested but not found.""") @@ -80,7 +80,7 @@ if os.environ.get('RUN_VALGRIND', ''): parent_path = os.path.join (srcdir, "fonts") for file in os.listdir (parent_path): - path = os.path.join(parent_path, file) + path = os.path.join (parent_path, file) if valgrind: text, returncode = cmd (libtool.split(' ') + ['--mode=execute', valgrind + ' --leak-check=full --error-exitcode=1', '--', hb_shape_fuzzer, path]) @@ -89,7 +89,7 @@ for file in os.listdir (parent_path): if 'error' in text: returncode = 1 - if not valgrind and text.strip (): + if (not valgrind or returncode) and text.strip (): print (text) if returncode != 0: diff --git a/test/shaping/data/in-house/fonts/fcbaa518d3cce441ed37ae3b1fed6a19e9b54efd.ttf b/test/shaping/data/in-house/fonts/fcbaa518d3cce441ed37ae3b1fed6a19e9b54efd.ttf new file mode 100644 index 000000000..b1a8a33e9 Binary files /dev/null and b/test/shaping/data/in-house/fonts/fcbaa518d3cce441ed37ae3b1fed6a19e9b54efd.ttf differ diff --git a/test/shaping/data/in-house/tests/color-fonts.tests b/test/shaping/data/in-house/tests/color-fonts.tests index b325d78c1..bf0005c67 100644 --- a/test/shaping/data/in-house/tests/color-fonts.tests +++ b/test/shaping/data/in-house/tests/color-fonts.tests @@ -1 +1,2 @@ ../fonts/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf:--font-funcs=ot --show-extents:U+1F42F:[gid1=0+2963<0,2179,2963,-2789>] +../fonts/fcbaa518d3cce441ed37ae3b1fed6a19e9b54efd.ttf:--font-funcs=ot --show-extents:U+1F600:[gid4=0+2550<0,1898,2555,-2405>]