Merge pull request #3411 from harfbuzz/draw
[draw] Finish and release draw API
This commit is contained in:
commit
a396543ae1
|
@ -3,7 +3,6 @@ set -e
|
||||||
|
|
||||||
meson --cross-file=.ci/win32-cross-file.txt \
|
meson --cross-file=.ci/win32-cross-file.txt \
|
||||||
--wrap-mode=forcefallback \
|
--wrap-mode=forcefallback \
|
||||||
--buildtype=release \
|
|
||||||
-Dtests=disabled \
|
-Dtests=disabled \
|
||||||
-Dcairo=enabled \
|
-Dcairo=enabled \
|
||||||
-Dcairo:fontconfig=disabled \
|
-Dcairo:fontconfig=disabled \
|
||||||
|
|
|
@ -3,7 +3,6 @@ set -e
|
||||||
|
|
||||||
meson --cross-file=.ci/win64-cross-file.txt \
|
meson --cross-file=.ci/win64-cross-file.txt \
|
||||||
--wrap-mode=forcefallback \
|
--wrap-mode=forcefallback \
|
||||||
--buildtype=release \
|
|
||||||
-Dtests=disabled \
|
-Dtests=disabled \
|
||||||
-Dcairo=enabled \
|
-Dcairo=enabled \
|
||||||
-Dcairo:fontconfig=disabled \
|
-Dcairo:fontconfig=disabled \
|
||||||
|
|
|
@ -194,6 +194,10 @@ AC_ARG_WITH(cairo,
|
||||||
have_cairo=false
|
have_cairo=false
|
||||||
if test "x$with_cairo" = "xyes" -o "x$with_cairo" = "xauto"; then
|
if test "x$with_cairo" = "xyes" -o "x$with_cairo" = "xauto"; then
|
||||||
PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, :)
|
PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, :)
|
||||||
|
save_libs=$LIBS
|
||||||
|
LIBS="$LIBS $CAIRO_LIBS"
|
||||||
|
AC_CHECK_FUNCS(cairo_user_font_face_set_render_color_glyph_func)
|
||||||
|
LIBS=$save_libs
|
||||||
fi
|
fi
|
||||||
if test "x$with_cairo" = "xyes" -a "x$have_cairo" != "xtrue"; then
|
if test "x$with_cairo" = "xyes" -a "x$have_cairo" != "xtrue"; then
|
||||||
AC_MSG_ERROR([cairo support requested but not found])
|
AC_MSG_ERROR([cairo support requested but not found])
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
<xi:include href="xml/hb-blob.xml"/>
|
<xi:include href="xml/hb-blob.xml"/>
|
||||||
<xi:include href="xml/hb-buffer.xml"/>
|
<xi:include href="xml/hb-buffer.xml"/>
|
||||||
<xi:include href="xml/hb-common.xml"/>
|
<xi:include href="xml/hb-common.xml"/>
|
||||||
|
<xi:include href="xml/hb-draw.xml"/>
|
||||||
<xi:include href="xml/hb-deprecated.xml"/>
|
<xi:include href="xml/hb-deprecated.xml"/>
|
||||||
<xi:include href="xml/hb-face.xml"/>
|
<xi:include href="xml/hb-face.xml"/>
|
||||||
<xi:include href="xml/hb-font.xml"/>
|
<xi:include href="xml/hb-font.xml"/>
|
||||||
|
|
|
@ -169,6 +169,7 @@ HB_FEATURE_GLOBAL_START
|
||||||
HB_BEGIN_DECLS
|
HB_BEGIN_DECLS
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
hb_var_int_t
|
hb_var_int_t
|
||||||
|
hb_var_num_t
|
||||||
int16_t
|
int16_t
|
||||||
int32_t
|
int32_t
|
||||||
int64_t
|
int64_t
|
||||||
|
@ -183,6 +184,33 @@ HB_DEPRECATED
|
||||||
HB_DEPRECATED_FOR
|
HB_DEPRECATED_FOR
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>hb-draw</FILE>
|
||||||
|
hb_draw_funcs_t
|
||||||
|
hb_draw_funcs_create
|
||||||
|
hb_draw_funcs_destroy
|
||||||
|
hb_draw_funcs_reference
|
||||||
|
hb_draw_funcs_is_immutable
|
||||||
|
hb_draw_funcs_make_immutable
|
||||||
|
hb_draw_move_to_func_t
|
||||||
|
hb_draw_funcs_set_move_to_func
|
||||||
|
hb_draw_line_to_func_t
|
||||||
|
hb_draw_funcs_set_line_to_func
|
||||||
|
hb_draw_quadratic_to_func_t
|
||||||
|
hb_draw_funcs_set_quadratic_to_func
|
||||||
|
hb_draw_cubic_to_func_t
|
||||||
|
hb_draw_funcs_set_cubic_to_func
|
||||||
|
hb_draw_close_path_func_t
|
||||||
|
hb_draw_funcs_set_close_path_func
|
||||||
|
hb_draw_state_t
|
||||||
|
HB_DRAW_STATE_DEFAULT
|
||||||
|
hb_draw_move_to
|
||||||
|
hb_draw_line_to
|
||||||
|
hb_draw_quadratic_to
|
||||||
|
hb_draw_cubic_to
|
||||||
|
hb_draw_close_path
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-deprecated</FILE>
|
<FILE>hb-deprecated</FILE>
|
||||||
HB_BUFFER_FLAGS_DEFAULT
|
HB_BUFFER_FLAGS_DEFAULT
|
||||||
|
@ -281,6 +309,7 @@ hb_font_funcs_set_glyph_h_advances_func
|
||||||
hb_font_funcs_set_glyph_h_kerning_func
|
hb_font_funcs_set_glyph_h_kerning_func
|
||||||
hb_font_funcs_set_glyph_h_origin_func
|
hb_font_funcs_set_glyph_h_origin_func
|
||||||
hb_font_funcs_set_glyph_name_func
|
hb_font_funcs_set_glyph_name_func
|
||||||
|
hb_font_funcs_set_glyph_shape_func
|
||||||
hb_font_funcs_set_glyph_v_advance_func
|
hb_font_funcs_set_glyph_v_advance_func
|
||||||
hb_font_funcs_set_glyph_v_advances_func
|
hb_font_funcs_set_glyph_v_advances_func
|
||||||
hb_font_funcs_set_glyph_v_origin_func
|
hb_font_funcs_set_glyph_v_origin_func
|
||||||
|
@ -318,6 +347,8 @@ hb_font_get_glyph_name
|
||||||
hb_font_get_glyph_name_func_t
|
hb_font_get_glyph_name_func_t
|
||||||
hb_font_get_glyph_origin_for_direction
|
hb_font_get_glyph_origin_for_direction
|
||||||
hb_font_get_glyph_origin_func_t
|
hb_font_get_glyph_origin_func_t
|
||||||
|
hb_font_get_glyph_shape
|
||||||
|
hb_font_get_glyph_shape_func_t
|
||||||
hb_font_get_glyph_v_advance
|
hb_font_get_glyph_v_advance
|
||||||
hb_font_get_glyph_v_advance_func_t
|
hb_font_get_glyph_v_advance_func_t
|
||||||
hb_font_get_glyph_v_advances
|
hb_font_get_glyph_v_advances
|
||||||
|
|
|
@ -186,6 +186,11 @@ endif
|
||||||
|
|
||||||
if cairo_dep.found()
|
if cairo_dep.found()
|
||||||
conf.set('HAVE_CAIRO', 1)
|
conf.set('HAVE_CAIRO', 1)
|
||||||
|
if cairo_dep.type_name() == 'internal'
|
||||||
|
conf.set('HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC', 1)
|
||||||
|
else
|
||||||
|
check_funcs += [['cairo_user_font_face_set_render_color_glyph_func', {'deps': cairo_dep}]]
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if cairo_ft_dep.found()
|
if cairo_ft_dep.found()
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
#ifdef HAVE_FREETYPE
|
#ifdef HAVE_FREETYPE
|
||||||
enum backend_t { HARFBUZZ, FREETYPE, TTF_PARSER };
|
enum backend_t { HARFBUZZ, FREETYPE, TTF_PARSER };
|
||||||
#include "perf-extents.hh"
|
#include "perf-extents.hh"
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
#include "perf-draw.hh"
|
#include "perf-draw.hh"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
BENCHMARK_MAIN ();
|
BENCHMARK_MAIN ();
|
||||||
|
|
|
@ -19,23 +19,7 @@ symbols = sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re
|
||||||
if '--experimental-api' not in sys.argv:
|
if '--experimental-api' not in sys.argv:
|
||||||
# Move these to harfbuzz-sections.txt when got stable
|
# Move these to harfbuzz-sections.txt when got stable
|
||||||
experimental_symbols = \
|
experimental_symbols = \
|
||||||
"""hb_font_draw_glyph
|
"""""".splitlines ()
|
||||||
hb_draw_funcs_t
|
|
||||||
hb_draw_close_path_func_t
|
|
||||||
hb_draw_cubic_to_func_t
|
|
||||||
hb_draw_line_to_func_t
|
|
||||||
hb_draw_move_to_func_t
|
|
||||||
hb_draw_quadratic_to_func_t
|
|
||||||
hb_draw_funcs_create
|
|
||||||
hb_draw_funcs_destroy
|
|
||||||
hb_draw_funcs_is_immutable
|
|
||||||
hb_draw_funcs_make_immutable
|
|
||||||
hb_draw_funcs_reference
|
|
||||||
hb_draw_funcs_set_close_path_func
|
|
||||||
hb_draw_funcs_set_cubic_to_func
|
|
||||||
hb_draw_funcs_set_line_to_func
|
|
||||||
hb_draw_funcs_set_move_to_func
|
|
||||||
hb_draw_funcs_set_quadratic_to_func""".splitlines ()
|
|
||||||
symbols = [x for x in symbols if x not in experimental_symbols]
|
symbols = [x for x in symbols if x not in experimental_symbols]
|
||||||
symbols = "\n".join (symbols)
|
symbols = "\n".join (symbols)
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,16 @@ typedef union _hb_var_int_t {
|
||||||
int8_t i8[4];
|
int8_t i8[4];
|
||||||
} hb_var_int_t;
|
} hb_var_int_t;
|
||||||
|
|
||||||
|
typedef union _hb_var_num_t {
|
||||||
|
float f;
|
||||||
|
uint32_t u32;
|
||||||
|
int32_t i32;
|
||||||
|
uint16_t u16[2];
|
||||||
|
int16_t i16[2];
|
||||||
|
uint8_t u8[4];
|
||||||
|
int8_t i8[4];
|
||||||
|
} hb_var_num_t;
|
||||||
|
|
||||||
|
|
||||||
/* hb_tag_t */
|
/* hb_tag_t */
|
||||||
|
|
||||||
|
|
392
src/hb-draw.cc
392
src/hb-draw.cc
|
@ -25,237 +25,313 @@
|
||||||
#include "hb.hh"
|
#include "hb.hh"
|
||||||
|
|
||||||
#ifndef HB_NO_DRAW
|
#ifndef HB_NO_DRAW
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
|
|
||||||
#include "hb-draw.hh"
|
#include "hb-draw.hh"
|
||||||
#include "hb-ot.h"
|
|
||||||
#include "hb-ot-glyf-table.hh"
|
|
||||||
#include "hb-ot-cff1-table.hh"
|
|
||||||
#include "hb-ot-cff2-table.hh"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_draw_funcs_set_move_to_func:
|
* SECTION:hb-draw
|
||||||
* @funcs: draw functions object
|
* @title: hb-draw
|
||||||
* @move_to: move-to callback
|
* @short_description: Glyph drawing
|
||||||
|
* @include: hb.h
|
||||||
*
|
*
|
||||||
* Sets move-to callback to the draw functions object.
|
* Functions for drawing (extracting) glyph shapes.
|
||||||
*
|
|
||||||
* Since: EXPERIMENTAL
|
|
||||||
**/
|
**/
|
||||||
void
|
|
||||||
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
|
|
||||||
hb_draw_move_to_func_t move_to)
|
|
||||||
{
|
|
||||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
|
||||||
funcs->move_to = move_to;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
static void
|
||||||
* hb_draw_funcs_set_line_to_func:
|
hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
|
||||||
* @funcs: draw functions object
|
hb_draw_state_t *st HB_UNUSED,
|
||||||
* @line_to: line-to callback
|
float to_x HB_UNUSED, float to_y HB_UNUSED,
|
||||||
*
|
void *user_data HB_UNUSED) {}
|
||||||
* Sets line-to callback to the draw functions object.
|
|
||||||
*
|
|
||||||
* Since: EXPERIMENTAL
|
|
||||||
**/
|
|
||||||
void
|
|
||||||
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
|
|
||||||
hb_draw_line_to_func_t line_to)
|
|
||||||
{
|
|
||||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
|
||||||
funcs->line_to = line_to;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
static void
|
||||||
* hb_draw_funcs_set_quadratic_to_func:
|
hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
|
||||||
* @funcs: draw functions object
|
hb_draw_state_t *st HB_UNUSED,
|
||||||
* @move_to: quadratic-to callback
|
float to_x HB_UNUSED, float to_y HB_UNUSED,
|
||||||
*
|
void *user_data HB_UNUSED) {}
|
||||||
* Sets quadratic-to callback to the draw functions object.
|
|
||||||
*
|
|
||||||
* Since: EXPERIMENTAL
|
|
||||||
**/
|
|
||||||
void
|
|
||||||
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
|
|
||||||
hb_draw_quadratic_to_func_t quadratic_to)
|
|
||||||
{
|
|
||||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
|
||||||
funcs->quadratic_to = quadratic_to;
|
|
||||||
funcs->is_quadratic_to_set = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
static void
|
||||||
* hb_draw_funcs_set_cubic_to_func:
|
hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
* @funcs: draw functions
|
hb_draw_state_t *st,
|
||||||
* @cubic_to: cubic-to callback
|
float control_x, float control_y,
|
||||||
*
|
float to_x, float to_y,
|
||||||
* Sets cubic-to callback to the draw functions object.
|
void *user_data HB_UNUSED)
|
||||||
*
|
|
||||||
* Since: EXPERIMENTAL
|
|
||||||
**/
|
|
||||||
void
|
|
||||||
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
|
|
||||||
hb_draw_cubic_to_func_t cubic_to)
|
|
||||||
{
|
{
|
||||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
dfuncs->emit_cubic_to (draw_data, *st,
|
||||||
funcs->cubic_to = cubic_to;
|
(st->current_x + 2.f * control_x) / 3.f,
|
||||||
}
|
(st->current_y + 2.f * control_y) / 3.f,
|
||||||
|
(to_x + 2.f * control_x) / 3.f,
|
||||||
/**
|
(to_y + 2.f * control_y) / 3.f,
|
||||||
* hb_draw_funcs_set_close_path_func:
|
to_x, to_y);
|
||||||
* @funcs: draw functions object
|
|
||||||
* @close_path: close-path callback
|
|
||||||
*
|
|
||||||
* Sets close-path callback to the draw functions object.
|
|
||||||
*
|
|
||||||
* Since: EXPERIMENTAL
|
|
||||||
**/
|
|
||||||
void
|
|
||||||
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
|
|
||||||
hb_draw_close_path_func_t close_path)
|
|
||||||
{
|
|
||||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
|
||||||
funcs->close_path = close_path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
|
hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
|
||||||
|
hb_draw_state_t *st HB_UNUSED,
|
||||||
|
float control1_x HB_UNUSED, float control1_y HB_UNUSED,
|
||||||
|
float control2_x HB_UNUSED, float control2_y HB_UNUSED,
|
||||||
|
float to_x HB_UNUSED, float to_y HB_UNUSED,
|
||||||
|
void *user_data HB_UNUSED) {}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
|
hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
|
||||||
|
hb_draw_state_t *st HB_UNUSED,
|
||||||
|
void *user_data HB_UNUSED) {}
|
||||||
|
|
||||||
static void
|
|
||||||
_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
|
|
||||||
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
|
|
||||||
void *user_data HB_UNUSED) {}
|
|
||||||
|
|
||||||
static void
|
#define HB_DRAW_FUNC_IMPLEMENT(name) \
|
||||||
_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
|
\
|
||||||
hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
|
void \
|
||||||
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
|
hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \
|
||||||
void *user_data HB_UNUSED) {}
|
hb_draw_##name##_func_t func, \
|
||||||
|
void *user_data, \
|
||||||
|
hb_destroy_func_t destroy) \
|
||||||
|
{ \
|
||||||
|
if (hb_object_is_immutable (dfuncs)) \
|
||||||
|
return; \
|
||||||
|
\
|
||||||
|
if (dfuncs->destroy.name) \
|
||||||
|
dfuncs->destroy.name (dfuncs->user_data.name); \
|
||||||
|
\
|
||||||
|
if (func) { \
|
||||||
|
dfuncs->func.name = func; \
|
||||||
|
dfuncs->user_data.name = user_data; \
|
||||||
|
dfuncs->destroy.name = destroy; \
|
||||||
|
} else { \
|
||||||
|
dfuncs->func.name = hb_draw_##name##_nil; \
|
||||||
|
dfuncs->user_data.name = nullptr; \
|
||||||
|
dfuncs->destroy.name = nullptr; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
_close_path_nil (void *user_data HB_UNUSED) {}
|
#undef HB_DRAW_FUNC_IMPLEMENT
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_draw_funcs_create:
|
* hb_draw_funcs_create: (Xconstructor)
|
||||||
*
|
*
|
||||||
* Creates a new draw callbacks object.
|
* Creates a new draw callbacks object.
|
||||||
*
|
*
|
||||||
* Since: EXPERIMENTAL
|
* Return value: (transfer full):
|
||||||
|
* A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
|
||||||
|
* reference count should be released with hb_draw_funcs_destroy when you are
|
||||||
|
* done using the #hb_draw_funcs_t. This function never returns %NULL. If
|
||||||
|
* memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
|
||||||
|
* be returned.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
**/
|
**/
|
||||||
hb_draw_funcs_t *
|
hb_draw_funcs_t *
|
||||||
hb_draw_funcs_create ()
|
hb_draw_funcs_create ()
|
||||||
{
|
{
|
||||||
hb_draw_funcs_t *funcs;
|
hb_draw_funcs_t *dfuncs;
|
||||||
if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ())))
|
if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ())))
|
||||||
return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
|
return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
|
||||||
|
|
||||||
funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil;
|
dfuncs->func = Null (hb_draw_funcs_t).func;
|
||||||
funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil;
|
|
||||||
funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil;
|
return dfuncs;
|
||||||
funcs->is_quadratic_to_set = false;
|
|
||||||
funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil;
|
|
||||||
funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil;
|
|
||||||
return funcs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
|
||||||
|
{
|
||||||
|
HB_OBJECT_HEADER_STATIC,
|
||||||
|
|
||||||
|
{
|
||||||
|
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
|
||||||
|
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
|
#undef HB_DRAW_FUNC_IMPLEMENT
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_draw_funcs_reference:
|
* hb_draw_funcs_reference: (skip)
|
||||||
* @funcs: draw functions
|
* @dfuncs: draw functions
|
||||||
*
|
*
|
||||||
* Add to callbacks object refcount.
|
* Increases the reference count on @dfuncs by one. This prevents @buffer from
|
||||||
|
* being destroyed until a matching call to hb_draw_funcs_destroy() is made.
|
||||||
*
|
*
|
||||||
* Returns: The same object.
|
* Return value: (transfer full):
|
||||||
* Since: EXPERIMENTAL
|
* The referenced #hb_draw_funcs_t.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
**/
|
**/
|
||||||
hb_draw_funcs_t *
|
hb_draw_funcs_t *
|
||||||
hb_draw_funcs_reference (hb_draw_funcs_t *funcs)
|
hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs)
|
||||||
{
|
{
|
||||||
return hb_object_reference (funcs);
|
return hb_object_reference (dfuncs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_draw_funcs_destroy:
|
* hb_draw_funcs_destroy: (skip)
|
||||||
* @funcs: draw functions
|
* @dfuncs: draw functions
|
||||||
*
|
*
|
||||||
* Decreases refcount of callbacks object and deletes the object if it reaches
|
* Deallocate the @dfuncs.
|
||||||
* to zero.
|
* Decreases the reference count on @dfuncs by one. If the result is zero, then
|
||||||
|
* @dfuncs and all associated resources are freed. See hb_draw_funcs_reference().
|
||||||
*
|
*
|
||||||
* Since: EXPERIMENTAL
|
* Since: REPLACEME
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
|
hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
|
||||||
{
|
{
|
||||||
if (!hb_object_destroy (funcs)) return;
|
if (!hb_object_destroy (dfuncs)) return;
|
||||||
|
|
||||||
hb_free (funcs);
|
#define HB_DRAW_FUNC_IMPLEMENT(name) \
|
||||||
|
if (dfuncs->destroy.name) dfuncs->destroy.name (dfuncs->user_data.name);
|
||||||
|
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
|
#undef HB_DRAW_FUNC_IMPLEMENT
|
||||||
|
|
||||||
|
|
||||||
|
hb_free (dfuncs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_draw_funcs_make_immutable:
|
* hb_draw_funcs_make_immutable:
|
||||||
* @funcs: draw functions
|
* @dfuncs: draw functions
|
||||||
*
|
*
|
||||||
* Makes funcs object immutable.
|
* Makes @dfuncs object immutable.
|
||||||
*
|
*
|
||||||
* Since: EXPERIMENTAL
|
* Since: REPLACEME
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs)
|
hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
|
||||||
{
|
{
|
||||||
if (hb_object_is_immutable (funcs))
|
if (hb_object_is_immutable (dfuncs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hb_object_make_immutable (funcs);
|
hb_object_make_immutable (dfuncs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_draw_funcs_is_immutable:
|
* hb_draw_funcs_is_immutable:
|
||||||
* @funcs: draw functions
|
* @dfuncs: draw functions
|
||||||
*
|
*
|
||||||
* Checks whether funcs is immutable.
|
* Checks whether @dfuncs is immutable.
|
||||||
*
|
*
|
||||||
* Returns: If is immutable.
|
* Return value: %true if @dfuncs is immutable, %false otherwise
|
||||||
* Since: EXPERIMENTAL
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
**/
|
**/
|
||||||
hb_bool_t
|
hb_bool_t
|
||||||
hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs)
|
hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs)
|
||||||
{
|
{
|
||||||
return hb_object_is_immutable (funcs);
|
return hb_object_is_immutable (dfuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_move_to:
|
||||||
|
* @dfuncs: draw functions
|
||||||
|
* @draw_data: associated draw data passed by the caller
|
||||||
|
* @st: current draw state
|
||||||
|
* @to_x: X component of target point
|
||||||
|
* @to_y: Y component of target point
|
||||||
|
*
|
||||||
|
* Perform a "move-to" draw operation.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y)
|
||||||
|
{
|
||||||
|
dfuncs->move_to (draw_data, *st,
|
||||||
|
to_x, to_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_font_draw_glyph:
|
* hb_draw_line_to:
|
||||||
* @font: a font object
|
* @dfuncs: draw functions
|
||||||
* @glyph: a glyph id
|
* @draw_data: associated draw data passed by the caller
|
||||||
* @funcs: draw callbacks object
|
* @st: current draw state
|
||||||
* @user_data: parameter you like be passed to the callbacks when are called
|
* @to_x: X component of target point
|
||||||
|
* @to_y: Y component of target point
|
||||||
*
|
*
|
||||||
* Draw a glyph.
|
* Perform a "line-to" draw operation.
|
||||||
*
|
*
|
||||||
* Returns: Whether the font had the glyph and the operation completed successfully.
|
* Since: REPLACEME
|
||||||
* Since: EXPERIMENTAL
|
|
||||||
**/
|
**/
|
||||||
hb_bool_t
|
void
|
||||||
hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
|
hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
const hb_draw_funcs_t *funcs,
|
hb_draw_state_t *st,
|
||||||
void *user_data)
|
float to_x, float to_y)
|
||||||
{
|
{
|
||||||
if (unlikely (funcs == &Null (hb_draw_funcs_t) ||
|
dfuncs->line_to (draw_data, *st,
|
||||||
glyph >= font->face->get_num_glyphs ()))
|
to_x, to_y);
|
||||||
return false;
|
|
||||||
|
|
||||||
draw_helper_t draw_helper (funcs, user_data);
|
|
||||||
if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true;
|
|
||||||
#ifndef HB_NO_CFF
|
|
||||||
if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true;
|
|
||||||
if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
/**
|
||||||
|
* hb_draw_quadratic_to:
|
||||||
|
* @dfuncs: draw functions
|
||||||
|
* @draw_data: associated draw data passed by the caller
|
||||||
|
* @st: current draw state
|
||||||
|
* @control_x: X component of control point
|
||||||
|
* @control_y: Y component of control point
|
||||||
|
* @to_x: X component of target point
|
||||||
|
* @to_y: Y component of target point
|
||||||
|
*
|
||||||
|
* Perform a "quadratic-to" draw operation.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float control_x, float control_y,
|
||||||
|
float to_x, float to_y)
|
||||||
|
{
|
||||||
|
dfuncs->quadratic_to (draw_data, *st,
|
||||||
|
control_x, control_y,
|
||||||
|
to_x, to_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_cubic_to:
|
||||||
|
* @dfuncs: draw functions
|
||||||
|
* @draw_data: associated draw data passed by the caller
|
||||||
|
* @st: current draw state
|
||||||
|
* @control1_x: X component of first control point
|
||||||
|
* @control1_y: Y component of first control point
|
||||||
|
* @control2_x: X component of second control point
|
||||||
|
* @control2_y: Y component of second control point
|
||||||
|
* @to_x: X component of target point
|
||||||
|
* @to_y: Y component of target point
|
||||||
|
*
|
||||||
|
* Perform a "cubic-to" draw operation.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float control1_x, float control1_y,
|
||||||
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y)
|
||||||
|
{
|
||||||
|
dfuncs->cubic_to (draw_data, *st,
|
||||||
|
control1_x, control1_y,
|
||||||
|
control2_x, control2_y,
|
||||||
|
to_x, to_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_close_path:
|
||||||
|
* @dfuncs: draw functions
|
||||||
|
* @draw_data: associated draw data passed by the caller
|
||||||
|
* @st: current draw state
|
||||||
|
*
|
||||||
|
* Perform a "close-path" draw operation.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st)
|
||||||
|
{
|
||||||
|
dfuncs->close_path (draw_data, *st);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
293
src/hb-draw.h
293
src/hb-draw.h
|
@ -33,65 +33,292 @@
|
||||||
|
|
||||||
HB_BEGIN_DECLS
|
HB_BEGIN_DECLS
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
typedef void (*hb_draw_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
|
/**
|
||||||
typedef void (*hb_draw_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
|
* hb_draw_state_t
|
||||||
typedef void (*hb_draw_quadratic_to_func_t) (hb_position_t control_x, hb_position_t control_y,
|
* @path_open: Whether there is an open path
|
||||||
hb_position_t to_x, hb_position_t to_y,
|
* @path_start_x: X component of the start of current path
|
||||||
void *user_data);
|
* @path_start_y: Y component of the start of current path
|
||||||
typedef void (*hb_draw_cubic_to_func_t) (hb_position_t control1_x, hb_position_t control1_y,
|
* @current_x: X component of current point
|
||||||
hb_position_t control2_x, hb_position_t control2_y,
|
* @current_y: Y component of current point
|
||||||
hb_position_t to_x, hb_position_t to_y,
|
*
|
||||||
void *user_data);
|
* Current drawing state.
|
||||||
typedef void (*hb_draw_close_path_func_t) (void *user_data);
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
typedef struct hb_draw_state_t {
|
||||||
|
hb_bool_t path_open;
|
||||||
|
|
||||||
|
float path_start_x;
|
||||||
|
float path_start_y;
|
||||||
|
|
||||||
|
float current_x;
|
||||||
|
float current_y;
|
||||||
|
|
||||||
|
/*< private >*/
|
||||||
|
hb_var_num_t reserved1;
|
||||||
|
hb_var_num_t reserved2;
|
||||||
|
hb_var_num_t reserved3;
|
||||||
|
hb_var_num_t reserved4;
|
||||||
|
hb_var_num_t reserved5;
|
||||||
|
hb_var_num_t reserved6;
|
||||||
|
hb_var_num_t reserved7;
|
||||||
|
} hb_draw_state_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HB_DRAW_STATE_DEFAULT:
|
||||||
|
*
|
||||||
|
* The default #hb_draw_state_t at the start of glyph drawing.
|
||||||
|
*/
|
||||||
|
#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_draw_funcs_t:
|
* hb_draw_funcs_t:
|
||||||
*
|
*
|
||||||
* Glyph draw callbacks.
|
* Glyph draw callbacks.
|
||||||
*
|
*
|
||||||
* _move_to, _line_to and _cubic_to calls are necessary to be defined but we
|
* #hb_draw_move_to_func_t, #hb_draw_line_to_func_t and
|
||||||
* translate _quadratic_to calls to _cubic_to if the callback isn't defined.
|
* #hb_draw_cubic_to_func_t calls are necessary to be defined but we translate
|
||||||
|
* #hb_draw_quadratic_to_func_t calls to #hb_draw_cubic_to_func_t if the
|
||||||
|
* callback isn't defined.
|
||||||
*
|
*
|
||||||
* Since: EXPERIMENTAL
|
* Since: REPLACEME
|
||||||
**/
|
**/
|
||||||
|
|
||||||
typedef struct hb_draw_funcs_t hb_draw_funcs_t;
|
typedef struct hb_draw_funcs_t hb_draw_funcs_t;
|
||||||
|
|
||||||
HB_EXTERN void
|
|
||||||
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
|
|
||||||
hb_draw_move_to_func_t move_to);
|
|
||||||
|
|
||||||
HB_EXTERN void
|
/**
|
||||||
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
|
* hb_draw_move_to_func_t:
|
||||||
hb_draw_line_to_func_t line_to);
|
* @dfuncs: draw functions object
|
||||||
|
* @draw_data: The data accompanying the draw functions
|
||||||
|
* @st: current draw state
|
||||||
|
* @to_x: X component of target point
|
||||||
|
* @to_y: Y component of target point
|
||||||
|
* @user_data: User data pointer passed by the caller
|
||||||
|
*
|
||||||
|
* A virtual method for the #hb_draw_funcs_t to perform a "move-to" draw
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
typedef void (*hb_draw_move_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
HB_EXTERN void
|
/**
|
||||||
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
|
* hb_draw_line_to_func_t:
|
||||||
hb_draw_quadratic_to_func_t quadratic_to);
|
* @dfuncs: draw functions object
|
||||||
|
* @draw_data: The data accompanying the draw functions
|
||||||
|
* @st: current draw state
|
||||||
|
* @to_x: X component of target point
|
||||||
|
* @to_y: Y component of target point
|
||||||
|
* @user_data: User data pointer passed by the caller
|
||||||
|
*
|
||||||
|
* A virtual method for the #hb_draw_funcs_t to perform a "line-to" draw
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
typedef void (*hb_draw_line_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
HB_EXTERN void
|
/**
|
||||||
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
|
* hb_draw_quadratic_to_func_t:
|
||||||
hb_draw_cubic_to_func_t cubic_to);
|
* @dfuncs: draw functions object
|
||||||
|
* @draw_data: The data accompanying the draw functions
|
||||||
|
* @st: current draw state
|
||||||
|
* @control_x: X component of control point
|
||||||
|
* @control_y: Y component of control point
|
||||||
|
* @to_x: X component of target point
|
||||||
|
* @to_y: Y component of target point
|
||||||
|
* @user_data: User data pointer passed by the caller
|
||||||
|
*
|
||||||
|
* A virtual method for the #hb_draw_funcs_t to perform a "quadratic-to" draw
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float control_x, float control_y,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_cubic_to_func_t:
|
||||||
|
* @dfuncs: draw functions object
|
||||||
|
* @draw_data: The data accompanying the draw functions
|
||||||
|
* @st: current draw state
|
||||||
|
* @control1_x: X component of first control point
|
||||||
|
* @control1_y: Y component of first control point
|
||||||
|
* @control2_x: X component of second control point
|
||||||
|
* @control2_y: Y component of second control point
|
||||||
|
* @to_x: X component of target point
|
||||||
|
* @to_y: Y component of target point
|
||||||
|
* @user_data: User data pointer passed by the caller
|
||||||
|
*
|
||||||
|
* A virtual method for the #hb_draw_funcs_t to perform a "cubic-to" draw
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
typedef void (*hb_draw_cubic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float control1_x, float control1_y,
|
||||||
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_close_path_func_t:
|
||||||
|
* @dfuncs: draw functions object
|
||||||
|
* @draw_data: The data accompanying the draw functions
|
||||||
|
* @st: current draw state
|
||||||
|
* @user_data: User data pointer passed by the caller
|
||||||
|
*
|
||||||
|
* A virtual method for the #hb_draw_funcs_t to perform a "close-path" draw
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
typedef void (*hb_draw_close_path_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_funcs_set_move_to_func:
|
||||||
|
* @dfuncs: draw functions object
|
||||||
|
* @func: (closure user_data) (destroy destroy) (scope notified): move-to callback
|
||||||
|
* @user_data: Data to pass to @func
|
||||||
|
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||||
|
*
|
||||||
|
* Sets move-to callback to the draw functions object.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
HB_EXTERN void
|
HB_EXTERN void
|
||||||
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
|
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *dfuncs,
|
||||||
hb_draw_close_path_func_t close_path);
|
hb_draw_move_to_func_t func,
|
||||||
|
void *user_data, hb_destroy_func_t destroy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_funcs_set_line_to_func:
|
||||||
|
* @dfuncs: draw functions object
|
||||||
|
* @func: (closure user_data) (destroy destroy) (scope notified): line-to callback
|
||||||
|
* @user_data: Data to pass to @func
|
||||||
|
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||||
|
*
|
||||||
|
* Sets line-to callback to the draw functions object.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *dfuncs,
|
||||||
|
hb_draw_line_to_func_t func,
|
||||||
|
void *user_data, hb_destroy_func_t destroy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_funcs_set_quadratic_to_func:
|
||||||
|
* @dfuncs: draw functions object
|
||||||
|
* @func: (closure user_data) (destroy destroy) (scope notified): quadratic-to callback
|
||||||
|
* @user_data: Data to pass to @func
|
||||||
|
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||||
|
*
|
||||||
|
* Sets quadratic-to callback to the draw functions object.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *dfuncs,
|
||||||
|
hb_draw_quadratic_to_func_t func,
|
||||||
|
void *user_data, hb_destroy_func_t destroy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_funcs_set_cubic_to_func:
|
||||||
|
* @dfuncs: draw functions
|
||||||
|
* @func: (closure user_data) (destroy destroy) (scope notified): cubic-to callback
|
||||||
|
* @user_data: Data to pass to @func
|
||||||
|
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||||
|
*
|
||||||
|
* Sets cubic-to callback to the draw functions object.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *dfuncs,
|
||||||
|
hb_draw_cubic_to_func_t func,
|
||||||
|
void *user_data, hb_destroy_func_t destroy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_draw_funcs_set_close_path_func:
|
||||||
|
* @dfuncs: draw functions object
|
||||||
|
* @func: (closure user_data) (destroy destroy) (scope notified): close-path callback
|
||||||
|
* @user_data: Data to pass to @func
|
||||||
|
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||||
|
*
|
||||||
|
* Sets close-path callback to the draw functions object.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *dfuncs,
|
||||||
|
hb_draw_close_path_func_t func,
|
||||||
|
void *user_data, hb_destroy_func_t destroy);
|
||||||
|
|
||||||
|
|
||||||
HB_EXTERN hb_draw_funcs_t *
|
HB_EXTERN hb_draw_funcs_t *
|
||||||
hb_draw_funcs_create (void);
|
hb_draw_funcs_create (void);
|
||||||
|
|
||||||
HB_EXTERN hb_draw_funcs_t *
|
HB_EXTERN hb_draw_funcs_t *
|
||||||
hb_draw_funcs_reference (hb_draw_funcs_t *funcs);
|
hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs);
|
||||||
|
|
||||||
HB_EXTERN void
|
HB_EXTERN void
|
||||||
hb_draw_funcs_destroy (hb_draw_funcs_t *funcs);
|
hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs);
|
||||||
|
|
||||||
HB_EXTERN void
|
HB_EXTERN void
|
||||||
hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs);
|
hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs);
|
||||||
|
|
||||||
HB_EXTERN hb_bool_t
|
HB_EXTERN hb_bool_t
|
||||||
hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs);
|
hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float control_x, float control_y,
|
||||||
|
float to_x, float to_y);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float control1_x, float control1_y,
|
||||||
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||||
|
hb_draw_state_t *st);
|
||||||
|
|
||||||
|
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
|
|
||||||
|
|
246
src/hb-draw.hh
246
src/hb-draw.hh
|
@ -27,113 +27,205 @@
|
||||||
|
|
||||||
#include "hb.hh"
|
#include "hb.hh"
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
|
/*
|
||||||
|
* hb_draw_funcs_t
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \
|
||||||
|
HB_DRAW_FUNC_IMPLEMENT (move_to) \
|
||||||
|
HB_DRAW_FUNC_IMPLEMENT (line_to) \
|
||||||
|
HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \
|
||||||
|
HB_DRAW_FUNC_IMPLEMENT (cubic_to) \
|
||||||
|
HB_DRAW_FUNC_IMPLEMENT (close_path) \
|
||||||
|
/* ^--- Add new callbacks here */
|
||||||
|
|
||||||
struct hb_draw_funcs_t
|
struct hb_draw_funcs_t
|
||||||
{
|
{
|
||||||
hb_object_header_t header;
|
hb_object_header_t header;
|
||||||
|
|
||||||
hb_draw_move_to_func_t move_to;
|
struct {
|
||||||
hb_draw_line_to_func_t line_to;
|
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name;
|
||||||
hb_draw_quadratic_to_func_t quadratic_to;
|
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
bool is_quadratic_to_set;
|
#undef HB_DRAW_FUNC_IMPLEMENT
|
||||||
hb_draw_cubic_to_func_t cubic_to;
|
} func;
|
||||||
hb_draw_close_path_func_t close_path;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct draw_helper_t
|
struct {
|
||||||
{
|
#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
|
||||||
draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_)
|
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
{
|
#undef HB_DRAW_FUNC_IMPLEMENT
|
||||||
funcs = funcs_;
|
} user_data;
|
||||||
user_data = user_data_;
|
|
||||||
path_open = false;
|
|
||||||
path_start_x = current_x = path_start_y = current_y = 0;
|
|
||||||
}
|
|
||||||
~draw_helper_t () { end_path (); }
|
|
||||||
|
|
||||||
void move_to (hb_position_t x, hb_position_t y)
|
struct {
|
||||||
|
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
|
||||||
|
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
|
#undef HB_DRAW_FUNC_IMPLEMENT
|
||||||
|
} destroy;
|
||||||
|
|
||||||
|
void emit_move_to (void *draw_data, hb_draw_state_t &st,
|
||||||
|
float to_x, float to_y)
|
||||||
|
{ func.move_to (this, draw_data, &st,
|
||||||
|
to_x, to_y,
|
||||||
|
user_data.move_to); }
|
||||||
|
void emit_line_to (void *draw_data, hb_draw_state_t &st,
|
||||||
|
float to_x, float to_y)
|
||||||
|
{ func.line_to (this, draw_data, &st,
|
||||||
|
to_x, to_y,
|
||||||
|
user_data.line_to); }
|
||||||
|
void emit_quadratic_to (void *draw_data, hb_draw_state_t &st,
|
||||||
|
float control_x, float control_y,
|
||||||
|
float to_x, float to_y)
|
||||||
|
{ func.quadratic_to (this, draw_data, &st,
|
||||||
|
control_x, control_y,
|
||||||
|
to_x, to_y,
|
||||||
|
user_data.quadratic_to); }
|
||||||
|
void emit_cubic_to (void *draw_data, hb_draw_state_t &st,
|
||||||
|
float control1_x, float control1_y,
|
||||||
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y)
|
||||||
|
{ func.cubic_to (this, draw_data, &st,
|
||||||
|
control1_x, control1_y,
|
||||||
|
control2_x, control2_y,
|
||||||
|
to_x, to_y,
|
||||||
|
user_data.cubic_to); }
|
||||||
|
void emit_close_path (void *draw_data, hb_draw_state_t &st)
|
||||||
|
{ func.close_path (this, draw_data, &st,
|
||||||
|
user_data.close_path); }
|
||||||
|
|
||||||
|
|
||||||
|
void move_to (void *draw_data, hb_draw_state_t &st,
|
||||||
|
float to_x, float to_y)
|
||||||
{
|
{
|
||||||
if (path_open) end_path ();
|
if (st.path_open) close_path (draw_data, st);
|
||||||
current_x = path_start_x = x;
|
st.current_x = to_x;
|
||||||
current_y = path_start_y = y;
|
st.current_y = to_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void line_to (hb_position_t x, hb_position_t y)
|
void line_to (void *draw_data, hb_draw_state_t &st,
|
||||||
|
float to_x, float to_y)
|
||||||
{
|
{
|
||||||
if (equal_to_current (x, y)) return;
|
if (!st.path_open) start_path (draw_data, st);
|
||||||
if (!path_open) start_path ();
|
emit_line_to (draw_data, st, to_x, to_y);
|
||||||
funcs->line_to (x, y, user_data);
|
st.current_x = to_x;
|
||||||
current_x = x;
|
st.current_y = to_y;
|
||||||
current_y = y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
quadratic_to (hb_position_t control_x, hb_position_t control_y,
|
quadratic_to (void *draw_data, hb_draw_state_t &st,
|
||||||
hb_position_t to_x, hb_position_t to_y)
|
float control_x, float control_y,
|
||||||
|
float to_x, float to_y)
|
||||||
{
|
{
|
||||||
if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y))
|
if (!st.path_open) start_path (draw_data, st);
|
||||||
return;
|
emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
|
||||||
if (!path_open) start_path ();
|
st.current_x = to_x;
|
||||||
if (funcs->is_quadratic_to_set)
|
st.current_y = to_y;
|
||||||
funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data);
|
|
||||||
else
|
|
||||||
funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f),
|
|
||||||
roundf ((current_y + 2.f * control_y) / 3.f),
|
|
||||||
roundf ((to_x + 2.f * control_x) / 3.f),
|
|
||||||
roundf ((to_y + 2.f * control_y) / 3.f),
|
|
||||||
to_x, to_y, user_data);
|
|
||||||
current_x = to_x;
|
|
||||||
current_y = to_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cubic_to (hb_position_t control1_x, hb_position_t control1_y,
|
cubic_to (void *draw_data, hb_draw_state_t &st,
|
||||||
hb_position_t control2_x, hb_position_t control2_y,
|
float control1_x, float control1_y,
|
||||||
hb_position_t to_x, hb_position_t to_y)
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y)
|
||||||
{
|
{
|
||||||
if (equal_to_current (control1_x, control1_y) &&
|
if (!st.path_open) start_path (draw_data, st);
|
||||||
equal_to_current (control2_x, control2_y) &&
|
emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
|
||||||
equal_to_current (to_x, to_y))
|
st.current_x = to_x;
|
||||||
return;
|
st.current_y = to_y;
|
||||||
if (!path_open) start_path ();
|
|
||||||
funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data);
|
|
||||||
current_x = to_x;
|
|
||||||
current_y = to_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_path ()
|
void
|
||||||
|
close_path (void *draw_data, hb_draw_state_t &st)
|
||||||
{
|
{
|
||||||
if (path_open)
|
if (st.path_open)
|
||||||
{
|
{
|
||||||
if ((path_start_x != current_x) || (path_start_y != current_y))
|
if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y))
|
||||||
funcs->line_to (path_start_x, path_start_y, user_data);
|
emit_line_to (draw_data, st, st.path_start_x, st.path_start_y);
|
||||||
funcs->close_path (user_data);
|
emit_close_path (draw_data, st);
|
||||||
}
|
}
|
||||||
path_open = false;
|
st.path_open = false;
|
||||||
path_start_x = current_x = path_start_y = current_y = 0;
|
st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool equal_to_current (hb_position_t x, hb_position_t y)
|
|
||||||
{ return current_x == x && current_y == y; }
|
|
||||||
|
|
||||||
void start_path ()
|
void start_path (void *draw_data, hb_draw_state_t &st)
|
||||||
{
|
{
|
||||||
if (path_open) end_path ();
|
assert (!st.path_open);
|
||||||
path_open = true;
|
emit_move_to (draw_data, st, st.current_x, st.current_y);
|
||||||
funcs->move_to (path_start_x, path_start_y, user_data);
|
st.path_open = true;
|
||||||
|
st.path_start_x = st.current_x;
|
||||||
|
st.path_start_y = st.current_y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
|
||||||
|
|
||||||
|
struct hb_draw_session_t
|
||||||
|
{
|
||||||
|
hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f)
|
||||||
|
: slant {slant_}, not_slanted {slant == 0.f},
|
||||||
|
funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
|
||||||
|
{}
|
||||||
|
|
||||||
|
~hb_draw_session_t () { close_path (); }
|
||||||
|
|
||||||
|
void move_to (float to_x, float to_y)
|
||||||
|
{
|
||||||
|
if (likely (not_slanted))
|
||||||
|
funcs->move_to (draw_data, st,
|
||||||
|
to_x, to_y);
|
||||||
|
else
|
||||||
|
funcs->move_to (draw_data, st,
|
||||||
|
to_x + to_y * slant, to_y);
|
||||||
|
}
|
||||||
|
void line_to (float to_x, float to_y)
|
||||||
|
{
|
||||||
|
if (likely (not_slanted))
|
||||||
|
funcs->line_to (draw_data, st,
|
||||||
|
to_x, to_y);
|
||||||
|
else
|
||||||
|
funcs->line_to (draw_data, st,
|
||||||
|
to_x + to_y * slant, to_y);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
quadratic_to (float control_x, float control_y,
|
||||||
|
float to_x, float to_y)
|
||||||
|
{
|
||||||
|
if (likely (not_slanted))
|
||||||
|
funcs->quadratic_to (draw_data, st,
|
||||||
|
control_x, control_y,
|
||||||
|
to_x, to_y);
|
||||||
|
else
|
||||||
|
funcs->quadratic_to (draw_data, st,
|
||||||
|
control_x + control_y * slant, control_y,
|
||||||
|
to_x + to_y * slant, to_y);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
cubic_to (float control1_x, float control1_y,
|
||||||
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y)
|
||||||
|
{
|
||||||
|
if (likely (not_slanted))
|
||||||
|
funcs->cubic_to (draw_data, st,
|
||||||
|
control1_x, control1_y,
|
||||||
|
control2_x, control2_y,
|
||||||
|
to_x, to_y);
|
||||||
|
else
|
||||||
|
funcs->cubic_to (draw_data, st,
|
||||||
|
control1_x + control1_y * slant, control1_y,
|
||||||
|
control2_x + control2_y * slant, control2_y,
|
||||||
|
to_x + to_y * slant, to_y);
|
||||||
|
}
|
||||||
|
void close_path ()
|
||||||
|
{
|
||||||
|
funcs->close_path (draw_data, st);
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_position_t path_start_x;
|
protected:
|
||||||
hb_position_t path_start_y;
|
float slant;
|
||||||
|
bool not_slanted;
|
||||||
hb_position_t current_x;
|
hb_draw_funcs_t *funcs;
|
||||||
hb_position_t current_y;
|
void *draw_data;
|
||||||
|
hb_draw_state_t st;
|
||||||
bool path_open;
|
|
||||||
const hb_draw_funcs_t *funcs;
|
|
||||||
void *user_data;
|
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HB_DRAW_HH */
|
#endif /* HB_DRAW_HH */
|
||||||
|
|
159
src/hb-font.cc
159
src/hb-font.cc
|
@ -29,6 +29,7 @@
|
||||||
#include "hb.hh"
|
#include "hb.hh"
|
||||||
|
|
||||||
#include "hb-font.hh"
|
#include "hb-font.hh"
|
||||||
|
#include "hb-draw.hh"
|
||||||
#include "hb-machinery.hh"
|
#include "hb-machinery.hh"
|
||||||
|
|
||||||
#include "hb-ot.h"
|
#include "hb-ot.h"
|
||||||
|
@ -501,6 +502,136 @@ hb_font_get_glyph_from_name_default (hb_font_t *font,
|
||||||
return font->parent->get_glyph_from_name (name, len, glyph);
|
return font->parent->get_glyph_from_name (name, len, glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hb_font_get_glyph_shape_nil (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data HB_UNUSED,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_draw_funcs_t *draw_funcs,
|
||||||
|
void *draw_data,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct hb_font_get_glyph_shape_default_adaptor_t {
|
||||||
|
hb_draw_funcs_t *draw_funcs;
|
||||||
|
void *draw_data;
|
||||||
|
float x_scale;
|
||||||
|
float y_scale;
|
||||||
|
} hb_font_get_glyph_shape_default_adaptor_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||||
|
void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
|
||||||
|
float x_scale = adaptor->x_scale;
|
||||||
|
float y_scale = adaptor->y_scale;
|
||||||
|
|
||||||
|
adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
|
||||||
|
x_scale * to_x, y_scale * to_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
|
||||||
|
float x_scale = adaptor->x_scale;
|
||||||
|
float y_scale = adaptor->y_scale;
|
||||||
|
|
||||||
|
st->current_x *= x_scale;
|
||||||
|
st->current_y *= y_scale;
|
||||||
|
|
||||||
|
adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
|
||||||
|
x_scale * to_x, y_scale * to_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float control_x, float control_y,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
|
||||||
|
float x_scale = adaptor->x_scale;
|
||||||
|
float y_scale = adaptor->y_scale;
|
||||||
|
|
||||||
|
st->current_x *= x_scale;
|
||||||
|
st->current_y *= y_scale;
|
||||||
|
|
||||||
|
adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
|
||||||
|
x_scale * control_x, y_scale * control_y,
|
||||||
|
x_scale * to_x, y_scale * to_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float control1_x, float control1_y,
|
||||||
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
|
||||||
|
float x_scale = adaptor->x_scale;
|
||||||
|
float y_scale = adaptor->y_scale;
|
||||||
|
|
||||||
|
st->current_x *= x_scale;
|
||||||
|
st->current_y *= y_scale;
|
||||||
|
|
||||||
|
adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
|
||||||
|
x_scale * control1_x, y_scale * control1_y,
|
||||||
|
x_scale * control2_x, y_scale * control2_y,
|
||||||
|
x_scale * to_x, y_scale * to_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hb_draw_close_path_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
|
||||||
|
|
||||||
|
adaptor->draw_funcs->emit_close_path (adaptor->draw_data, *st);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const hb_draw_funcs_t _hb_draw_funcs_default = {
|
||||||
|
HB_OBJECT_HEADER_STATIC,
|
||||||
|
|
||||||
|
{
|
||||||
|
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_default,
|
||||||
|
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
|
#undef HB_DRAW_FUNC_IMPLEMENT
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
hb_font_get_glyph_shape_default (hb_font_t *font,
|
||||||
|
void *font_data HB_UNUSED,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_draw_funcs_t *draw_funcs,
|
||||||
|
void *draw_data,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
hb_font_get_glyph_shape_default_adaptor_t adaptor = {
|
||||||
|
draw_funcs,
|
||||||
|
draw_data,
|
||||||
|
(float) font->x_scale / (float) font->parent->x_scale,
|
||||||
|
(float) font->y_scale / (float) font->parent->y_scale
|
||||||
|
};
|
||||||
|
|
||||||
|
font->parent->get_glyph_shape (glyph,
|
||||||
|
const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default),
|
||||||
|
&adaptor);
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
|
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
|
||||||
{
|
{
|
||||||
HB_OBJECT_HEADER_STATIC,
|
HB_OBJECT_HEADER_STATIC,
|
||||||
|
@ -1168,6 +1299,26 @@ hb_font_get_glyph_from_name (hb_font_t *font,
|
||||||
return font->get_glyph_from_name (name, len, glyph);
|
return font->get_glyph_from_name (name, len, glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_get_glyph_shape:
|
||||||
|
* @font: #hb_font_t to work upon
|
||||||
|
* @glyph: : The glyph ID
|
||||||
|
* @dfuncs: #hb_draw_funcs_t to draw to
|
||||||
|
* @draw_data: User data to pass to draw callbacks
|
||||||
|
*
|
||||||
|
* Fetches the glyph shape that corresponds to a glyph in the specified @font.
|
||||||
|
* The shape is returned by way of calls to the callsbacks of the @dfuncs
|
||||||
|
* objects, with @draw_data passed to them.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
hb_font_get_glyph_shape (hb_font_t *font,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_draw_funcs_t *dfuncs, void *draw_data)
|
||||||
|
{
|
||||||
|
font->get_glyph_shape (glyph, dfuncs, draw_data);
|
||||||
|
}
|
||||||
|
|
||||||
/* A bit higher-level, and with fallback */
|
/* A bit higher-level, and with fallback */
|
||||||
|
|
||||||
|
@ -2044,12 +2195,16 @@ hb_font_get_ptem (hb_font_t *font)
|
||||||
* @slant: synthetic slant value.
|
* @slant: synthetic slant value.
|
||||||
*
|
*
|
||||||
* Sets the "synthetic slant" of a font. By default is zero.
|
* Sets the "synthetic slant" of a font. By default is zero.
|
||||||
* Synthetic slant is the graphical skew that the renderer
|
* Synthetic slant is the graphical skew applied to the font
|
||||||
* applies to the font at rendering time.
|
* at rendering time.
|
||||||
*
|
*
|
||||||
* HarfBuzz needs to know this value to adjust shaping results,
|
* HarfBuzz needs to know this value to adjust shaping results,
|
||||||
* metrics, and style values to match the slanted rendering.
|
* metrics, and style values to match the slanted rendering.
|
||||||
*
|
*
|
||||||
|
* <note>Note: The glyph shape fetched via the
|
||||||
|
* hb_font_get_glyph_shape() is slanted to reflect this value
|
||||||
|
* as well.</note>
|
||||||
|
*
|
||||||
* <note>Note: The slant value is a ratio. For example, a
|
* <note>Note: The slant value is a ratio. For example, a
|
||||||
* 20% slant would be represented as a 0.2 value.</note>
|
* 20% slant would be represented as a 0.2 value.</note>
|
||||||
*
|
*
|
||||||
|
|
|
@ -511,6 +511,25 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
|
||||||
hb_codepoint_t *glyph,
|
hb_codepoint_t *glyph,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_get_glyph_shape_func_t:
|
||||||
|
* @font: #hb_font_t to work upon
|
||||||
|
* @font_data: @font user data pointer
|
||||||
|
* @glyph: The glyph ID to query
|
||||||
|
* @draw_funcs: The draw functions to send the shape data to
|
||||||
|
* @draw_data: The data accompanying the draw functions
|
||||||
|
* @user_data: User data pointer passed by the caller
|
||||||
|
*
|
||||||
|
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
|
||||||
/* func setters */
|
/* func setters */
|
||||||
|
|
||||||
|
@ -770,6 +789,22 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
|
||||||
hb_font_get_glyph_from_name_func_t func,
|
hb_font_get_glyph_from_name_func_t func,
|
||||||
void *user_data, hb_destroy_func_t destroy);
|
void *user_data, hb_destroy_func_t destroy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_funcs_set_glyph_shape_func:
|
||||||
|
* @ffuncs: A font-function structure
|
||||||
|
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
|
||||||
|
* @user_data: Data to pass to @func
|
||||||
|
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||||
|
*
|
||||||
|
* Sets the implementation function for #hb_font_get_glyph_shape_func_t.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
**/
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
|
||||||
|
hb_font_get_glyph_shape_func_t func,
|
||||||
|
void *user_data, hb_destroy_func_t destroy);
|
||||||
|
|
||||||
/* func dispatch */
|
/* func dispatch */
|
||||||
|
|
||||||
HB_EXTERN hb_bool_t
|
HB_EXTERN hb_bool_t
|
||||||
|
@ -850,6 +885,11 @@ hb_font_get_glyph_from_name (hb_font_t *font,
|
||||||
const char *name, int len, /* -1 means nul-terminated */
|
const char *name, int len, /* -1 means nul-terminated */
|
||||||
hb_codepoint_t *glyph);
|
hb_codepoint_t *glyph);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_font_get_glyph_shape (hb_font_t *font,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_draw_funcs_t *dfuncs, void *draw_data);
|
||||||
|
|
||||||
|
|
||||||
/* high-level funcs, with fallback */
|
/* high-level funcs, with fallback */
|
||||||
|
|
||||||
|
@ -1056,11 +1096,6 @@ HB_EXTERN void
|
||||||
hb_font_set_var_named_instance (hb_font_t *font,
|
hb_font_set_var_named_instance (hb_font_t *font,
|
||||||
unsigned instance_index);
|
unsigned instance_index);
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
HB_EXTERN hb_bool_t
|
|
||||||
hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
|
|
||||||
const hb_draw_funcs_t *funcs, void *user_data);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
|
HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
|
||||||
HB_FONT_FUNC_IMPLEMENT (glyph_name) \
|
HB_FONT_FUNC_IMPLEMENT (glyph_name) \
|
||||||
HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
|
HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
|
||||||
|
HB_FONT_FUNC_IMPLEMENT (glyph_shape) \
|
||||||
/* ^--- Add new callbacks here */
|
/* ^--- Add new callbacks here */
|
||||||
|
|
||||||
struct hb_font_funcs_t
|
struct hb_font_funcs_t
|
||||||
|
@ -140,6 +141,8 @@ struct hb_font_t
|
||||||
hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
|
hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
|
||||||
float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
|
float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
|
||||||
float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
|
float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
|
||||||
|
float em_fscalef_x (float v) { return em_fscalef (v, x_scale); }
|
||||||
|
float em_fscalef_y (float v) { return em_fscalef (v, y_scale); }
|
||||||
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
|
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
|
||||||
{ return em_mult (v, dir_mult (direction)); }
|
{ return em_mult (v, dir_mult (direction)); }
|
||||||
|
|
||||||
|
@ -373,6 +376,15 @@ struct hb_font_t
|
||||||
klass->user_data.glyph_from_name);
|
klass->user_data.glyph_from_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_glyph_shape (hb_codepoint_t glyph,
|
||||||
|
hb_draw_funcs_t *draw_funcs, void *draw_data)
|
||||||
|
{
|
||||||
|
klass->get.f.glyph_shape (this, user_data,
|
||||||
|
glyph,
|
||||||
|
draw_funcs, draw_data,
|
||||||
|
klass->user_data.glyph_shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* A bit higher-level, and with fallback */
|
/* A bit higher-level, and with fallback */
|
||||||
|
|
||||||
|
@ -625,7 +637,9 @@ struct hb_font_t
|
||||||
hb_position_t em_mult (int16_t v, int64_t mult)
|
hb_position_t em_mult (int16_t v, int64_t mult)
|
||||||
{ return (hb_position_t) ((v * mult + 32768) >> 16); }
|
{ return (hb_position_t) ((v * mult + 32768) >> 16); }
|
||||||
hb_position_t em_scalef (float v, int scale)
|
hb_position_t em_scalef (float v, int scale)
|
||||||
{ return (hb_position_t) roundf (v * scale / face->get_upem ()); }
|
{ return (hb_position_t) roundf (em_fscalef (v, scale)); }
|
||||||
|
float em_fscalef (float v, int scale)
|
||||||
|
{ return v * scale / face->get_upem (); }
|
||||||
float em_fscale (int16_t v, int scale)
|
float em_fscale (int16_t v, int scale)
|
||||||
{ return (float) v * scale / face->get_upem (); }
|
{ return (float) v * scale / face->get_upem (); }
|
||||||
};
|
};
|
||||||
|
|
82
src/hb-ft.cc
82
src/hb-ft.cc
|
@ -33,12 +33,14 @@
|
||||||
|
|
||||||
#include "hb-ft.h"
|
#include "hb-ft.h"
|
||||||
|
|
||||||
|
#include "hb-draw.hh"
|
||||||
#include "hb-font.hh"
|
#include "hb-font.hh"
|
||||||
#include "hb-machinery.hh"
|
#include "hb-machinery.hh"
|
||||||
#include "hb-cache.hh"
|
#include "hb-cache.hh"
|
||||||
|
|
||||||
#include FT_ADVANCES_H
|
#include FT_ADVANCES_H
|
||||||
#include FT_MULTIPLE_MASTERS_H
|
#include FT_MULTIPLE_MASTERS_H
|
||||||
|
#include FT_OUTLINE_H
|
||||||
#include FT_TRUETYPE_TABLES_H
|
#include FT_TRUETYPE_TABLES_H
|
||||||
|
|
||||||
|
|
||||||
|
@ -565,6 +567,82 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HB_NO_DRAW
|
||||||
|
|
||||||
|
static int
|
||||||
|
_hb_ft_move_to (const FT_Vector *to,
|
||||||
|
hb_draw_session_t *drawing)
|
||||||
|
{
|
||||||
|
drawing->move_to (to->x, to->y);
|
||||||
|
return FT_Err_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_hb_ft_line_to (const FT_Vector *to,
|
||||||
|
hb_draw_session_t *drawing)
|
||||||
|
{
|
||||||
|
drawing->line_to (to->x, to->y);
|
||||||
|
return FT_Err_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_hb_ft_conic_to (const FT_Vector *control,
|
||||||
|
const FT_Vector *to,
|
||||||
|
hb_draw_session_t *drawing)
|
||||||
|
{
|
||||||
|
drawing->quadratic_to (control->x, control->y,
|
||||||
|
to->x, to->y);
|
||||||
|
return FT_Err_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_hb_ft_cubic_to (const FT_Vector *control1,
|
||||||
|
const FT_Vector *control2,
|
||||||
|
const FT_Vector *to,
|
||||||
|
hb_draw_session_t *drawing)
|
||||||
|
{
|
||||||
|
drawing->cubic_to (control1->x, control1->y,
|
||||||
|
control2->x, control2->y,
|
||||||
|
to->x, to->y);
|
||||||
|
return FT_Err_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||||
|
hb_lock_t lock (ft_font->lock);
|
||||||
|
FT_Face ft_face = ft_font->ft_face;
|
||||||
|
|
||||||
|
if (unlikely (FT_Load_Glyph (ft_face, glyph,
|
||||||
|
FT_LOAD_NO_BITMAP | ft_font->load_flags)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const FT_Outline_Funcs outline_funcs = {
|
||||||
|
(FT_Outline_MoveToFunc) _hb_ft_move_to,
|
||||||
|
(FT_Outline_LineToFunc) _hb_ft_line_to,
|
||||||
|
(FT_Outline_ConicToFunc) _hb_ft_conic_to,
|
||||||
|
(FT_Outline_CubicToFunc) _hb_ft_cubic_to,
|
||||||
|
0, /* shift */
|
||||||
|
0, /* delta */
|
||||||
|
};
|
||||||
|
|
||||||
|
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
|
||||||
|
|
||||||
|
FT_Outline_Decompose (&ft_face->glyph->outline,
|
||||||
|
&outline_funcs,
|
||||||
|
&draw_session);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline void free_static_ft_funcs ();
|
static inline void free_static_ft_funcs ();
|
||||||
|
|
||||||
static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
|
static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
|
||||||
|
@ -596,6 +674,10 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
|
||||||
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
|
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
|
||||||
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
|
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
|
||||||
|
|
||||||
|
#ifndef HB_NO_DRAW
|
||||||
|
hb_font_funcs_set_glyph_shape_func (funcs, hb_ft_get_glyph_shape, nullptr, nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
hb_font_funcs_make_immutable (funcs);
|
hb_font_funcs_make_immutable (funcs);
|
||||||
|
|
||||||
hb_atexit (free_static_ft_funcs);
|
hb_atexit (free_static_ft_funcs);
|
||||||
|
|
|
@ -90,6 +90,7 @@ hb_gobject_##name##_get_type () \
|
||||||
|
|
||||||
HB_DEFINE_OBJECT_TYPE (buffer)
|
HB_DEFINE_OBJECT_TYPE (buffer)
|
||||||
HB_DEFINE_OBJECT_TYPE (blob)
|
HB_DEFINE_OBJECT_TYPE (blob)
|
||||||
|
HB_DEFINE_OBJECT_TYPE (draw_funcs)
|
||||||
HB_DEFINE_OBJECT_TYPE (face)
|
HB_DEFINE_OBJECT_TYPE (face)
|
||||||
HB_DEFINE_OBJECT_TYPE (font)
|
HB_DEFINE_OBJECT_TYPE (font)
|
||||||
HB_DEFINE_OBJECT_TYPE (font_funcs)
|
HB_DEFINE_OBJECT_TYPE (font_funcs)
|
||||||
|
|
|
@ -48,6 +48,10 @@ HB_EXTERN GType
|
||||||
hb_gobject_buffer_get_type (void);
|
hb_gobject_buffer_get_type (void);
|
||||||
#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
|
#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
|
||||||
|
|
||||||
|
HB_EXTERN GType
|
||||||
|
hb_gobject_draw_funcs_get_type (void);
|
||||||
|
#define HB_GOBJECT_TYPE_DRAW_FUNCS (hb_gobject_draw_funcs_get_type ())
|
||||||
|
|
||||||
HB_EXTERN GType
|
HB_EXTERN GType
|
||||||
hb_gobject_face_get_type (void);
|
hb_gobject_face_get_type (void);
|
||||||
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
|
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
|
||||||
|
|
|
@ -442,13 +442,12 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
struct cff1_path_param_t
|
struct cff1_path_param_t
|
||||||
{
|
{
|
||||||
cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
|
cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
|
||||||
draw_helper_t &draw_helper_, point_t *delta_)
|
hb_draw_session_t &draw_session_, point_t *delta_)
|
||||||
{
|
{
|
||||||
draw_helper = &draw_helper_;
|
draw_session = &draw_session_;
|
||||||
cff = cff_;
|
cff = cff_;
|
||||||
font = font_;
|
font = font_;
|
||||||
delta = delta_;
|
delta = delta_;
|
||||||
|
@ -458,14 +457,14 @@ struct cff1_path_param_t
|
||||||
{
|
{
|
||||||
point_t point = p;
|
point_t point = p;
|
||||||
if (delta) point.move (*delta);
|
if (delta) point.move (*delta);
|
||||||
draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
|
draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void line_to (const point_t &p)
|
void line_to (const point_t &p)
|
||||||
{
|
{
|
||||||
point_t point = p;
|
point_t point = p;
|
||||||
if (delta) point.move (*delta);
|
if (delta) point.move (*delta);
|
||||||
draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
|
draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
|
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
|
||||||
|
@ -477,15 +476,15 @@ struct cff1_path_param_t
|
||||||
point2.move (*delta);
|
point2.move (*delta);
|
||||||
point3.move (*delta);
|
point3.move (*delta);
|
||||||
}
|
}
|
||||||
draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()),
|
draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()),
|
||||||
font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()),
|
font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()),
|
||||||
font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ()));
|
font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_path () { draw_helper->end_path (); }
|
void end_path () { draw_session->close_path (); }
|
||||||
|
|
||||||
hb_font_t *font;
|
hb_font_t *font;
|
||||||
draw_helper_t *draw_helper;
|
hb_draw_session_t *draw_session;
|
||||||
point_t *delta;
|
point_t *delta;
|
||||||
|
|
||||||
const OT::cff1::accelerator_t *cff;
|
const OT::cff1::accelerator_t *cff;
|
||||||
|
@ -513,7 +512,7 @@ struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_int
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
|
static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
|
||||||
draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr);
|
hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr);
|
||||||
|
|
||||||
struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
|
struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
|
||||||
{
|
{
|
||||||
|
@ -530,14 +529,14 @@ struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_pa
|
||||||
hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
|
hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
|
||||||
|
|
||||||
if (unlikely (!(!env.in_seac && base && accent
|
if (unlikely (!(!env.in_seac && base && accent
|
||||||
&& _get_path (param.cff, param.font, base, *param.draw_helper, true)
|
&& _get_path (param.cff, param.font, base, *param.draw_session, true)
|
||||||
&& _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta))))
|
&& _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta))))
|
||||||
env.set_error ();
|
env.set_error ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
|
bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
|
||||||
draw_helper_t &draw_helper, bool in_seac, point_t *delta)
|
hb_draw_session_t &draw_session, bool in_seac, point_t *delta)
|
||||||
{
|
{
|
||||||
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
|
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
|
||||||
|
|
||||||
|
@ -546,7 +545,7 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
|
||||||
const byte_str_t str = (*cff->charStrings)[glyph];
|
const byte_str_t str = (*cff->charStrings)[glyph];
|
||||||
interp.env.init (str, *cff, fd);
|
interp.env.init (str, *cff, fd);
|
||||||
interp.env.set_in_seac (in_seac);
|
interp.env.set_in_seac (in_seac);
|
||||||
cff1_path_param_t param (cff, font, draw_helper, delta);
|
cff1_path_param_t param (cff, font, draw_session, delta);
|
||||||
if (unlikely (!interp.interpret (param))) return false;
|
if (unlikely (!interp.interpret (param))) return false;
|
||||||
|
|
||||||
/* Let's end the path specially since it is called inside seac also */
|
/* Let's end the path specially since it is called inside seac also */
|
||||||
|
@ -555,16 +554,15 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
|
bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
|
||||||
{
|
{
|
||||||
#ifdef HB_NO_OT_FONT_CFF
|
#ifdef HB_NO_OT_FONT_CFF
|
||||||
/* XXX Remove check when this code moves to .hh file. */
|
/* XXX Remove check when this code moves to .hh file. */
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return _get_path (this, font, glyph, draw_helper);
|
return _get_path (this, font, glyph, draw_session);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
struct get_seac_param_t
|
struct get_seac_param_t
|
||||||
{
|
{
|
||||||
|
|
|
@ -1347,9 +1347,7 @@ struct cff1
|
||||||
|
|
||||||
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
|
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
|
||||||
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
|
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
|
||||||
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct gname_t
|
struct gname_t
|
||||||
|
|
|
@ -143,30 +143,29 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
struct cff2_path_param_t
|
struct cff2_path_param_t
|
||||||
{
|
{
|
||||||
cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_)
|
cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
|
||||||
{
|
{
|
||||||
draw_helper = &draw_helper_;
|
draw_session = &draw_session_;
|
||||||
font = font_;
|
font = font_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void move_to (const point_t &p)
|
void move_to (const point_t &p)
|
||||||
{ draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
|
{ draw_session->move_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
|
||||||
|
|
||||||
void line_to (const point_t &p)
|
void line_to (const point_t &p)
|
||||||
{ draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
|
{ draw_session->line_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
|
||||||
|
|
||||||
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
|
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
|
||||||
{
|
{
|
||||||
draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()),
|
draw_session->cubic_to (font->em_fscalef_x (p1.x.to_real ()), font->em_fscalef_y (p1.y.to_real ()),
|
||||||
font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()),
|
font->em_fscalef_x (p2.x.to_real ()), font->em_fscalef_y (p2.y.to_real ()),
|
||||||
font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ()));
|
font->em_fscalef_x (p3.x.to_real ()), font->em_fscalef_y (p3.y.to_real ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
draw_helper_t *draw_helper;
|
hb_draw_session_t *draw_session;
|
||||||
hb_font_t *font;
|
hb_font_t *font;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -193,7 +192,7 @@ struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_int
|
||||||
|
|
||||||
struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
|
struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
|
||||||
|
|
||||||
bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
|
bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
|
||||||
{
|
{
|
||||||
#ifdef HB_NO_OT_FONT_CFF
|
#ifdef HB_NO_OT_FONT_CFF
|
||||||
/* XXX Remove check when this code moves to .hh file. */
|
/* XXX Remove check when this code moves to .hh file. */
|
||||||
|
@ -206,10 +205,9 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, d
|
||||||
cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
|
cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
|
||||||
const byte_str_t str = (*charStrings)[glyph];
|
const byte_str_t str = (*charStrings)[glyph];
|
||||||
interp.env.init (str, *this, fd, font->coords, font->num_coords);
|
interp.env.init (str, *this, fd, font->coords, font->num_coords);
|
||||||
cff2_path_param_t param (font, draw_helper);
|
cff2_path_param_t param (font, draw_session);
|
||||||
if (unlikely (!interp.interpret (param))) return false;
|
if (unlikely (!interp.interpret (param))) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -515,9 +515,7 @@ struct cff2
|
||||||
HB_INTERNAL bool get_extents (hb_font_t *font,
|
HB_INTERNAL bool get_extents (hb_font_t *font,
|
||||||
hb_codepoint_t glyph,
|
hb_codepoint_t glyph,
|
||||||
hb_glyph_extents_t *extents) const;
|
hb_glyph_extents_t *extents) const;
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
|
||||||
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
|
typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
|
||||||
|
|
|
@ -257,6 +257,23 @@ hb_ot_get_font_v_extents (hb_font_t *font,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_NO_DRAW
|
||||||
|
static void
|
||||||
|
hb_ot_get_glyph_shape (hb_font_t *font,
|
||||||
|
void *font_data HB_UNUSED,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
|
||||||
|
if (font->face->table.glyf->get_path (font, glyph, draw_session)) return;
|
||||||
|
#ifndef HB_NO_CFF
|
||||||
|
if (font->face->table.cff1->get_path (font, glyph, draw_session)) return;
|
||||||
|
if (font->face->table.cff2->get_path (font, glyph, draw_session)) return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void free_static_ot_funcs ();
|
static inline void free_static_ot_funcs ();
|
||||||
|
|
||||||
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
|
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
|
||||||
|
@ -279,6 +296,10 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
|
||||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
|
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_NO_DRAW
|
||||||
|
hb_font_funcs_set_glyph_shape_func (funcs, hb_ot_get_glyph_shape, nullptr, nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
|
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
|
||||||
//hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
|
//hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
|
||||||
|
|
||||||
|
|
|
@ -1152,11 +1152,10 @@ struct glyf
|
||||||
return operation_count;
|
return operation_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
struct path_builder_t
|
struct path_builder_t
|
||||||
{
|
{
|
||||||
hb_font_t *font;
|
hb_font_t *font;
|
||||||
draw_helper_t *draw_helper;
|
hb_draw_session_t *draw_session;
|
||||||
|
|
||||||
struct optional_point_t
|
struct optional_point_t
|
||||||
{
|
{
|
||||||
|
@ -1171,10 +1170,10 @@ struct glyf
|
||||||
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
|
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
|
||||||
} first_oncurve, first_offcurve, last_offcurve;
|
} first_oncurve, first_offcurve, last_offcurve;
|
||||||
|
|
||||||
path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_)
|
path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
|
||||||
{
|
{
|
||||||
font = font_;
|
font = font_;
|
||||||
draw_helper = &draw_helper_;
|
draw_session = &draw_session_;
|
||||||
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1184,10 +1183,6 @@ struct glyf
|
||||||
* https://stackoverflow.com/a/20772557 */
|
* https://stackoverflow.com/a/20772557 */
|
||||||
void consume_point (const contour_point_t &point)
|
void consume_point (const contour_point_t &point)
|
||||||
{
|
{
|
||||||
/* Skip empty contours */
|
|
||||||
if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data))
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
|
bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
|
||||||
optional_point_t p (point.x, point.y);
|
optional_point_t p (point.x, point.y);
|
||||||
if (!first_oncurve.has_data)
|
if (!first_oncurve.has_data)
|
||||||
|
@ -1195,7 +1190,7 @@ struct glyf
|
||||||
if (is_on_curve)
|
if (is_on_curve)
|
||||||
{
|
{
|
||||||
first_oncurve = p;
|
first_oncurve = p;
|
||||||
draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
|
draw_session->move_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1204,7 +1199,7 @@ struct glyf
|
||||||
optional_point_t mid = first_offcurve.lerp (p, .5f);
|
optional_point_t mid = first_offcurve.lerp (p, .5f);
|
||||||
first_oncurve = mid;
|
first_oncurve = mid;
|
||||||
last_offcurve = p;
|
last_offcurve = p;
|
||||||
draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
|
draw_session->move_to (font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
first_offcurve = p;
|
first_offcurve = p;
|
||||||
|
@ -1216,22 +1211,22 @@ struct glyf
|
||||||
{
|
{
|
||||||
if (is_on_curve)
|
if (is_on_curve)
|
||||||
{
|
{
|
||||||
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
|
draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
|
||||||
font->em_scalef_x (p.x), font->em_scalef_y (p.y));
|
font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
|
||||||
last_offcurve = optional_point_t ();
|
last_offcurve = optional_point_t ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
optional_point_t mid = last_offcurve.lerp (p, .5f);
|
optional_point_t mid = last_offcurve.lerp (p, .5f);
|
||||||
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
|
draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
|
||||||
font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
|
font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
|
||||||
last_offcurve = p;
|
last_offcurve = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (is_on_curve)
|
if (is_on_curve)
|
||||||
draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
|
draw_session->line_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
|
||||||
else
|
else
|
||||||
last_offcurve = p;
|
last_offcurve = p;
|
||||||
}
|
}
|
||||||
|
@ -1242,24 +1237,30 @@ struct glyf
|
||||||
if (first_offcurve.has_data && last_offcurve.has_data)
|
if (first_offcurve.has_data && last_offcurve.has_data)
|
||||||
{
|
{
|
||||||
optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
|
optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
|
||||||
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
|
draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
|
||||||
font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
|
font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
|
||||||
last_offcurve = optional_point_t ();
|
last_offcurve = optional_point_t ();
|
||||||
/* now check the rest */
|
/* now check the rest */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first_offcurve.has_data && first_oncurve.has_data)
|
if (first_offcurve.has_data && first_oncurve.has_data)
|
||||||
draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y),
|
draw_session->quadratic_to (font->em_fscalef_x (first_offcurve.x), font->em_fscalef_y (first_offcurve.y),
|
||||||
font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
|
font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
|
||||||
else if (last_offcurve.has_data && first_oncurve.has_data)
|
else if (last_offcurve.has_data && first_oncurve.has_data)
|
||||||
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
|
draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
|
||||||
font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
|
font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
|
||||||
else if (first_oncurve.has_data)
|
else if (first_oncurve.has_data)
|
||||||
draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
|
draw_session->line_to (font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
|
||||||
|
else if (first_offcurve.has_data)
|
||||||
|
{
|
||||||
|
float x = font->em_fscalef_x (first_offcurve.x), y = font->em_fscalef_x (first_offcurve.y);
|
||||||
|
draw_session->move_to (x, y);
|
||||||
|
draw_session->quadratic_to (x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
/* Getting ready for the next contour */
|
/* Getting ready for the next contour */
|
||||||
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
||||||
draw_helper->end_path ();
|
draw_session->close_path ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void points_end () {}
|
void points_end () {}
|
||||||
|
@ -1269,9 +1270,8 @@ struct glyf
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const
|
get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
|
||||||
{ return get_points (font, gid, path_builder_t (font, draw_helper)); }
|
{ return get_points (font, gid, path_builder_t (font, draw_session)); }
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
const gvar_accelerator_t *gvar;
|
const gvar_accelerator_t *gvar;
|
||||||
|
|
82
src/main.cc
82
src/main.cc
|
@ -42,7 +42,7 @@
|
||||||
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API)
|
#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW)
|
||||||
static void
|
static void
|
||||||
svg_dump (hb_face_t *face, unsigned face_index)
|
svg_dump (hb_face_t *face, unsigned face_index)
|
||||||
{
|
{
|
||||||
|
@ -129,48 +129,60 @@ png_dump (hb_face_t *face, unsigned face_index)
|
||||||
hb_font_destroy (font);
|
hb_font_destroy (font);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct user_data_t
|
struct draw_data_t
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
hb_position_t ascender;
|
hb_position_t ascender;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
move_to (hb_position_t to_x, hb_position_t to_y, user_data_t &user_data)
|
move_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *)
|
||||||
{
|
{
|
||||||
fprintf (user_data.f, "M%d,%d", to_x, user_data.ascender - to_y);
|
fprintf (draw_data->f, "M%g,%g", to_x, draw_data->ascender - to_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
line_to (hb_position_t to_x, hb_position_t to_y, user_data_t &user_data)
|
line_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *)
|
||||||
{
|
{
|
||||||
fprintf (user_data.f, "L%d,%d", to_x, user_data.ascender - to_y);
|
fprintf (draw_data->f, "L%g,%g", to_x, draw_data->ascender - to_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
quadratic_to (hb_position_t control_x, hb_position_t control_y,
|
quadratic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
|
||||||
hb_position_t to_x, hb_position_t to_y,
|
hb_draw_state_t *st,
|
||||||
user_data_t &user_data)
|
float control_x, float control_y,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *)
|
||||||
{
|
{
|
||||||
fprintf (user_data.f, "Q%d,%d %d,%d", control_x, user_data.ascender - control_y,
|
fprintf (draw_data->f, "Q%g,%g %g,%g", control_x, draw_data->ascender - control_y,
|
||||||
to_x, user_data.ascender - to_y);
|
to_x, draw_data->ascender - to_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cubic_to (hb_position_t control1_x, hb_position_t control1_y,
|
cubic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
|
||||||
hb_position_t control2_x, hb_position_t control2_y,
|
hb_draw_state_t *st,
|
||||||
hb_position_t to_x, hb_position_t to_y,
|
float control1_x, float control1_y,
|
||||||
user_data_t &user_data)
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *)
|
||||||
{
|
{
|
||||||
fprintf (user_data.f, "C%d,%d %d,%d %d,%d", control1_x, user_data.ascender - control1_y,
|
fprintf (draw_data->f, "C%g,%g %g,%g %g,%g", control1_x, draw_data->ascender - control1_y,
|
||||||
control2_x, user_data.ascender - control2_y,
|
control2_x, draw_data->ascender - control2_y,
|
||||||
to_x, user_data.ascender - to_y);
|
to_x, draw_data->ascender - to_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_path (user_data_t &user_data)
|
close_path (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
void *)
|
||||||
{
|
{
|
||||||
fprintf (user_data.f, "Z");
|
fprintf (draw_data->f, "Z");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -218,9 +230,9 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index
|
||||||
" viewBox=\"%d %d %d %d\">\n",
|
" viewBox=\"%d %d %d %d\">\n",
|
||||||
extents.x_bearing, 0,
|
extents.x_bearing, 0,
|
||||||
extents.x_bearing + extents.width, -extents.height);
|
extents.x_bearing + extents.width, -extents.height);
|
||||||
user_data_t user_data;
|
draw_data_t draw_data;
|
||||||
user_data.ascender = extents.y_bearing;
|
draw_data.ascender = extents.y_bearing;
|
||||||
user_data.f = f;
|
draw_data.f = f;
|
||||||
|
|
||||||
for (unsigned layer = 0; layer < num_layers; ++layer)
|
for (unsigned layer = 0; layer < num_layers; ++layer)
|
||||||
{
|
{
|
||||||
|
@ -232,8 +244,7 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index
|
||||||
if (hb_color_get_alpha (color) != 255)
|
if (hb_color_get_alpha (color) != 255)
|
||||||
fprintf (f, "fill-opacity=\"%.3f\"", (double) hb_color_get_alpha (color) / 255.);
|
fprintf (f, "fill-opacity=\"%.3f\"", (double) hb_color_get_alpha (color) / 255.);
|
||||||
fprintf (f, "d=\"");
|
fprintf (f, "d=\"");
|
||||||
if (!hb_font_draw_glyph (font, layers[layer].glyph, funcs, &user_data))
|
hb_font_get_glyph_shape (font, layers[layer].glyph, funcs, &draw_data);
|
||||||
printf ("Failed to decompose layer %d while %d\n", layers[layer].glyph, gid);
|
|
||||||
fprintf (f, "\"/>\n");
|
fprintf (f, "\"/>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,11 +280,10 @@ dump_glyphs (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index)
|
||||||
" viewBox=\"%d %d %d %d\"><path d=\"",
|
" viewBox=\"%d %d %d %d\"><path d=\"",
|
||||||
extents.x_bearing, 0,
|
extents.x_bearing, 0,
|
||||||
extents.x_bearing + extents.width, font_extents.ascender - font_extents.descender);
|
extents.x_bearing + extents.width, font_extents.ascender - font_extents.descender);
|
||||||
user_data_t user_data;
|
draw_data_t draw_data;
|
||||||
user_data.ascender = font_extents.ascender;
|
draw_data.ascender = font_extents.ascender;
|
||||||
user_data.f = f;
|
draw_data.f = f;
|
||||||
if (!hb_font_draw_glyph (font, gid, funcs, &user_data))
|
hb_font_get_glyph_shape (font, gid, funcs, &draw_data);
|
||||||
printf ("Failed to decompose gid: %d\n", gid);
|
|
||||||
fprintf (f, "\"/></svg>");
|
fprintf (f, "\"/></svg>");
|
||||||
fclose (f);
|
fclose (f);
|
||||||
}
|
}
|
||||||
|
@ -300,11 +310,11 @@ dump_glyphs (hb_blob_t *blob, const char *font_name)
|
||||||
fclose (font_name_file);
|
fclose (font_name_file);
|
||||||
|
|
||||||
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
||||||
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to);
|
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, nullptr, nullptr);
|
||||||
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to);
|
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, nullptr, nullptr);
|
||||||
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to);
|
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, nullptr, nullptr);
|
||||||
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to);
|
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, nullptr, nullptr);
|
||||||
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path);
|
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, nullptr, nullptr);
|
||||||
|
|
||||||
unsigned num_faces = hb_face_count (blob);
|
unsigned num_faces = hb_face_count (blob);
|
||||||
for (unsigned face_index = 0; face_index < num_faces; ++face_index)
|
for (unsigned face_index = 0; face_index < num_faces; ++face_index)
|
||||||
|
@ -512,7 +522,7 @@ main (int argc, char **argv)
|
||||||
#ifndef MAIN_CC_NO_PRIVATE_API
|
#ifndef MAIN_CC_NO_PRIVATE_API
|
||||||
print_layout_info_using_private_api (blob);
|
print_layout_info_using_private_api (blob);
|
||||||
#endif
|
#endif
|
||||||
#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API)
|
#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW)
|
||||||
dump_glyphs (blob, argv[1]);
|
dump_glyphs (blob, argv[1]);
|
||||||
#endif
|
#endif
|
||||||
hb_blob_destroy (blob);
|
hb_blob_destroy (blob);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
directory=cairo
|
directory=cairo
|
||||||
url=https://gitlab.freedesktop.org/cairo/cairo.git
|
url=https://gitlab.freedesktop.org/cairo/cairo.git
|
||||||
depth=1
|
depth=1
|
||||||
revision=1.17.4
|
revision=c90faeb7492b1b778d18a796afe5c2e4b32a6356
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
dependency_names = cairo, cairo-ft
|
dependency_names = cairo, cairo-ft
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -163,11 +163,9 @@ test_font (hb_font_t *font, hb_codepoint_t cp)
|
||||||
hb_ot_var_normalize_variations (face, NULL, 0, NULL, 0);
|
hb_ot_var_normalize_variations (face, NULL, 0, NULL, 0);
|
||||||
hb_ot_var_normalize_coords (face, 0, NULL, NULL);
|
hb_ot_var_normalize_coords (face, 0, NULL, NULL);
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
||||||
hb_font_draw_glyph (font, cp, funcs, NULL);
|
hb_font_get_glyph_shape (font, cp, funcs, NULL);
|
||||||
hb_draw_funcs_destroy (funcs);
|
hb_draw_funcs_destroy (funcs);
|
||||||
#endif
|
|
||||||
|
|
||||||
hb_set_destroy (set);
|
hb_set_destroy (set);
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
static void
|
static void
|
||||||
test_get_var_coords (void)
|
test_get_var_coords (void)
|
||||||
{
|
{
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
#ifndef G_APPROX_VALUE
|
#ifndef G_APPROX_VALUE
|
||||||
#define G_APPROX_VALUE(a, b, epsilon) \
|
#define G_APPROX_VALUE(a, b, epsilon) \
|
||||||
(((a) > (b) ? (a) - (b) : (b) - (a)) < (epsilon))
|
(((a) > (b) ? (a) - (b) : (b) - (a)) < (epsilon))
|
||||||
|
@ -66,7 +65,6 @@ test_get_var_coords (void)
|
||||||
|
|
||||||
hb_font_destroy (font);
|
hb_font_destroy (font);
|
||||||
hb_face_destroy (face);
|
hb_face_destroy (face);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -5,77 +5,80 @@
|
||||||
|
|
||||||
#include "hb-fuzzer.hh"
|
#include "hb-fuzzer.hh"
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
struct _draw_data_t
|
||||||
struct _user_data_t
|
|
||||||
{
|
{
|
||||||
bool is_open;
|
|
||||||
unsigned path_len;
|
unsigned path_len;
|
||||||
hb_position_t path_start_x;
|
float path_start_x;
|
||||||
hb_position_t path_start_y;
|
float path_start_y;
|
||||||
hb_position_t path_last_x;
|
float path_last_x;
|
||||||
hb_position_t path_last_y;
|
float path_last_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_move_to (hb_position_t to_x, hb_position_t to_y, void *user_data_)
|
_move_to (hb_draw_funcs_t *dfuncs, void *draw_data_,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
_user_data_t *user_data = (_user_data_t *) user_data_;
|
_draw_data_t *draw_data = (_draw_data_t *) draw_data_;
|
||||||
assert (!user_data->is_open);
|
assert (!st->path_open);
|
||||||
user_data->is_open = true;
|
draw_data->path_start_x = draw_data->path_last_x = to_x;
|
||||||
user_data->path_start_x = user_data->path_last_x = to_x;
|
draw_data->path_start_y = draw_data->path_last_y = to_y;
|
||||||
user_data->path_start_y = user_data->path_last_y = to_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_line_to (hb_position_t to_x, hb_position_t to_y, void *user_data_)
|
_line_to (hb_draw_funcs_t *dfuncs, void *draw_data_,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
_user_data_t *user_data = (_user_data_t *) user_data_;
|
_draw_data_t *draw_data = (_draw_data_t *) draw_data_;
|
||||||
assert (user_data->is_open);
|
assert (st->path_open);
|
||||||
assert (user_data->path_last_x != to_x || user_data->path_last_y != to_y);
|
++draw_data->path_len;
|
||||||
++user_data->path_len;
|
draw_data->path_last_x = to_x;
|
||||||
user_data->path_last_x = to_x;
|
draw_data->path_last_y = to_y;
|
||||||
user_data->path_last_y = to_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_quadratic_to (hb_position_t control_x, hb_position_t control_y,
|
_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data_,
|
||||||
hb_position_t to_x, hb_position_t to_y, void *user_data_)
|
hb_draw_state_t *st,
|
||||||
|
float control_x, float control_y,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
_user_data_t *user_data = (_user_data_t *) user_data_;
|
_draw_data_t *draw_data = (_draw_data_t *) draw_data_;
|
||||||
assert (user_data->is_open);
|
assert (st->path_open);
|
||||||
assert (user_data->path_last_x != control_x || user_data->path_last_y != control_y ||
|
++draw_data->path_len;
|
||||||
user_data->path_last_x != to_x || user_data->path_last_y != to_y);
|
draw_data->path_last_x = to_x;
|
||||||
++user_data->path_len;
|
draw_data->path_last_y = to_y;
|
||||||
user_data->path_last_x = to_x;
|
|
||||||
user_data->path_last_y = to_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cubic_to (hb_position_t control1_x, hb_position_t control1_y,
|
_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data_,
|
||||||
hb_position_t control2_x, hb_position_t control2_y,
|
hb_draw_state_t *st,
|
||||||
hb_position_t to_x, hb_position_t to_y, void *user_data_)
|
float control1_x, float control1_y,
|
||||||
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
_user_data_t *user_data = (_user_data_t *) user_data_;
|
_draw_data_t *draw_data = (_draw_data_t *) draw_data_;
|
||||||
assert (user_data->is_open);
|
assert (st->path_open);
|
||||||
assert (user_data->path_last_x != control1_x || user_data->path_last_y != control1_y ||
|
++draw_data->path_len;
|
||||||
user_data->path_last_x != control2_x || user_data->path_last_y != control2_y ||
|
draw_data->path_last_x = to_x;
|
||||||
user_data->path_last_x != to_x || user_data->path_last_y != to_y);
|
draw_data->path_last_y = to_y;
|
||||||
++user_data->path_len;
|
|
||||||
user_data->path_last_x = to_x;
|
|
||||||
user_data->path_last_y = to_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_close_path (void *user_data_)
|
_close_path (hb_draw_funcs_t *dfuncs, void *draw_data_,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
_user_data_t *user_data = (_user_data_t *) user_data_;
|
_draw_data_t *draw_data = (_draw_data_t *) draw_data_;
|
||||||
assert (user_data->is_open && user_data->path_len != 0);
|
assert (st->path_open && draw_data->path_len != 0);
|
||||||
user_data->path_len = 0;
|
draw_data->path_len = 0;
|
||||||
user_data->is_open = false;
|
assert (draw_data->path_start_x == draw_data->path_last_x &&
|
||||||
assert (user_data->path_start_x == user_data->path_last_x &&
|
draw_data->path_start_y == draw_data->path_last_y);
|
||||||
user_data->path_start_y == user_data->path_last_y);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Similar to test-ot-face.c's #test_font() */
|
/* Similar to test-ot-face.c's #test_font() */
|
||||||
static void misc_calls_for_gid (hb_face_t *face, hb_font_t *font, hb_set_t *set, hb_codepoint_t cp)
|
static void misc_calls_for_gid (hb_face_t *face, hb_font_t *font, hb_set_t *set, hb_codepoint_t cp)
|
||||||
|
@ -135,24 +138,19 @@ extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||||
unsigned glyph_count = hb_face_get_glyph_count (face);
|
unsigned glyph_count = hb_face_get_glyph_count (face);
|
||||||
glyph_count = glyph_count > 16 ? 16 : glyph_count;
|
glyph_count = glyph_count > 16 ? 16 : glyph_count;
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
_draw_data_t draw_data = {0, 0, 0, 0, 0};
|
||||||
_user_data_t user_data = {false, 0, 0, 0, 0, 0};
|
|
||||||
|
|
||||||
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
||||||
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) _move_to);
|
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) _move_to, nullptr, nullptr);
|
||||||
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) _line_to);
|
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) _line_to, nullptr, nullptr);
|
||||||
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) _quadratic_to);
|
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) _quadratic_to, nullptr, nullptr);
|
||||||
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) _cubic_to);
|
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) _cubic_to, nullptr, nullptr);
|
||||||
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) _close_path);
|
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) _close_path, nullptr, nullptr);
|
||||||
#endif
|
|
||||||
volatile unsigned counter = !glyph_count;
|
volatile unsigned counter = !glyph_count;
|
||||||
hb_set_t *set = hb_set_create ();
|
hb_set_t *set = hb_set_create ();
|
||||||
for (unsigned gid = 0; gid < glyph_count; ++gid)
|
for (unsigned gid = 0; gid < glyph_count; ++gid)
|
||||||
{
|
{
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
hb_font_get_glyph_shape (font, gid, funcs, &draw_data);
|
||||||
hb_font_draw_glyph (font, gid, funcs, &user_data);
|
|
||||||
assert (!user_data.is_open);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Glyph extents also may practices the similar path, call it now that is related */
|
/* Glyph extents also may practices the similar path, call it now that is related */
|
||||||
hb_glyph_extents_t extents;
|
hb_glyph_extents_t extents;
|
||||||
|
@ -166,9 +164,7 @@ extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||||
}
|
}
|
||||||
hb_set_destroy (set);
|
hb_set_destroy (set);
|
||||||
assert (counter);
|
assert (counter);
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
hb_draw_funcs_destroy (funcs);
|
hb_draw_funcs_destroy (funcs);
|
||||||
#endif
|
|
||||||
|
|
||||||
hb_font_destroy (font);
|
hb_font_destroy (font);
|
||||||
hb_face_destroy (face);
|
hb_face_destroy (face);
|
||||||
|
|
|
@ -4,6 +4,8 @@ HB_VIEW_sources = \
|
||||||
font-options.hh \
|
font-options.hh \
|
||||||
hb-view.cc \
|
hb-view.cc \
|
||||||
helper-cairo-ansi.hh \
|
helper-cairo-ansi.hh \
|
||||||
|
helper-cairo-ft.hh \
|
||||||
|
helper-cairo-user.hh \
|
||||||
helper-cairo.hh \
|
helper-cairo.hh \
|
||||||
main-font-text.hh \
|
main-font-text.hh \
|
||||||
options.hh \
|
options.hh \
|
||||||
|
|
|
@ -53,11 +53,13 @@ struct font_options_t : face_options_t
|
||||||
|
|
||||||
void post_parse (GError **error);
|
void post_parse (GError **error);
|
||||||
|
|
||||||
|
hb_bool_t sub_font = false;
|
||||||
hb_variation_t *variations = nullptr;
|
hb_variation_t *variations = nullptr;
|
||||||
unsigned int num_variations = 0;
|
unsigned int num_variations = 0;
|
||||||
int x_ppem = 0;
|
int x_ppem = 0;
|
||||||
int y_ppem = 0;
|
int y_ppem = 0;
|
||||||
double ptem = 0.;
|
double ptem = 0.;
|
||||||
|
double slant = 0.;
|
||||||
unsigned int subpixel_bits = SUBPIXEL_BITS;
|
unsigned int subpixel_bits = SUBPIXEL_BITS;
|
||||||
mutable double font_size_x = DEFAULT_FONT_SIZE;
|
mutable double font_size_x = DEFAULT_FONT_SIZE;
|
||||||
mutable double font_size_y = DEFAULT_FONT_SIZE;
|
mutable double font_size_y = DEFAULT_FONT_SIZE;
|
||||||
|
@ -73,10 +75,10 @@ static struct supported_font_funcs_t {
|
||||||
void (*func) (hb_font_t *);
|
void (*func) (hb_font_t *);
|
||||||
} supported_font_funcs[] =
|
} supported_font_funcs[] =
|
||||||
{
|
{
|
||||||
|
{"ot", hb_ot_font_set_funcs},
|
||||||
#ifdef HAVE_FREETYPE
|
#ifdef HAVE_FREETYPE
|
||||||
{"ft", hb_ft_font_set_funcs},
|
{"ft", hb_ft_font_set_funcs},
|
||||||
#endif
|
#endif
|
||||||
{"ot", hb_ot_font_set_funcs},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,6 +96,8 @@ font_options_t::post_parse (GError **error)
|
||||||
hb_font_set_ppem (font, x_ppem, y_ppem);
|
hb_font_set_ppem (font, x_ppem, y_ppem);
|
||||||
hb_font_set_ptem (font, ptem);
|
hb_font_set_ptem (font, ptem);
|
||||||
|
|
||||||
|
hb_font_set_synthetic_slant (font, slant);
|
||||||
|
|
||||||
int scale_x = (int) scalbnf (font_size_x, subpixel_bits);
|
int scale_x = (int) scalbnf (font_size_x, subpixel_bits);
|
||||||
int scale_y = (int) scalbnf (font_size_y, subpixel_bits);
|
int scale_y = (int) scalbnf (font_size_y, subpixel_bits);
|
||||||
hb_font_set_scale (font, scale_x, scale_y);
|
hb_font_set_scale (font, scale_x, scale_y);
|
||||||
|
@ -137,6 +141,14 @@ font_options_t::post_parse (GError **error)
|
||||||
#ifdef HAVE_FREETYPE
|
#ifdef HAVE_FREETYPE
|
||||||
hb_ft_font_set_load_flags (font, ft_load_flags);
|
hb_ft_font_set_load_flags (font, ft_load_flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (sub_font)
|
||||||
|
{
|
||||||
|
hb_font_t *old_font = font;
|
||||||
|
font = hb_font_create_sub_font (old_font);
|
||||||
|
hb_font_set_scale (old_font, scale_x * 2, scale_y * 2);
|
||||||
|
hb_font_destroy (old_font);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,7 +277,11 @@ font_options_t::add_options (option_parser_t *parser)
|
||||||
G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_ppem, "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"},
|
G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_ppem, "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"},
|
||||||
{"font-ptem", 0, 0,
|
{"font-ptem", 0, 0,
|
||||||
G_OPTION_ARG_DOUBLE, &this->ptem, "Set font point-size (default: 0; disabled)", "point-size"},
|
G_OPTION_ARG_DOUBLE, &this->ptem, "Set font point-size (default: 0; disabled)", "point-size"},
|
||||||
|
{"font-slant", 0, 0,
|
||||||
|
G_OPTION_ARG_DOUBLE, &this->slant, "Set synthetic slant (default: 0)", "slant ratio; eg. 0.2"},
|
||||||
{"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"},
|
{"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"},
|
||||||
|
{"sub-font", 0, G_OPTION_FLAG_HIDDEN,
|
||||||
|
G_OPTION_ARG_NONE, &this->sub_font, "Create a sub-font (default: false)", "boolean"},
|
||||||
{"ft-load-flags", 0, 0, G_OPTION_ARG_INT, &this->ft_load_flags, "Set FreeType load-flags (default: 2)", "integer"},
|
{"ft-load-flags", 0, 0, G_OPTION_ARG_INT, &this->ft_load_flags, "Set FreeType load-flags (default: 2)", "integer"},
|
||||||
{nullptr}
|
{nullptr}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2022 Google, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Google Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HELPER_CAIRO_FT_HH
|
||||||
|
#define HELPER_CAIRO_FT_HH
|
||||||
|
|
||||||
|
#include "font-options.hh"
|
||||||
|
|
||||||
|
#include <cairo-ft.h>
|
||||||
|
#include <hb-ft.h>
|
||||||
|
#include FT_MULTIPLE_MASTERS_H
|
||||||
|
|
||||||
|
static FT_Library ft_library;
|
||||||
|
|
||||||
|
#ifdef HAVE_ATEXIT
|
||||||
|
static inline
|
||||||
|
void free_ft_library ()
|
||||||
|
{
|
||||||
|
FT_Done_FreeType (ft_library);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline cairo_font_face_t *
|
||||||
|
helper_cairo_create_ft_font_face (const font_options_t *font_opts)
|
||||||
|
{
|
||||||
|
cairo_font_face_t *cairo_face;
|
||||||
|
/* We cannot use the FT_Face from hb_font_t, as doing so will confuse hb_font_t because
|
||||||
|
* cairo will reset the face size. As such, create new face...
|
||||||
|
* TODO Perhaps add API to hb-ft to encapsulate this code. */
|
||||||
|
FT_Face ft_face = nullptr;//hb_ft_font_get_face (font);
|
||||||
|
if (!ft_face)
|
||||||
|
{
|
||||||
|
if (!ft_library)
|
||||||
|
{
|
||||||
|
FT_Init_FreeType (&ft_library);
|
||||||
|
#ifdef HAVE_ATEXIT
|
||||||
|
atexit (free_ft_library);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int blob_length;
|
||||||
|
const char *blob_data = hb_blob_get_data (font_opts->blob, &blob_length);
|
||||||
|
|
||||||
|
if (FT_New_Memory_Face (ft_library,
|
||||||
|
(const FT_Byte *) blob_data,
|
||||||
|
blob_length,
|
||||||
|
font_opts->face_index,
|
||||||
|
&ft_face))
|
||||||
|
fail (false, "FT_New_Memory_Face fail");
|
||||||
|
}
|
||||||
|
if (!ft_face)
|
||||||
|
{
|
||||||
|
/* This allows us to get some boxes at least... */
|
||||||
|
cairo_face = cairo_toy_font_face_create ("@cairo:sans",
|
||||||
|
CAIRO_FONT_SLANT_NORMAL,
|
||||||
|
CAIRO_FONT_WEIGHT_NORMAL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FT_SET_VAR_BLEND_COORDINATES
|
||||||
|
unsigned int num_coords;
|
||||||
|
const int *coords = hb_font_get_var_coords_normalized (font_opts->font, &num_coords);
|
||||||
|
if (num_coords)
|
||||||
|
{
|
||||||
|
FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
|
||||||
|
if (ft_coords)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < num_coords; i++)
|
||||||
|
ft_coords[i] = coords[i] << 2;
|
||||||
|
FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
|
||||||
|
free (ft_coords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, font_opts->ft_load_flags);
|
||||||
|
}
|
||||||
|
return cairo_face;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
helper_cairo_ft_scaled_font_has_color (cairo_scaled_font_t *scaled_font)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
#ifdef FT_HAS_COLOR
|
||||||
|
FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
|
||||||
|
if (ft_face)
|
||||||
|
{
|
||||||
|
if (FT_HAS_COLOR (ft_face))
|
||||||
|
ret = true;
|
||||||
|
cairo_ft_scaled_font_unlock_face (scaled_font);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,316 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2022 Google, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Google Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HELPER_CAIRO_USER_HH
|
||||||
|
#define HELPER_CAIRO_USER_HH
|
||||||
|
|
||||||
|
#include "font-options.hh"
|
||||||
|
|
||||||
|
#include <cairo.h>
|
||||||
|
#include <hb.h>
|
||||||
|
|
||||||
|
#include "hb-blob.hh"
|
||||||
|
|
||||||
|
static void
|
||||||
|
move_to (hb_draw_funcs_t *dfuncs,
|
||||||
|
cairo_t *cr,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *)
|
||||||
|
{
|
||||||
|
cairo_move_to (cr,
|
||||||
|
(double) to_x, (double) to_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
line_to (hb_draw_funcs_t *dfuncs,
|
||||||
|
cairo_t *cr,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *)
|
||||||
|
{
|
||||||
|
cairo_line_to (cr,
|
||||||
|
(double) to_x, (double) to_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cubic_to (hb_draw_funcs_t *dfuncs,
|
||||||
|
cairo_t *cr,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
float control1_x, float control1_y,
|
||||||
|
float control2_x, float control2_y,
|
||||||
|
float to_x, float to_y,
|
||||||
|
void *)
|
||||||
|
{
|
||||||
|
cairo_curve_to (cr,
|
||||||
|
(double) control1_x, (double) control1_y,
|
||||||
|
(double) control2_x, (double) control2_y,
|
||||||
|
(double) to_x, (double) to_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
close_path (hb_draw_funcs_t *dfuncs,
|
||||||
|
cairo_t *cr,
|
||||||
|
hb_draw_state_t *st,
|
||||||
|
void *)
|
||||||
|
{
|
||||||
|
cairo_close_path (cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static hb_draw_funcs_t *
|
||||||
|
get_cairo_draw_funcs ()
|
||||||
|
{
|
||||||
|
static hb_draw_funcs_t *funcs;
|
||||||
|
|
||||||
|
if (!funcs)
|
||||||
|
{
|
||||||
|
funcs = hb_draw_funcs_create ();
|
||||||
|
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, nullptr, nullptr);
|
||||||
|
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, nullptr, nullptr);
|
||||||
|
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, nullptr, nullptr);
|
||||||
|
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return funcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const cairo_user_data_key_t _hb_font_cairo_user_data_key = {0};
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
render_glyph (cairo_scaled_font_t *scaled_font,
|
||||||
|
unsigned long glyph,
|
||||||
|
cairo_t *cr,
|
||||||
|
cairo_text_extents_t *extents)
|
||||||
|
{
|
||||||
|
hb_font_t *font = (hb_font_t *) (cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
|
||||||
|
&_hb_font_cairo_user_data_key));
|
||||||
|
|
||||||
|
hb_position_t x_scale, y_scale;
|
||||||
|
hb_font_get_scale (font, &x_scale, &y_scale);
|
||||||
|
cairo_scale (cr, +1./x_scale, -1./y_scale);
|
||||||
|
|
||||||
|
hb_font_get_glyph_shape (font, glyph, get_cairo_draw_funcs (), cr);
|
||||||
|
cairo_fill (cr);
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
|
||||||
|
|
||||||
|
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
||||||
|
static inline cairo_status_t
|
||||||
|
_hb_bytes_read_func (hb_bytes_t *src,
|
||||||
|
char *data,
|
||||||
|
unsigned length)
|
||||||
|
{
|
||||||
|
if (unlikely (src->length < length))
|
||||||
|
return CAIRO_STATUS_READ_ERROR;
|
||||||
|
|
||||||
|
memcpy (data, src->arrayZ, length);
|
||||||
|
*src += length;
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
render_color_glyph_png (cairo_scaled_font_t *scaled_font,
|
||||||
|
unsigned long glyph,
|
||||||
|
cairo_t *cr,
|
||||||
|
cairo_text_extents_t *extents)
|
||||||
|
{
|
||||||
|
hb_font_t *font = (hb_font_t *) (cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
|
||||||
|
&_hb_font_cairo_user_data_key));
|
||||||
|
|
||||||
|
hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, glyph);
|
||||||
|
if (blob == hb_blob_get_empty ())
|
||||||
|
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
hb_position_t x_scale, y_scale;
|
||||||
|
hb_font_get_scale (font, &x_scale, &y_scale);
|
||||||
|
cairo_scale (cr, +1./x_scale, -1./y_scale);
|
||||||
|
|
||||||
|
/* Draw PNG. */
|
||||||
|
hb_bytes_t bytes = blob->as_bytes ();
|
||||||
|
cairo_surface_t *surface = cairo_image_surface_create_from_png_stream ((cairo_read_func_t) _hb_bytes_read_func,
|
||||||
|
std::addressof (bytes));
|
||||||
|
hb_blob_destroy (blob);
|
||||||
|
|
||||||
|
if (unlikely (cairo_surface_status (surface)) != CAIRO_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = cairo_image_surface_get_width (surface);
|
||||||
|
int height = cairo_image_surface_get_width (surface);
|
||||||
|
|
||||||
|
hb_glyph_extents_t hb_extents;
|
||||||
|
if (unlikely (!hb_font_get_glyph_extents (font, glyph, &hb_extents)))
|
||||||
|
{
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
|
||||||
|
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
|
||||||
|
|
||||||
|
cairo_matrix_t matrix = {(double) width, 0, 0, (double) height, 0, 0};
|
||||||
|
cairo_pattern_set_matrix (pattern, &matrix);
|
||||||
|
|
||||||
|
cairo_translate (cr, hb_extents.x_bearing, hb_extents.y_bearing);
|
||||||
|
cairo_scale (cr, hb_extents.width, hb_extents.height);
|
||||||
|
cairo_set_source (cr, pattern);
|
||||||
|
|
||||||
|
cairo_rectangle (cr, 0, 0, 1, 1);
|
||||||
|
cairo_fill (cr);
|
||||||
|
cairo_pattern_destroy (pattern);
|
||||||
|
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
render_color_glyph_layers (cairo_scaled_font_t *scaled_font,
|
||||||
|
unsigned long glyph,
|
||||||
|
cairo_t *cr,
|
||||||
|
cairo_text_extents_t *extents)
|
||||||
|
{
|
||||||
|
hb_font_t *font = (hb_font_t *) (cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
|
||||||
|
&_hb_font_cairo_user_data_key));
|
||||||
|
hb_face_t *face = hb_font_get_face (font);
|
||||||
|
|
||||||
|
unsigned count = hb_ot_color_glyph_get_layers (face, glyph, 0, nullptr, nullptr);
|
||||||
|
if (!count)
|
||||||
|
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
hb_ot_color_layer_t layers[16];
|
||||||
|
unsigned offset = 0, len;
|
||||||
|
do {
|
||||||
|
len = ARRAY_LENGTH (layers);
|
||||||
|
hb_ot_color_glyph_get_layers (face, glyph,
|
||||||
|
offset,
|
||||||
|
&len,
|
||||||
|
layers);
|
||||||
|
for (unsigned i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
hb_color_t color;
|
||||||
|
unsigned clen = 1;
|
||||||
|
unsigned color_index = layers[i].color_index;
|
||||||
|
bool is_foreground = color_index == 65535;
|
||||||
|
|
||||||
|
if (!is_foreground)
|
||||||
|
{
|
||||||
|
hb_ot_color_palette_get_colors (face,
|
||||||
|
0/*palette_index*/,
|
||||||
|
color_index/*start_offset*/,
|
||||||
|
&clen/*color_count*/,
|
||||||
|
&color);
|
||||||
|
if (clen < 1)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_save (cr);
|
||||||
|
{
|
||||||
|
if (!is_foreground)
|
||||||
|
cairo_set_source_rgba (cr,
|
||||||
|
hb_color_get_red (color) / 255.,
|
||||||
|
hb_color_get_green (color) / 255.,
|
||||||
|
hb_color_get_blue (color) / 255.,
|
||||||
|
hb_color_get_alpha (color) / 255.);
|
||||||
|
|
||||||
|
cairo_status_t ret = render_glyph (scaled_font, layers[i].glyph, cr, extents);
|
||||||
|
if (ret != CAIRO_STATUS_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
cairo_restore (cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (len == ARRAY_LENGTH (layers));
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
render_color_glyph (cairo_scaled_font_t *scaled_font,
|
||||||
|
unsigned long glyph,
|
||||||
|
cairo_t *cr,
|
||||||
|
cairo_text_extents_t *extents)
|
||||||
|
{
|
||||||
|
cairo_status_t ret = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
||||||
|
ret = render_color_glyph_png (scaled_font, glyph, cr, extents);
|
||||||
|
if (ret != CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = render_color_glyph_layers (scaled_font, glyph, cr, extents);
|
||||||
|
if (ret != CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return render_glyph (scaled_font, glyph, cr, extents);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline cairo_font_face_t *
|
||||||
|
helper_cairo_create_user_font_face (const font_options_t *font_opts)
|
||||||
|
{
|
||||||
|
cairo_font_face_t *cairo_face = cairo_user_font_face_create ();
|
||||||
|
|
||||||
|
cairo_font_face_set_user_data (cairo_face,
|
||||||
|
&_hb_font_cairo_user_data_key,
|
||||||
|
hb_font_reference (font_opts->font),
|
||||||
|
(cairo_destroy_func_t) hb_font_destroy);
|
||||||
|
|
||||||
|
cairo_user_font_face_set_render_glyph_func (cairo_face, render_glyph);
|
||||||
|
#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
|
||||||
|
hb_face_t *face = hb_font_get_face (font_opts->font);
|
||||||
|
if (hb_ot_color_has_png (face) || hb_ot_color_has_layers (face))
|
||||||
|
cairo_user_font_face_set_render_color_glyph_func (cairo_face, render_color_glyph);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return cairo_face;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
helper_cairo_user_font_face_has_data (cairo_font_face_t *font_face)
|
||||||
|
{
|
||||||
|
return cairo_font_face_get_user_data (font_face, &_hb_font_cairo_user_data_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
helper_cairo_user_scaled_font_has_color (cairo_scaled_font_t *scaled_font)
|
||||||
|
{
|
||||||
|
/* Ignoring SVG for now, since we cannot render it. */
|
||||||
|
hb_font_t *font = (hb_font_t *) (cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
|
||||||
|
&_hb_font_cairo_user_data_key));
|
||||||
|
hb_face_t *face = hb_font_get_face (font);
|
||||||
|
return hb_ot_color_has_png (face) || hb_ot_color_has_layers (face);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -29,10 +29,11 @@
|
||||||
|
|
||||||
#include "view-options.hh"
|
#include "view-options.hh"
|
||||||
#include "output-options.hh"
|
#include "output-options.hh"
|
||||||
|
#include "helper-cairo-ft.hh"
|
||||||
|
#include "helper-cairo-user.hh"
|
||||||
|
|
||||||
#include <cairo-ft.h>
|
#include <cairo.h>
|
||||||
#include <hb-ft.h>
|
#include <hb.h>
|
||||||
#include FT_MULTIPLE_MASTERS_H
|
|
||||||
|
|
||||||
#include "helper-cairo-ansi.hh"
|
#include "helper-cairo-ansi.hh"
|
||||||
#ifdef CAIRO_HAS_SVG_SURFACE
|
#ifdef CAIRO_HAS_SVG_SURFACE
|
||||||
|
@ -65,74 +66,27 @@ _cairo_eps_surface_create_for_stream (cairo_write_func_t write_func,
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline bool
|
||||||
static FT_Library ft_library;
|
helper_cairo_use_hb_draw (const font_options_t *font_opts)
|
||||||
|
|
||||||
#ifdef HAVE_ATEXIT
|
|
||||||
static inline
|
|
||||||
void free_ft_library ()
|
|
||||||
{
|
{
|
||||||
FT_Done_FreeType (ft_library);
|
const char *env = getenv ("HB_DRAW");
|
||||||
|
if (!env)
|
||||||
|
return cairo_version () >= CAIRO_VERSION_ENCODE (1, 17, 5);
|
||||||
|
return atoi (env);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline cairo_scaled_font_t *
|
static inline cairo_scaled_font_t *
|
||||||
helper_cairo_create_scaled_font (const font_options_t *font_opts)
|
helper_cairo_create_scaled_font (const font_options_t *font_opts)
|
||||||
{
|
{
|
||||||
|
bool use_hb_draw = helper_cairo_use_hb_draw (font_opts);
|
||||||
hb_font_t *font = hb_font_reference (font_opts->font);
|
hb_font_t *font = hb_font_reference (font_opts->font);
|
||||||
|
|
||||||
cairo_font_face_t *cairo_face;
|
cairo_font_face_t *cairo_face;
|
||||||
/* We cannot use the FT_Face from hb_font_t, as doing so will confuse hb_font_t because
|
if (use_hb_draw)
|
||||||
* cairo will reset the face size. As such, create new face...
|
cairo_face = helper_cairo_create_user_font_face (font_opts);
|
||||||
* TODO Perhaps add API to hb-ft to encapsulate this code. */
|
|
||||||
FT_Face ft_face = nullptr;//hb_ft_font_get_face (font);
|
|
||||||
if (!ft_face)
|
|
||||||
{
|
|
||||||
if (!ft_library)
|
|
||||||
{
|
|
||||||
FT_Init_FreeType (&ft_library);
|
|
||||||
#ifdef HAVE_ATEXIT
|
|
||||||
atexit (free_ft_library);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int blob_length;
|
|
||||||
const char *blob_data = hb_blob_get_data (font_opts->blob, &blob_length);
|
|
||||||
|
|
||||||
if (FT_New_Memory_Face (ft_library,
|
|
||||||
(const FT_Byte *) blob_data,
|
|
||||||
blob_length,
|
|
||||||
font_opts->face_index,
|
|
||||||
&ft_face))
|
|
||||||
fail (false, "FT_New_Memory_Face fail");
|
|
||||||
}
|
|
||||||
if (!ft_face)
|
|
||||||
{
|
|
||||||
/* This allows us to get some boxes at least... */
|
|
||||||
cairo_face = cairo_toy_font_face_create ("@cairo:sans",
|
|
||||||
CAIRO_FONT_SLANT_NORMAL,
|
|
||||||
CAIRO_FONT_WEIGHT_NORMAL);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
cairo_face = helper_cairo_create_ft_font_face (font_opts);
|
||||||
#ifdef HAVE_FT_SET_VAR_BLEND_COORDINATES
|
|
||||||
unsigned int num_coords;
|
|
||||||
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
|
|
||||||
if (num_coords)
|
|
||||||
{
|
|
||||||
FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
|
|
||||||
if (ft_coords)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < num_coords; i++)
|
|
||||||
ft_coords[i] = coords[i] << 2;
|
|
||||||
FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
|
|
||||||
free (ft_coords);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, font_opts->ft_load_flags);
|
|
||||||
}
|
|
||||||
cairo_matrix_t ctm, font_matrix;
|
cairo_matrix_t ctm, font_matrix;
|
||||||
cairo_font_options_t *font_options;
|
cairo_font_options_t *font_options;
|
||||||
|
|
||||||
|
@ -140,6 +94,9 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts)
|
||||||
cairo_matrix_init_scale (&font_matrix,
|
cairo_matrix_init_scale (&font_matrix,
|
||||||
font_opts->font_size_x,
|
font_opts->font_size_x,
|
||||||
font_opts->font_size_y);
|
font_opts->font_size_y);
|
||||||
|
if (use_hb_draw)
|
||||||
|
font_matrix.xy = -font_opts->slant * font_opts->font_size_x;
|
||||||
|
|
||||||
font_options = cairo_font_options_create ();
|
font_options = cairo_font_options_create ();
|
||||||
cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
|
cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
|
||||||
cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
|
cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
|
||||||
|
@ -165,17 +122,10 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts)
|
||||||
static inline bool
|
static inline bool
|
||||||
helper_cairo_scaled_font_has_color (cairo_scaled_font_t *scaled_font)
|
helper_cairo_scaled_font_has_color (cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
if (helper_cairo_user_font_face_has_data (cairo_scaled_font_get_font_face (scaled_font)))
|
||||||
#ifdef FT_HAS_COLOR
|
return helper_cairo_user_scaled_font_has_color (scaled_font);
|
||||||
FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
|
else
|
||||||
if (ft_face)
|
return helper_cairo_ft_scaled_font_has_color (scaled_font);
|
||||||
{
|
|
||||||
if (FT_HAS_COLOR (ft_face))
|
|
||||||
ret = true;
|
|
||||||
cairo_ft_scaled_font_unlock_face (scaled_font);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue