Merge branch 'var-subset' of https://github.com/harfbuzz/harfbuzz into var-subset

This commit is contained in:
Michiharu Ariza 2019-07-31 14:58:53 -07:00
commit 07f27accb9
106 changed files with 1419 additions and 338 deletions

View File

@ -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)
@ -140,8 +142,8 @@ endif ()
## Extract variables from Makefile files
function (extract_make_variable variable makefile_source)
string(REGEX MATCH "${variable} = ([^$]+)\\$" temp ${makefile_source})
string(REGEX MATCHALL "[^ \n\t\\]+" listVar ${CMAKE_MATCH_1})
string(REGEX MATCH "${variable} = ([^$]+)\\$" temp "${makefile_source}")
string(REGEX MATCHALL "[^ \n\t\\]+" listVar "${CMAKE_MATCH_1}")
set (${variable} ${listVar} PARENT_SCOPE)
endfunction ()
@ -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)

View File

@ -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\

View File

@ -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:

View File

@ -1,6 +1,7 @@
<SUBSECTION Private>
HB_H_IN
HB_OT_H_IN
HB_AAT_H_IN
</SECTION>
<SECTION>
@ -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
</SECTION>
<SECTION>
<FILE>hb-gdi</FILE>
hb_gdi_face_create
</SECTION>
<SECTION>
<FILE>hb-glib</FILE>
hb_glib_get_unicode_funcs
@ -600,6 +607,22 @@ hb_ot_math_get_min_connector_overlap
hb_ot_math_get_glyph_assembly
</SECTION>
<SECTION>
<FILE>hb-ot-meta</FILE>
hb_ot_meta_t
hb_ot_meta_get_entries
hb_ot_meta_reference_entry
</SECTION>
<SECTION>
<FILE>hb-ot-metrics</FILE>
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
</SECTION>
<SECTION>
<FILE>hb-ot-shape</FILE>
hb_ot_shape_glyphs_closure

View File

@ -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 | \
@ -324,6 +332,7 @@ noinst_PROGRAMS = \
main \
test \
test-buffer-serialize \
test-ot-meta \
test-ot-name \
test-gpos-size-params \
test-gsub-would-substitute \
@ -342,6 +351,10 @@ test_buffer_serialize_SOURCES = test-buffer-serialize.cc
test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
test_ot_meta_SOURCES = test-ot-meta.cc
test_ot_meta_CPPFLAGS = $(HBCFLAGS)
test_ot_meta_LDADD = libharfbuzz.la $(HBLIBS)
test_ot_name_SOURCES = test-ot-name.cc
test_ot_name_CPPFLAGS = $(HBCFLAGS)
test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)

View File

@ -89,6 +89,10 @@ HB_BASE_sources = \
hb-ot-math-table.hh \
hb-ot-math.cc \
hb-ot-maxp-table.hh \
hb-ot-meta-table.hh \
hb-ot-meta.cc \
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 +197,8 @@ HB_BASE_headers = \
hb-ot-font.h \
hb-ot-layout.h \
hb-ot-math.h \
hb-ot-meta.h \
hb-ot-metrics.h \
hb-ot-name.h \
hb-ot-shape.h \
hb-ot-var.h \
@ -224,6 +230,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

View File

@ -17,6 +17,8 @@
#include "hb-ot-layout.cc"
#include "hb-ot-map.cc"
#include "hb-ot-math.cc"
#include "hb-ot-meta.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 +49,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"

View File

@ -174,9 +174,7 @@ struct feat
}
const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
{
return namesZ.bsearch (featureNameCount, feature_type);
}
{ return namesZ.bsearch (featureNameCount, feature_type); }
hb_ot_name_id_t get_feature_name_id (hb_aat_layout_feature_type_t feature) const
{ return get_feature (feature).get_feature_name_id (); }

View File

@ -85,7 +85,7 @@ typedef enum
HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE = 39,
HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE = 103,
_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_aat_layout_feature_type_t;
/**
@ -424,7 +424,7 @@ typedef enum
HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN = 2,
HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN = 3,
_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_aat_layout_feature_selector_t;
HB_EXTERN unsigned int

View File

@ -94,6 +94,14 @@ struct hb_bimap_t
/* Inremental bimap: only lhs is given, rhs is incrementally assigned */
struct hb_inc_bimap_t : hb_bimap_t
{
hb_inc_bimap_t () { init (); }
void init ()
{
hb_bimap_t::init ();
next_value = 0;
}
/* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
* Return the rhs value as the result.
*/
@ -102,12 +110,24 @@ struct hb_inc_bimap_t : hb_bimap_t
hb_codepoint_t rhs = forw_map[lhs];
if (rhs == HB_MAP_VALUE_INVALID)
{
rhs = get_population ();
rhs = next_value++;
set (lhs, rhs);
}
return rhs;
}
hb_codepoint_t skip ()
{ return next_value++; }
hb_codepoint_t get_next_value () const
{ return next_value; }
void add_set (const hb_set_t *set)
{
hb_codepoint_t i = HB_SET_VALUE_INVALID;
while (hb_set_next (set, &i)) add (i);
}
/* Create an identity map. */
bool identity (unsigned int size)
{
@ -138,6 +158,9 @@ struct hb_inc_bimap_t : hb_bimap_t
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
set (work[rhs], rhs);
}
protected:
unsigned int next_value;
};
#endif /* HB_BIMAP_HH */

View File

@ -66,6 +66,8 @@
#define HB_NO_LAYOUT_COLLECT_GLYPHS
#define HB_NO_LAYOUT_UNUSED
#define HB_NO_MATH
#define HB_NO_META
#define HB_NO_METRICS
#define HB_NO_MMAP
#define HB_NO_NAME
#define HB_NO_OPEN

View File

@ -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;

73
src/hb-gdi.cc Normal file
View File

@ -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

39
src/hb-gdi.h Normal file
View File

