summaryrefslogtreecommitdiffstats
path: root/gfx/harfbuzz/src/OT/glyf/path-builder.hh
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/harfbuzz/src/OT/glyf/path-builder.hh')
-rw-r--r--gfx/harfbuzz/src/OT/glyf/path-builder.hh190
1 files changed, 190 insertions, 0 deletions
diff --git a/gfx/harfbuzz/src/OT/glyf/path-builder.hh b/gfx/harfbuzz/src/OT/glyf/path-builder.hh
new file mode 100644
index 0000000000..f550524503
--- /dev/null
+++ b/gfx/harfbuzz/src/OT/glyf/path-builder.hh
@@ -0,0 +1,190 @@
+#ifndef OT_GLYF_PATH_BUILDER_HH
+#define OT_GLYF_PATH_BUILDER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct path_builder_t
+{
+ hb_font_t *font;
+ hb_draw_session_t *draw_session;
+
+ struct optional_point_t
+ {
+ optional_point_t () {}
+ optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {}
+ operator bool () const { return has_data; }
+
+ bool has_data = false;
+ float x;
+ float y;
+
+ optional_point_t mid (optional_point_t p)
+ { return optional_point_t ((x + p.x) * 0.5f, (y + p.y) * 0.5f); }
+ } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2;
+
+ path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) :
+ font (font_), draw_session (&draw_session_) {}
+
+ /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
+ See also:
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
+ * https://stackoverflow.com/a/20772557
+ *
+ * Cubic support added. */
+ HB_ALWAYS_INLINE
+ void consume_point (const contour_point_t &point)
+ {
+ bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
+#ifdef HB_NO_CUBIC_GLYF
+ bool is_cubic = false;
+#else
+ bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
+#endif
+ optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
+ if (unlikely (!first_oncurve))
+ {
+ if (is_on_curve)
+ {
+ first_oncurve = p;
+ draw_session->move_to (p.x, p.y);
+ }
+ else
+ {
+ if (is_cubic && !first_offcurve2)
+ {
+ first_offcurve2 = first_offcurve;
+ first_offcurve = p;
+ }
+ else if (first_offcurve)
+ {
+ optional_point_t mid = first_offcurve.mid (p);
+ first_oncurve = mid;
+ last_offcurve = p;
+ draw_session->move_to (mid.x, mid.y);
+ }
+ else
+ first_offcurve = p;
+ }
+ }
+ else
+ {
+ if (last_offcurve)
+ {
+ if (is_on_curve)
+ {
+ if (last_offcurve2)
+ {
+ draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+ last_offcurve.x, last_offcurve.y,
+ p.x, p.y);
+ last_offcurve2 = optional_point_t ();
+ }
+ else
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ p.x, p.y);
+ last_offcurve = optional_point_t ();
+ }
+ else
+ {
+ if (is_cubic && !last_offcurve2)
+ {
+ last_offcurve2 = last_offcurve;
+ last_offcurve = p;
+ }
+ else
+ {
+ optional_point_t mid = last_offcurve.mid (p);
+
+ if (is_cubic)
+ {
+ draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+ last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve2 = optional_point_t ();
+ }
+ else
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve = p;
+ }
+ }
+ }
+ else
+ {
+ if (is_on_curve)
+ draw_session->line_to (p.x, p.y);
+ else
+ last_offcurve = p;
+ }
+ }
+
+ if (unlikely (point.is_end_point))
+ {
+ if (first_offcurve && last_offcurve)
+ {
+ optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
+ first_offcurve2 :
+ first_offcurve);
+ if (last_offcurve2)
+ draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+ last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ else
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve = optional_point_t ();
+ }
+ /* now check the rest */
+
+ if (first_offcurve && first_oncurve)
+ {
+ if (first_offcurve2)
+ draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
+ first_offcurve.x, first_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else
+ draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ }
+ else if (last_offcurve && first_oncurve)
+ {
+ if (last_offcurve2)
+ draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+ last_offcurve.x, last_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ }
+ else if (first_oncurve)
+ draw_session->line_to (first_oncurve.x, first_oncurve.y);
+ else if (first_offcurve)
+ {
+ float x = first_offcurve.x, y = first_offcurve.y;
+ draw_session->move_to (x, y);
+ draw_session->quadratic_to (x, y, x, y);
+ }
+
+ /* Getting ready for the next contour */
+ first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
+ draw_session->close_path ();
+ }
+ }
+ void points_end () {}
+
+ bool is_consuming_contour_points () { return true; }
+ contour_point_t *get_phantoms_sink () { return nullptr; }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_PATH_BUILDER_HH */