@ -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 <windows.h>
HB_BEGIN_DECLS
HB_EXTERN hb_face_t *
hb_gdi_face_create (HFONT hfont);
HB_END_DECLS
#endif /* HB_GDI_H */

View File

@ -106,32 +106,6 @@ retry:
return d;
}
static void hb_graphite2_release_table(const void *data, const void *table_buffer)
{
hb_graphite2_face_data_t *face_data = (hb_graphite2_face_data_t *) data;
hb_graphite2_tablelist_t *tlist = face_data->tlist;
hb_graphite2_tablelist_t *prev = nullptr;
hb_graphite2_tablelist_t *curr = tlist;
while (curr)
{
if (hb_blob_get_data(curr->blob, nullptr) == table_buffer)
{
if (prev == nullptr)
face_data->tlist.cmpexch(tlist, curr->next);
else
prev->next = curr->next;
hb_blob_destroy(curr->blob);
free(curr);
break;
}
prev = curr;
curr = curr->next;
}
}
static gr_face_ops hb_graphite2_face_ops = { sizeof(gr_face_ops), hb_graphite2_get_table, hb_graphite2_release_table };
hb_graphite2_face_data_t *
_hb_graphite2_shaper_face_data_create (hb_face_t *face)
{
@ -150,7 +124,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
return nullptr;
data->face = face;
data->grface = gr_make_face_with_ops (data, &hb_graphite2_face_ops, gr_face_preloadAll);
data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
if (unlikely (!data->grface)) {
free (data);

View File

@ -480,7 +480,7 @@ struct hb_reduce_t
template <typename Iter,
hb_requires (hb_is_iterator (Iter)),
typename AccuT = decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>
typename AccuT = hb_decay<decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>>
AccuT
operator () (Iter it)
{

View File

@ -141,14 +141,15 @@ typedef struct OffsetTable
TableRecord &rec = tables.arrayZ[i];
hb_blob_t *blob = items[i].blob;
rec.tag = items[i].tag;
rec.length = hb_blob_get_length (blob);
rec.length = blob->length;
rec.offset.serialize (c, this);
/* Allocate room for the table and copy it. */
char *start = (char *) c->allocate_size<void> (rec.length);
if (unlikely (!start)) {return false;}
if (unlikely (!start)) return false;
memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
if (likely (rec.length))
memcpy (start, blob->data, rec.length);
/* 4-byte alignment. */
c->align (4);

View File

@ -979,6 +979,14 @@ struct cmap
if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups)))
return false;
}
else
{
// FIXME: Merge this with above or, remove and tweak #final_size
// and rebase all the tests expectations
HBUINT32 empty;
empty = 0;
for (unsigned int i = 0; i < 4; ++i) c.copy (empty);
}
c.end_serialize ();

View File

@ -235,9 +235,9 @@ struct sbix
const PNGHeader &png = *blob->as<PNGHeader>();
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)

View File

@ -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,12 @@ HB_OT_ACCELERATOR (OT, name)
#ifndef HB_NO_STAT
HB_OT_TABLE (OT, STAT)
#endif
#ifndef HB_NO_META
HB_OT_ACCELERATOR (OT, meta)
#endif
/* Vertical layout. */
HB_OT_TABLE (OT, vhea)
HB_OT_ACCELERATOR (OT, vmtx)
/* TrueType outlines. */

View File

@ -32,6 +32,7 @@
#include "hb-ot-cff2-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-kern-table.hh"
#include "hb-ot-meta-table.hh"
#include "hb-ot-name-table.hh"
#include "hb-ot-post-table.hh"
#include "hb-ot-color-cbdt-table.hh"

View File

@ -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

View File

@ -45,6 +45,8 @@ namespace OT {
template <typename T>
struct _hea
{
bool has_data () const { return version.major; }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);

View File

@ -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<H> (face);
const H *_hea_table = _hea_blob->as<H> ();
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<hmtxvmtx> (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<hmtx, hhea> {
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<vmtx, vhea> {
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 {};

View File

@ -1,7 +1,7 @@
/*
* Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
* Copyright © 2018 Google, Inc.
* Copyright © 2018 Ebrahim Byagowi
* Copyright © 2018-2019 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
@ -116,6 +116,8 @@ struct BaseCoordFormat3
struct BaseCoord
{
bool has_data () const { return u.format; }
hb_position_t get_coord (hb_font_t *font,
const VariationStore &var_store,
hb_direction_t direction) const
@ -153,14 +155,9 @@ struct BaseCoord
struct FeatMinMaxRecord
{
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
{
hb_tag_t key = * (hb_tag_t *) key_;
const FeatMinMaxRecord &entry = * (const FeatMinMaxRecord *) entry_;
return key < (unsigned int) entry.tag ? -1 :
key > (unsigned int) entry.tag ? 1 :
0;
}
int cmp (hb_tag_t key) const { return tag.cmp (key); }
bool has_data () const { return tag; }
void get_min_max (const BaseCoord **min, const BaseCoord **max) const
{
@ -198,14 +195,9 @@ struct MinMax
const BaseCoord **min,
const BaseCoord **max) const
{
/* TODO Replace hb_bsearch() with .bsearch(). */
const FeatMinMaxRecord *minMaxCoord = (const FeatMinMaxRecord *)
hb_bsearch (&feature_tag, featMinMaxRecords.arrayZ,
featMinMaxRecords.len,
FeatMinMaxRecord::static_size,
FeatMinMaxRecord::cmp);
if (minMaxCoord)
minMaxCoord->get_min_max (min, max);
const FeatMinMaxRecord &minMaxCoord = featMinMaxRecords.bsearch (feature_tag);
if (minMaxCoord.has_data ())
minMaxCoord.get_min_max (min, max);
else
{
if (likely (min)) *min = &(this+minCoord);
@ -271,17 +263,11 @@ struct BaseValues
struct BaseLangSysRecord
{
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
{
hb_tag_t key = * (hb_tag_t *) key_;
const BaseLangSysRecord &entry = * (const BaseLangSysRecord *) entry_;
return key < (unsigned int) entry.baseLangSysTag ? -1 :
key > (unsigned int) entry.baseLangSysTag ? 1 :
0;
}
int cmp (hb_tag_t key) const { return baseLangSysTag.cmp (key); }
const MinMax &get_min_max () const
{ return this+minMax; }
bool has_data () const { return baseLangSysTag; }
const MinMax &get_min_max () const { return this+minMax; }
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
@ -303,19 +289,14 @@ struct BaseScript
{
const MinMax &get_min_max (hb_tag_t language_tag) const
{
/* TODO Replace hb_bsearch() with .bsearch(). */
const BaseLangSysRecord* record = (const BaseLangSysRecord *)
hb_bsearch (&language_tag, baseLangSysRecords.arrayZ,
baseLangSysRecords.len,
BaseLangSysRecord::static_size,
BaseLangSysRecord::cmp);
return record ? record->get_min_max () : this+defaultMinMax;
const BaseLangSysRecord& record = baseLangSysRecords.bsearch (language_tag);
return record.has_data () ? record.get_min_max () : this+defaultMinMax;
}
const BaseCoord &get_base_coord (int baseline_tag_index) const
{ return (this+baseValues).get_base_coord (baseline_tag_index); }
bool is_empty () const { return !baseValues; }
bool has_data () const { return baseValues; }
bool sanitize (hb_sanitize_context_t *c) const
{
@ -345,14 +326,9 @@ struct BaseScript
struct BaseScriptList;
struct BaseScriptRecord
{
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
{
hb_tag_t key = * (hb_tag_t *) key_;
const BaseScriptRecord &entry = * (const BaseScriptRecord *) entry_;
return key < (unsigned int) entry.baseScriptTag ? -1 :
key > (unsigned int) entry.baseScriptTag ? 1 :
0;
}
int cmp (hb_tag_t key) const { return baseScriptTag.cmp (key); }
bool has_data () const { return baseScriptTag; }
const BaseScript &get_base_script (const BaseScriptList *list) const
{ return list+baseScript; }
@ -376,22 +352,11 @@ struct BaseScriptRecord
struct BaseScriptList
{
const BaseScriptRecord *find_record (hb_tag_t script) const
{
/* TODO Replace hb_bsearch() with .bsearch(). */
return (const BaseScriptRecord *) hb_bsearch (&script, baseScriptRecords.arrayZ,
baseScriptRecords.len,
BaseScriptRecord::static_size,
BaseScriptRecord::cmp);
}
/* TODO: Or client should handle fallback? */
const BaseScript &get_base_script (hb_tag_t script) const
{
const BaseScriptRecord *record = find_record (script);
if (!record) record = find_record ((hb_script_t) HB_TAG ('D','F','L','T'));
return record ? record->get_base_script (this) : Null (BaseScript);
const BaseScriptRecord *record = &baseScriptRecords.bsearch (script);
if (!record->has_data ()) record = &baseScriptRecords.bsearch (HB_TAG ('D','F','L','T'));
return record->has_data () ? record->get_base_script (this) : Null (BaseScript);
}
bool sanitize (hb_sanitize_context_t *c) const
@ -417,9 +382,14 @@ struct Axis
const BaseCoord **coord) const
{
const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
if (base_script.is_empty ()) return false;
if (!base_script.has_data ()) return false;
if (likely (coord)) *coord = &base_script.get_base_coord ((this+baseTagList).bsearch (baseline));
if (likely (coord))
{
unsigned int tag_index = 0;
(this+baseTagList).bfind (baseline, &tag_index);
*coord = &base_script.get_base_coord (tag_index);
}
return true;
}
@ -431,7 +401,7 @@ struct Axis
const BaseCoord **max_coord) const
{
const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
if (base_script.is_empty ()) return false;
if (!base_script.has_data ()) return false;
base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord);
@ -479,13 +449,14 @@ struct BASE
hb_tag_t language_tag,
hb_position_t *base) const
{
const BaseCoord *base_coord;
if (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord))
const BaseCoord *base_coord = nullptr;
if (unlikely (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord) ||
!base_coord || !base_coord->has_data ()))
return false;
if (likely (base && base_coord)) *base = base_coord->get_coord (font,
get_var_store (),
direction);
if (likely (base))
*base = base_coord->get_coord (font, get_var_store (), direction);
return true;
}

View File

@ -1723,6 +1723,9 @@ struct VarData
unsigned int get_region_index_count () const
{ return regionIndices.len; }
unsigned int get_row_size () const
{ return shortCount + regionIndices.len; }
unsigned int get_size () const
{ return itemCount * get_row_size (); }
@ -1783,12 +1786,12 @@ struct VarData
bool serialize (hb_serialize_context_t *c,
const VarData *src,
const hb_bimap_t &inner_map,
const hb_inc_bimap_t &inner_map,
const hb_bimap_t &region_map)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
itemCount = inner_map.get_population ();
itemCount = inner_map.get_next_value ();
/* Optimize short count */
unsigned short ri_count = src->regionIndices.len;
@ -1802,7 +1805,7 @@ struct VarData
for (r = 0; r < ri_count; r++)
{
delta_sz[r] = kZero;
for (unsigned int i = 0; i < inner_map.get_population (); i++)
for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
{
unsigned int old = inner_map.backward (i);
int16_t delta = src->get_item_delta (old, r);
@ -1838,8 +1841,7 @@ struct VarData
for (unsigned int i = 0; i < itemCount; i++)
{
hb_codepoint_t old = inner_map.backward (i);
if (unlikely (old >= src->itemCount)) return_trace (false);
unsigned int old = inner_map.backward (i);
for (unsigned int r = 0; r < ri_count; r++)
if (delta_sz[r]) set_item_delta (i, ri_map[r], src->get_item_delta (old, r));
}
@ -1847,13 +1849,13 @@ struct VarData
return_trace (true);
}
void collect_region_refs (hb_inc_bimap_t &region_map, const hb_bimap_t &inner_map) const
void collect_region_refs (hb_inc_bimap_t &region_map, const hb_inc_bimap_t &inner_map) const
{
for (unsigned int r = 0; r < regionIndices.len; r++)
{
unsigned int region = regionIndices[r];
if (region_map.has (region)) continue;
for (unsigned int i = 0; i < inner_map.get_population (); i++)
for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
if (get_item_delta (inner_map.backward (i), r) != 0)
{
region_map.add (region);
@ -1863,9 +1865,6 @@ struct VarData
}
protected:
unsigned int get_row_size () const
{ return shortCount + regionIndices.len; }
const HBUINT8 *get_delta_bytes () const
{ return &StructAfter<HBUINT8> (regionIndices); }
@ -1874,7 +1873,7 @@ struct VarData
int16_t get_item_delta (unsigned int item, unsigned int region) const
{
if (unlikely (item >= itemCount || region >= regionIndices.len)) return 0;
if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0;
const HBINT8 *p = (const HBINT8 *)get_delta_bytes () + item * get_row_size ();
if (region < shortCount)
return ((const HBINT16 *)p)[region];
@ -1940,20 +1939,20 @@ struct VariationStore
bool serialize (hb_serialize_context_t *c,
const VariationStore *src,
const hb_array_t <hb_inc_bimap_t> &inner_remaps)
const hb_array_t <hb_inc_bimap_t> &inner_maps)
{
TRACE_SERIALIZE (this);
unsigned int set_count = 0;
for (unsigned int i = 0; i < inner_remaps.length; i++)
if (inner_remaps[i].get_population () > 0) set_count++;
for (unsigned int i = 0; i < inner_maps.length; i++)
if (inner_maps[i].get_population () > 0) set_count++;
unsigned int size = min_size + HBUINT32::static_size * set_count;
if (unlikely (!c->allocate_size<HBUINT32> (size))) return_trace (false);
format = 1;
hb_inc_bimap_t region_map;
for (unsigned int i = 0; i < inner_remaps.length; i++)
(src+src->dataSets[i]).collect_region_refs (region_map, inner_remaps[i]);
for (unsigned int i = 0; i < inner_maps.length; i++)
(src+src->dataSets[i]).collect_region_refs (region_map, inner_maps[i]);
region_map.sort ();
if (unlikely (!regions.serialize (c, this)
@ -1964,11 +1963,11 @@ struct VariationStore
*/
dataSets.len = set_count;
unsigned int set_index = 0;
for (unsigned int i = 0; i < inner_remaps.length; i++)
for (unsigned int i = 0; i < inner_maps.length; i++)
{
if (inner_remaps[i].get_population () == 0) continue;
if (inner_maps[i].get_population () == 0) continue;
if (unlikely (!dataSets[set_index++].serialize (c, this)
.serialize (c, &(src+src->dataSets[i]), inner_remaps[i], region_map)))
.serialize (c, &(src+src->dataSets[i]), inner_maps[i], region_map)))
return_trace (false);
}
@ -1993,8 +1992,6 @@ struct VariationStore
&scalars[0], num_scalars);
}
const VarRegionList &get_regions () const { return this+regions; }
unsigned int get_sub_table_count () const { return dataSets.len; }
protected:

View File

@ -733,7 +733,7 @@ struct PairPosFormat1
+ hb_zip (this+coverage, pairSet)
| hb_filter (*glyphs, hb_first)
| hb_map (hb_second)
| hb_map ([=] (const OffsetTo<PairSet> &_)
| hb_map ([glyphs, this] (const OffsetTo<PairSet> &_)
{ return (this+_).intersects (glyphs, valueFormat); })
| hb_any
;

View File

@ -248,7 +248,7 @@ struct SingleSubst
if (unlikely (!c->extend_min (u.format))) return_trace (false);
unsigned format = 2;
unsigned delta = 0;
if (glyphs.len ())
if (glyphs)
{
format = 1;
auto get_delta = [=] (hb_codepoint_pair_t _) {

View File

@ -43,7 +43,6 @@
#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"
@ -1980,7 +1979,9 @@ typedef enum {
HB_OT_LAYOUT_BASELINE_IDEO = HB_TAG('i','d','e','o'),
HB_OT_LAYOUT_BASELINE_IDTB = HB_TAG('i','d','t','b'),
HB_OT_LAYOUT_BASELINE_MATH = HB_TAG('m','a','t','h'),
HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n')
HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n'),
_HB_OT_LAYOUT_BASELINE_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_layout_baseline_t;

View File

@ -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
*

124
src/hb-ot-meta-table.hh Normal file
View File

@ -0,0 +1,124 @@
/*
* 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
{
int cmp (hb_tag_t a) const { return tag.cmp (a); }
hb_tag_t get_tag () const { return tag; }
hb_blob_t *reference_entry (hb_blob_t *meta_blob) const
{ return hb_blob_create_sub_blob (meta_blob, dataZ, dataLength); }
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<UnsizedArrayOf<HBUINT8>>
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;
struct accelerator_t
{
void init (hb_face_t *face)
{ table = hb_sanitize_context_t ().reference_table<meta> (face); }
void fini () { table.destroy (); }
hb_blob_t *reference_entry (hb_tag_t tag) const
{ return table->dataMaps.lsearch (tag).reference_entry (table.get_blob ()); }
unsigned int get_entries (unsigned int start_offset,
unsigned int *count,
hb_ot_meta_tag_t *entries) const
{
if (count)
{
hb_array_t<const DataMap> arr = table->dataMaps.sub_array (start_offset, count);
for (unsigned int i = 0; i < arr.length; i++)
entries[i] = (hb_ot_meta_tag_t) arr[i].get_tag ();
}
return table->dataMaps.len;
}
private:
hb_blob_ptr_t<meta> table;
};
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<DataMap>
dataMaps; /* Array of data map records. */
public:
DEFINE_SIZE_ARRAY (16, dataMaps);
};
struct meta_accelerator_t : meta::accelerator_t {};
} /* namespace OT */
#endif /* HB_OT_META_TABLE_HH */

77
src/hb-ot-meta.cc Normal file
View File

@ -0,0 +1,77 @@
/*
* Copyright © 2019 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include "hb.hh"
#ifndef HB_NO_META
#include "hb-ot-meta-table.hh"
/**
* SECTION:hb-ot-meta
* @title: hb-ot-meta
* @short_description: OpenType Metadata
* @include: hb-ot.h
*
* Functions for fetching metadata from fonts.
**/
/**
* hb_ot_meta_reference_entry:
* @face: a face object
* @start_offset: iteration's start offset
* @entries_count:(inout) (allow-none): buffer size as input, filled size as output
* @entries: (out caller-allocates) (array length=entries_count): entries tags buffer
*
* Return value: Number of all available feature types.
*
* Since: REPLACEME
**/
unsigned int
hb_ot_meta_get_entries (hb_face_t *face,
unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT. May be NULL. */
hb_ot_meta_tag_t *entries /* OUT. May be NULL. */)
{
return face->table.meta->get_entries (start_offset, entries_count, entries);
}
/**
* hb_ot_meta_reference_entry:
* @face: a #hb_face_t object.
* @meta_tag: tag of metadata you like to have.
*
* It fetches metadata entry of a given tag from a font.
*
* Returns: (transfer full): A blob containing the blob.
*
* Since: REPLACEME
**/
hb_blob_t *
hb_ot_meta_reference_entry (hb_face_t *face, hb_ot_meta_tag_t meta_tag)
{
return face->table.meta->reference_entry (meta_tag);
}
#endif

65
src/hb-ot-meta.h Normal file
View File

@ -0,0 +1,65 @@
/*
* 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_H_IN
#error "Include <hb-ot.h> instead."
#endif
#ifndef HB_OT_META_H
#define HB_OT_META_H
#include "hb.h"
HB_BEGIN_DECLS
/**
* hb_ot_meta_tag_t:
*
* From https://docs.microsoft.com/en-us/typography/opentype/spec/meta
*
* Since: REPLACEME
**/
typedef enum {
/*
HB_OT_META_APPL = HB_TAG ('a','p','p','l'),
HB_OT_META_BILD = HB_TAG ('b','i','l','d'),
*/
HB_OT_META_DESIGN_LANGUAGES = HB_TAG ('d','l','n','g'),
HB_OT_META_SUPPORTED_LANGUAGES= HB_TAG ('s','l','n','g'),
_HB_OT_META_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_meta_tag_t;
HB_EXTERN unsigned int
hb_ot_meta_get_entries (hb_face_t *face,
unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT. May be NULL. */
hb_ot_meta_tag_t *entries /* OUT. May be NULL. */);
HB_EXTERN hb_blob_t *
hb_ot_meta_reference_entry (hb_face_t *face, hb_ot_meta_tag_t meta_tag);
HB_END_DECLS
#endif /* HB_OT_META_H */

231
src/hb-ot-metrics.cc Normal file
View File

@ -0,0 +1,231 @@
/*
* 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_tag_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_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */)
{
hb_face_t *face = font->face;
switch ((unsigned) 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_tag_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
/* Private tags for https://github.com/harfbuzz/harfbuzz/issues/1866 */
#define _HB_OT_METRICS_HORIZONTAL_ASCENDER_OS2 HB_TAG ('O','a','s','c')
#define _HB_OT_METRICS_HORIZONTAL_ASCENDER_HHEA HB_TAG ('H','a','s','c')
#define _HB_OT_METRICS_HORIZONTAL_DESCENDER_OS2 HB_TAG ('O','d','s','c')
#define _HB_OT_METRICS_HORIZONTAL_DESCENDER_HHEA HB_TAG ('H','d','s','c')
#define _HB_OT_METRICS_HORIZONTAL_LINE_GAP_OS2 HB_TAG ('O','l','g','p')
#define _HB_OT_METRICS_HORIZONTAL_LINE_GAP_HHEA HB_TAG ('H','l','g','p')
/**
* 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_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */)
{
hb_face_t *face = font->face;
switch ((unsigned) 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);
/* Private tags */
case _HB_OT_METRICS_HORIZONTAL_ASCENDER_OS2: return GET_METRIC_Y (OS2, sTypoAscender);
case _HB_OT_METRICS_HORIZONTAL_ASCENDER_HHEA: return GET_METRIC_Y (hhea, ascender);
case _HB_OT_METRICS_HORIZONTAL_DESCENDER_OS2: return GET_METRIC_Y (OS2, sTypoDescender);
case _HB_OT_METRICS_HORIZONTAL_DESCENDER_HHEA: return GET_METRIC_Y (hhea, descender);
case _HB_OT_METRICS_HORIZONTAL_LINE_GAP_OS2: return GET_METRIC_Y (OS2, sTypoLineGap);
case _HB_OT_METRICS_HORIZONTAL_LINE_GAP_HHEA: return GET_METRIC_Y (hhea, lineGap);
#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_tag_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_tag_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_tag_t metrics_tag)
{
return font->em_scalef_y (hb_ot_metrics_get_variation (font, metrics_tag));
}
#endif
#endif

94
src/hb-ot-metrics.h Normal file
View File

@ -0,0 +1,94 @@
/*
* 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 <hb-ot.h> 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_tag_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_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_metrics_tag_t;
HB_EXTERN hb_bool_t
hb_ot_metrics_get_position (hb_font_t *font,
hb_ot_metrics_tag_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_tag_t metrics_tag);
HB_EXTERN hb_position_t
hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
HB_EXTERN hb_position_t
hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
HB_END_DECLS
#endif /* HB_OT_METRICS_H */

35
src/hb-ot-metrics.hh Normal file
View File

@ -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_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */);
#endif /* HB_OT_METRICS_HH */

View File

@ -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);
@ -115,7 +119,7 @@ struct OS2
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 use_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
enum width_class_t {
FWIDTH_ULTRA_CONDENSED = 1, /* 50% */
@ -199,6 +203,7 @@ struct OS2
*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); }

View File

@ -178,6 +178,8 @@ struct post
return false;
}
hb_blob_ptr_t<post> table;
protected:
unsigned int get_glyph_count () const
@ -237,7 +239,6 @@ struct post
}
private:
hb_blob_ptr_t<post> table;
uint32_t version;
const ArrayOf<HBUINT16> *glyphNameIndex;
hb_vector_t<uint32_t> index_to_offset;
@ -245,6 +246,8 @@ struct post
hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
};
bool has_data () const { return version.to_int (); }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);

View File

@ -129,9 +129,8 @@ struct index_map_subset_plan_t
};
void init (const DeltaSetIndexMap &index_map,
unsigned int im_index,
hb_inc_bimap_t &outer_map,
hb_vector_t<hb_inc_bimap_t> &inner_maps,
hb_vector_t<hb_set_t *> &inner_sets,
const hb_subset_plan_t *plan)
{
map_count = 0;
@ -140,36 +139,27 @@ struct index_map_subset_plan_t
max_inners.init ();
output_map.init ();
if (&index_map == &Null(DeltaSetIndexMap))
{
/* Advance width index map is required. If its offset is missing,
* treat it as an indentity map. */
if (im_index == ADV_INDEX)
{
outer_map.add (0);
for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
{
hb_codepoint_t old_gid = gid;
(void)plan->old_gid_for_new_gid (gid, &old_gid);
inner_maps[0].add (old_gid);
}
}
return;
}
if (&index_map == &Null(DeltaSetIndexMap)) return;
unsigned int last_val = (unsigned int)-1;
hb_codepoint_t last_gid = (hb_codepoint_t)-1;
hb_codepoint_t gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ());
outer_bit_count = (index_map.get_width () * 8) - index_map.get_inner_bit_count ();
max_inners.resize (inner_maps.length);
for (unsigned i = 0; i < inner_maps.length; i++) max_inners[i] = 0;
max_inners.resize (inner_sets.length);
for (unsigned i = 0; i < inner_sets.length; i++) max_inners[i] = 0;
/* Search backwards for a map value different from the last map value */
for (; gid > 0; gid--)
{
hb_codepoint_t old_gid = gid - 1;
(void)plan->old_gid_for_new_gid (gid - 1, &old_gid);
hb_codepoint_t old_gid;
if (!plan->old_gid_for_new_gid (gid - 1, &old_gid))
{
if (last_gid == (hb_codepoint_t)-1)
continue;
else
break;
}
unsigned int v = index_map.map (old_gid);
if (last_gid == (hb_codepoint_t)-1)
@ -187,14 +177,16 @@ struct index_map_subset_plan_t
map_count = last_gid;
for (gid = 0; gid < map_count; gid++)
{
hb_codepoint_t old_gid = gid;
(void)plan->old_gid_for_new_gid (gid, &old_gid);
hb_codepoint_t old_gid;
if (plan->old_gid_for_new_gid (gid, &old_gid))
{
unsigned int v = index_map.map (old_gid);
unsigned int outer = v >> 16;
unsigned int inner = v & 0xFFFF;
outer_map.add (outer);
if (inner > max_inners[outer]) max_inners[outer] = inner;
inner_maps[outer].add (inner);
hb_set_add (inner_sets[outer], inner);
}
}
}
@ -209,10 +201,7 @@ struct index_map_subset_plan_t
const hb_vector_t<hb_inc_bimap_t> &inner_maps,
const hb_subset_plan_t *plan)
{
/* Leave output_map empty for an identity map */
/* TODO: if retain_gids, convert identity to a customized map, or not subset varstore? */
if (input_map == &Null(DeltaSetIndexMap))
return;
if (input_map == &Null(DeltaSetIndexMap)) return;
for (unsigned int i = 0; i < max_inners.length; i++)
{
@ -224,12 +213,16 @@ struct index_map_subset_plan_t
output_map.resize (map_count);
for (hb_codepoint_t gid = 0; gid < output_map.length; gid++)
{
hb_codepoint_t old_gid = gid;
(void)plan->old_gid_for_new_gid (gid, &old_gid);
hb_codepoint_t old_gid;
if (plan->old_gid_for_new_gid (gid, &old_gid))
{
unsigned int v = input_map->map (old_gid);
unsigned int outer = v >> 16;
output_map[gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]);
}
else
output_map[gid] = 0; /* Map unused glyph to outer/inner=0/0 */
}
}
unsigned int get_inner_bit_count () const { return inner_bit_count; }
@ -264,17 +257,53 @@ struct hvarvvar_subset_plan_t
index_map_plans.resize (index_maps.length);
var_store = &_var_store;
inner_sets.resize (var_store->get_sub_table_count ());
for (unsigned int i = 0; i < inner_sets.length; i++)
inner_sets[i] = hb_set_create ();
adv_set = hb_set_create ();
inner_maps.resize (var_store->get_sub_table_count ());
for (unsigned int i = 0; i < inner_maps.length; i++)
inner_maps[i].init ();
for (unsigned int i = 0; i < index_maps.length; i++)
index_map_plans[i].init (*index_maps[i], i, outer_map, inner_maps, plan);
bool retain_adv_map = false;
index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan);
if (index_maps[0] == &Null(DeltaSetIndexMap))
{
retain_adv_map = plan->retain_gids;
outer_map.add (0);
for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
{
hb_codepoint_t old_gid;
if (plan->old_gid_for_new_gid (gid, &old_gid))
hb_set_add (inner_sets[0], old_gid);
}
hb_set_union (adv_set, inner_sets[0]);
}
for (unsigned int i = 1; i < index_maps.length; i++)
index_map_plans[i].init (*index_maps[i], outer_map, inner_sets, plan);
outer_map.sort ();
for (unsigned int i = 0; i < inner_maps.length; i++)
if (inner_maps[i].get_population () > 0) inner_maps[i].sort ();
if (retain_adv_map)
{
for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
if (hb_set_has (inner_sets[0], gid))
inner_maps[0].add (gid);
else
inner_maps[0].skip ();
}
else
{
inner_maps[0].add_set (adv_set);
hb_set_subtract (inner_sets[0], adv_set);
inner_maps[0].add_set (inner_sets[0]);
}
for (unsigned int i = 1; i < inner_maps.length; i++)
inner_maps[i].add_set (inner_sets[i]);
for (unsigned int i = 0; i < index_maps.length; i++)
index_map_plans[i].remap (index_maps[i], outer_map, inner_maps, plan);
@ -282,6 +311,9 @@ struct hvarvvar_subset_plan_t
void fini ()
{
for (unsigned int i = 0; i < inner_sets.length; i++)
hb_set_destroy (inner_sets[i]);
hb_set_destroy (adv_set);
inner_maps.fini_deep ();
index_map_plans.fini_deep ();
}
@ -291,6 +323,10 @@ struct hvarvvar_subset_plan_t
hb_vector_t<index_map_subset_plan_t>
index_map_plans;
const VariationStore *var_store;
protected:
hb_vector_t<hb_set_t *> inner_sets;
hb_set_t *adv_set;
};
/*

View File

@ -68,7 +68,7 @@ hb_ot_var_get_axis_count (hb_face_t *face);
typedef enum { /*< flags >*/
HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x00000001u,
_HB_OT_VAR_AXIS_FLAG_MAX_VALUE= 0x7FFFFFFFu /*< skip >*/
_HB_OT_VAR_AXIS_FLAG_MAX_VALUE= HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_var_axis_flags_t;
/**

View File

@ -35,6 +35,8 @@
#include "hb-ot-font.h"
#include "hb-ot-layout.h"
#include "hb-ot-math.h"
#include "hb-ot-meta.h"
#include "hb-ot-metrics.h"
#include "hb-ot-name.h"
#include "hb-ot-shape.h"
#include "hb-ot-var.h"

View File

@ -179,7 +179,7 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
unsigned max_glyph =
+ hb_iter (all_gids_to_retain)
| hb_reduce (hb_max, 0)
| hb_reduce (hb_max, 0u)
;
*num_glyphs = max_glyph + 1;
}

View File

@ -126,8 +126,12 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED
}
#endif
extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs ();
extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs ();
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_GLIB)
#include "hb-glib.h"
#endif
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
#include "hb-icu.h"
#endif
hb_unicode_funcs_t *
hb_unicode_funcs_get_default ()

View File

@ -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;

View File

@ -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,
@ -245,8 +238,9 @@ struct hb_uniscribe_shaper_funcs_t
}
};
#if HB_USE_ATEXIT
static void free_static_uniscribe_shaper_funcs ();
#endif
static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_uniscribe_shaper_funcs_t,
hb_uniscribe_shaper_funcs_lazy_loader_t>

View File

@ -98,6 +98,7 @@
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
#pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
#pragma GCC diagnostic warning "-Wdeprecated"
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
#pragma GCC diagnostic warning "-Wdisabled-optimization"
#pragma GCC diagnostic warning "-Wdouble-promotion"
#pragma GCC diagnostic warning "-Wformat=2"
@ -317,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")))
@ -475,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.

70
src/test-ot-meta.cc Normal file
View File

@ -0,0 +1,70 @@
/*
* 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"
#include "hb-ot.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef HB_NO_OPEN
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
#endif
int
main (int argc, char **argv)
{
if (argc != 2) {
fprintf (stderr, "usage: %s font-file\n", argv[0]);
exit (1);
}
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
hb_face_t *face = hb_face_create (blob, 0 /* first face */);
hb_blob_destroy (blob);
blob = nullptr;
unsigned int count = 0;
#ifndef HB_NO_META
count = hb_ot_meta_get_entries (face, 0, nullptr, nullptr);
hb_ot_meta_tag_t *tags = (hb_ot_meta_tag_t *)
malloc (sizeof (hb_ot_meta_tag_t) * count);
hb_ot_meta_get_entries (face, 0, &count, tags);
for (unsigned i = 0; i < count; ++i)
{
hb_blob_t *entry = hb_ot_meta_reference_entry (face, tags[i]);
printf ("%c%c%c%c, size: %d: %.*s\n",
HB_UNTAG (tags[i]), hb_blob_get_length (entry),
hb_blob_get_length (entry), hb_blob_get_data (entry, nullptr));
hb_blob_destroy (entry);
}
free (tags);
#endif
hb_face_destroy (face);
return !count;
}

View File

@ -90,6 +90,8 @@ TEST_PROGS += \
test-ot-color \
test-ot-ligature-carets \
test-ot-name \
test-ot-meta \
test-ot-metrics \
test-ot-tag \
test-ot-extents-cff \
test-ot-metrics-tt-var \

Binary file not shown.

BIN
test/api/fonts/meta.ttf Normal file

Binary file not shown.

View File

@ -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);

84
test/api/test-ot-meta.c Normal file
View File

@ -0,0 +1,84 @@
/*
* 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-test.h"
#include <hb-ot.h>
/* Unit tests for hb-ot-meta.h */
static void
test_ot_meta_get_entries (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/meta.ttf");
hb_ot_meta_tag_t entries[2];
unsigned int entries_count = 2;
g_assert_cmpint (hb_ot_meta_get_entries (face, 0, &entries_count, entries), ==, 5);
g_assert_cmpint (entries_count, ==, 2);
g_assert_cmpint (entries[0], ==, HB_TAG ('a','p','p','l'));
g_assert_cmpint (entries[1], ==, HB_TAG ('b','i','l','d'));
entries_count = 1;
g_assert_cmpint (hb_ot_meta_get_entries (face, 2, &entries_count, entries), ==, 5);
g_assert_cmpint (entries_count, ==, 1);
g_assert_cmpint (entries[0], ==, HB_TAG ('d','l','n','g'));
entries_count = 2;
g_assert_cmpint (hb_ot_meta_get_entries (face, 4, &entries_count, entries), ==, 5);
g_assert_cmpint (entries_count, ==, 1);
g_assert_cmpint (entries[0], ==, HB_TAG ('s','l','n','g'));
hb_face_destroy (face);
}
static void
test_ot_meta_reference_entry (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/meta.ttf");
hb_blob_t *dlng = hb_ot_meta_reference_entry (face, HB_OT_META_DESIGN_LANGUAGES);
g_assert_cmpint (hb_blob_get_length (dlng), ==, 8);
g_assert_cmpmem (hb_blob_get_data (dlng, NULL), 8, "ar,de,fa", 8);
hb_blob_destroy (dlng);
hb_blob_t *fslf = hb_ot_meta_reference_entry (face, (hb_ot_meta_tag_t) HB_TAG ('f','s','l','f'));
g_assert_cmpint (hb_blob_get_length (fslf), ==, 12);
hb_blob_destroy (fslf);
hb_blob_t *nacl = hb_ot_meta_reference_entry (face, (hb_ot_meta_tag_t) HB_TAG ('n','a','c','l'));
g_assert_cmpint (hb_blob_get_length (nacl), ==, 0);
hb_blob_destroy (nacl);
hb_blob_t *slng = hb_ot_meta_reference_entry (face, HB_OT_META_SUPPORTED_LANGUAGES);
g_assert_cmpint (hb_blob_get_length (slng), ==, 11);
g_assert_cmpmem (hb_blob_get_data (slng, NULL), 11, "ar,de,en,fa", 11);
hb_blob_destroy (slng);
hb_face_destroy (face);
}
int
main (int argc, char **argv)
{
hb_test_init (&argc, &argv);
hb_test_add (test_ot_meta_get_entries);
hb_test_add (test_ot_meta_reference_entry);
return hb_test_run ();
}

View File

@ -0,0 +1,78 @@
/*
* 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 <hb-ot.h>
#include <math.h>
/* Unit tests for hb-ot-metrics.h */
static void
test_ot_metrics_get_no_var (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 (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_X_HEIGHT), ==, 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);
}
static void
test_ot_metrics_get_var (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/TestCFF2VF.otf");
hb_font_t *font = hb_font_create (face);
hb_position_t value;
g_assert (hb_ot_metrics_get_position (font, HB_OT_METRICS_X_HEIGHT, &value));
g_assert_cmpint (value, ==, 486);
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 (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_X_HEIGHT), ==, 0);
float coords[] = {100.f};
hb_font_set_var_coords_design (font, coords, 1);
g_assert (hb_ot_metrics_get_position (font, HB_OT_METRICS_X_HEIGHT, &value));
g_assert_cmpint (value, ==, 478);
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 (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_X_HEIGHT), ==, -8);
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_no_var);
hb_test_add (test_ot_metrics_get_var);
return hb_test_run ();
}

View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "hb-subset.h"
@ -32,6 +33,19 @@ trySubset (hb_face_t *face,
}
hb_face_t *result = hb_subset (face, input);
{
hb_blob_t *blob = hb_face_reference_blob (result);
unsigned int length;
const char *data = hb_blob_get_data (blob, &length);
// Something not optimizable just to access all the blob data
unsigned int bytes_count = 0;
for (unsigned int i = 0; i < length; ++i)
if (data[i]) ++bytes_count;
assert (bytes_count || !length);
hb_blob_destroy (blob);
}
hb_face_destroy (result);
hb_subset_input_destroy (input);

View File

@ -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:

View File

@ -33,7 +33,7 @@ def cmd(command):
def timeout(p, is_killed):
is_killed['value'] = True
p.kill()
timer = threading.Timer (2, timeout, [p, is_killed])
timer = threading.Timer (8, timeout, [p, is_killed])
try:
timer.start()
@ -82,6 +82,8 @@ def run_dir (parent_path):
global fails
for file in os.listdir (parent_path):
path = os.path.join(parent_path, file)
# TODO: Run on all the fonts not just subset related ones
if "subset" not in path: continue
print ("running subset fuzzer against %s" % path)
if valgrind:
@ -91,7 +93,7 @@ def run_dir (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:
@ -100,8 +102,7 @@ def run_dir (parent_path):
run_dir (os.path.join (srcdir, "..", "subset", "data", "fonts"))
# TODO running these tests very slow tests. Fix and re-enable
#run_dir (os.path.join (srcdir, "fonts"))
run_dir (os.path.join (srcdir, "fonts"))
if fails:
print ("%i subset fuzzer related tests failed." % fails)

View File

@ -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>]

View File

@ -15,3 +15,4 @@ b
c
ac
a
*

View File

@ -67,7 +67,7 @@ def run_test (test, should_check_ots):
"--font-file=" + test.font_path,
"--output-file=" + out_file,
"--unicodes=%s" % test.unicodes (),
"--drop-tables+=DSIG,GPOS,GSUB,GDEF,HVAR,VVAR,gvar"]
"--drop-tables+=DSIG,GPOS,GSUB,GDEF"]
cli_args.extend (test.get_profile_flags ())
print (' '.join (cli_args))
_, return_code = cmd (cli_args)

Some files were not shown because too many files have changed in this diff Show More