From c0c85b852d37dad75eeef473e6dd3ec91a3b559b Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Mon, 17 Sep 2018 11:14:56 -0700 Subject: [PATCH] implemented get_glyph_extents with CFF1 Implemented path operators in a new struct PathProc hooked up to CSOpSet Added current point to CSInterpEnv --- src/hb-cff-interp-common.hh | 86 ++++++- src/hb-cff-interp-cs-common.hh | 429 +++++++++++++++++++++++++++++++-- src/hb-cff1-interp-cs.hh | 18 +- src/hb-cff2-interp-cs.hh | 10 +- src/hb-null.hh | 2 +- src/hb-ot-cff1-table.cc | 82 +++++++ src/hb-ot-cff1-table.hh | 95 ++++---- src/hb-ot-face.cc | 1 + src/hb-ot-face.hh | 1 + src/hb-ot-font.cc | 2 + src/hb-subset-cff1.cc | 4 +- src/hb-subset-cff2.cc | 10 +- 12 files changed, 659 insertions(+), 81 deletions(-) diff --git a/src/hb-cff-interp-common.hh b/src/hb-cff-interp-common.hh index ea702095d..cd5552dbb 100644 --- a/src/hb-cff-interp-common.hh +++ b/src/hb-cff-interp-common.hh @@ -237,6 +237,35 @@ struct Number else return (float)u.int_val; } + + inline int ceil (void) const + { + switch (format) + { + default: + case NumInt: + return u.int_val; + case NumFixed: + return (u.fixed_val + 0xFFFF) >> 16; + case NumReal: + return (int)ceilf (u.real_val); + } + } + + inline int floor (void) const + { + switch (format) + { + default: + case NumInt: + return u.int_val; + case NumFixed: + return u.fixed_val >> 16; + case NumReal: + return (int)floorf (u.real_val); + } + } + inline bool in_int_range (void) const { if (is_int ()) @@ -247,6 +276,44 @@ struct Number return ((float)(int16_t)to_int () == u.real_val); } + inline bool operator > (const Number &n) const + { + switch (format) + { + default: + case NumInt: return u.int_val > n.to_int (); + case NumFixed: return u.fixed_val > n.to_fixed (); + case NumReal: return u.real_val > n.to_real (); + } + } + + inline bool operator < (const Number &n) const + { return n > *this; } + + inline bool operator >= (const Number &n) const + { return ! (*this < n); } + + inline bool operator <= (const Number &n) const + { return ! (*this > n); } + + inline const Number &operator += (const Number &n) + { + switch (format) + { + default: + case NumInt: + u.int_val += n.to_int (); + break; + case NumFixed: + u.fixed_val += n.to_fixed (); + break; + case NumReal: + u.real_val += n.to_real (); + break; + } + return *this; + } + protected: enum NumFormat { NumInt, @@ -390,6 +457,12 @@ struct Stack elements[i].fini (); } + inline const ELEM& operator [] (unsigned int i) const + { return elements[i]; } + + inline ELEM& operator [] (unsigned int i) + { return elements[i]; } + inline void push (const ELEM &v) { if (likely (count < elements.len)) @@ -412,6 +485,12 @@ struct Stack return Null(ELEM); } + inline void pop (unsigned int n) + { + if (likely (count >= n)) + count -= n; + } + inline const ELEM& peek (void) { if (likely (count > 0)) @@ -436,6 +515,7 @@ struct Stack static const unsigned int kSizeLimit = LIMIT; + protected: unsigned int count; hb_vector_t elements; }; @@ -597,13 +677,13 @@ struct InterpEnv inline void pop_n_args (unsigned int n) { - assert (n <= argStack.count); - argStack.count -= n; + assert (n <= argStack.get_count ()); + argStack.pop (n); } inline void clear_args (void) { - pop_n_args (argStack.count); + pop_n_args (argStack.get_count ()); } SubByteStr substr; diff --git a/src/hb-cff-interp-cs-common.hh b/src/hb-cff-interp-cs-common.hh index ef7b05612..dad7f6ddd 100644 --- a/src/hb-cff-interp-cs-common.hh +++ b/src/hb-cff-interp-cs-common.hh @@ -57,6 +57,22 @@ struct BiasedSubrs unsigned int bias; }; +struct Point +{ + inline void init (void) + { + x.init (); + y.init (); + } + + inline void move_x (const Number &dx) { x += dx; } + inline void move_y (const Number &dy) { y += dy; } + inline void move (const Number &dx, const Number &dy) { move_x (dx); move_y (dy); } + + Number x; + Number y; +}; + template struct CSInterpEnv : InterpEnv { @@ -68,6 +84,7 @@ struct CSInterpEnv : InterpEnv seen_hintmask = false; hstem_count = 0; vstem_count = 0; + pt.init (); callStack.init (); globalSubrs.init (globalSubrs_); localSubrs.init (localSubrs_); @@ -129,6 +146,30 @@ struct CSInterpEnv : InterpEnv inline void set_endchar (bool endchar_flag_) { endchar_flag = endchar_flag_; } inline bool is_endchar (void) const { return endchar_flag; } + inline const Number &get_x (void) const { return pt.x; } + inline const Number &get_y (void) const { return pt.y; } + inline const Point &get_pt (void) const { return pt; } + + inline void moveto (const Point &pt_ ) { pt = pt_; } + + inline unsigned int move_x_with_arg (unsigned int i) + { + pt.move_x (SUPER::argStack[i]); + return i + 1; + } + + inline unsigned int move_y_with_arg (unsigned int i) + { + pt.move_y (SUPER::argStack[i]); + return i + 1; + } + + inline unsigned int move_xy_with_arg (unsigned int i) + { + pt.move (SUPER::argStack[i], SUPER::argStack[i+1]); + return i + 2; + } + public: bool endchar_flag; bool seen_moveto; @@ -142,10 +183,33 @@ struct CSInterpEnv : InterpEnv BiasedSubrs localSubrs; private: + Point pt; + typedef InterpEnv SUPER; }; -template +template +struct PathProcsNull +{ + static inline void rmoveto (ENV &env, PARAM& param) {} + static inline void hmoveto (ENV &env, PARAM& param) {} + static inline void vmoveto (ENV &env, PARAM& param) {} + static inline void rlineto (ENV &env, PARAM& param) {} + static inline void hlineto (ENV &env, PARAM& param) {} + static inline void vlineto (ENV &env, PARAM& param) {} + static inline void rrcurveto (ENV &env, PARAM& param) {} + static inline void rcurveline (ENV &env, PARAM& param) {} + static inline void rlinecurve (ENV &env, PARAM& param) {} + static inline void vvcurveto (ENV &env, PARAM& param) {} + static inline void hhcurveto (ENV &env, PARAM& param) {} + static inline void vhcurveto (ENV &env, PARAM& param) {} + static inline void hvcurveto (ENV &env, PARAM& param) {} + static inline void moveto (ENV &env, PARAM& param, const Point &pt) {} + static inline void line (ENV &env, PARAM& param, const Point &pt1) {} + static inline void curve (ENV &env, PARAM& param, const Point &pt1, const Point &pt2, const Point &pt3) {} +}; + +template > struct CSOpSet : OpSet { static inline bool process_op (OpCode op, ENV &env, PARAM& param) @@ -180,23 +244,57 @@ struct CSOpSet : OpSet case OpCode_cntrmask: OPSET::process_hintmask (op, env, param); break; - - case OpCode_vmoveto: - case OpCode_rlineto: - case OpCode_hlineto: - case OpCode_vlineto: case OpCode_rmoveto: + PATH::rmoveto (env, param); + process_post_move (op, env, param); + break; case OpCode_hmoveto: - OPSET::process_moveto (op, env, param); + PATH::hmoveto (env, param); + process_post_move (op, env, param); + break; + case OpCode_vmoveto: + PATH::vmoveto (env, param); + process_post_move (op, env, param); + break; + case OpCode_rlineto: + PATH::rlineto (env, param); + process_post_path (op, env, param); + break; + case OpCode_hlineto: + PATH::hlineto (env, param); + process_post_path (op, env, param); + break; + case OpCode_vlineto: + PATH::vlineto (env, param); + process_post_path (op, env, param); break; case OpCode_rrcurveto: + PATH::rrcurveto (env, param); + process_post_path (op, env, param); + break; case OpCode_rcurveline: + PATH::rcurveline (env, param); + process_post_path (op, env, param); + break; case OpCode_rlinecurve: + PATH::rlinecurve (env, param); + process_post_path (op, env, param); + break; case OpCode_vvcurveto: + PATH::vvcurveto (env, param); + process_post_path (op, env, param); + break; case OpCode_hhcurveto: + PATH::hhcurveto (env, param); + process_post_path (op, env, param); + break; case OpCode_vhcurveto: + PATH::vhcurveto (env, param); + process_post_path (op, env, param); + break; case OpCode_hvcurveto: - OPSET::process_path (op, env, param); + PATH::hvcurveto (env, param); + process_post_path (op, env, param); break; case OpCode_hflex: @@ -214,13 +312,13 @@ struct CSOpSet : OpSet static inline void process_hstem (OpCode op, ENV &env, PARAM& param) { - env.hstem_count += env.argStack.count / 2; + env.hstem_count += env.argStack.get_count () / 2; OPSET::flush_args_and_op (op, env, param); } static inline void process_vstem (OpCode op, ENV &env, PARAM& param) { - env.vstem_count += env.argStack.count / 2; + env.vstem_count += env.argStack.get_count () / 2; OPSET::flush_args_and_op (op, env, param); } @@ -239,7 +337,7 @@ struct CSOpSet : OpSet OPSET::flush_args_and_op (op, env, param); } - static inline void process_moveto (OpCode op, ENV &env, PARAM& param) + static inline void process_post_move (OpCode op, ENV &env, PARAM& param) { if (!env.seen_moveto) { @@ -249,14 +347,14 @@ struct CSOpSet : OpSet OPSET::flush_args_and_op (op, env, param); } - static inline void process_path (OpCode op, ENV &env, PARAM& param) + static inline void process_post_path (OpCode op, ENV &env, PARAM& param) { OPSET::flush_args_and_op (op, env, param); } static inline void flush_args_and_op (OpCode op, ENV &env, PARAM& param) { - OPSET::flush_n_args_and_op (op, env.argStack.count, env, param); + OPSET::flush_n_args_and_op (op, env.argStack.get_count (), env, param); } static inline void flush_n_args_and_op (OpCode op, unsigned int n, ENV &env, PARAM& param) @@ -267,7 +365,7 @@ struct CSOpSet : OpSet static inline void flush_args (ENV &env, PARAM& param) { - OPSET::flush_n_args (env.argStack.count, env, param); + OPSET::flush_n_args (env.argStack.get_count (), env, param); } static inline void flush_n_args (unsigned int n, ENV &env, PARAM& param) @@ -297,9 +395,312 @@ struct CSOpSet : OpSet } } + protected: typedef OpSet SUPER; }; +template +struct PathProcs +{ + static inline void rmoveto (ENV &env, PARAM& param) + { + Point pt1 = env.get_pt (); + const Number &dy = env.argStack.pop (); + const Number &dx = env.argStack.pop (); + pt1.move (dx, dy); + env.moveto (pt1); + } + + static inline void hmoveto (ENV &env, PARAM& param) + { + Point pt1 = env.get_pt (); + pt1.move_x (env.argStack.pop ()); + env.moveto (pt1); + } + + static inline void vmoveto (ENV &env, PARAM& param) + { + Point pt1 = env.get_pt (); + pt1.move_y (env.argStack.pop ()); + env.moveto (pt1); + } + + static inline void rlineto (ENV &env, PARAM& param) + { + for (unsigned int i = 0; i + 2 <= env.argStack.get_count (); i += 2) + { + Point pt1 = env.get_pt (); + pt1.move (env.argStack[i], env.argStack[i+1]); + PATH::line (env, param, pt1); + } + } + + static inline void hlineto (ENV &env, PARAM& param) + { + Point pt1; + unsigned int i = 0; + for (; i + 2 <= env.argStack.get_count (); i += 2) + { + pt1 = env.get_pt (); + pt1.move_x (env.argStack[i]); + PATH::line (env, param, pt1); + pt1.move_y (env.argStack[i+1]); + PATH::line (env, param, pt1); + } + if (i < env.argStack.get_count ()) + { + pt1 = env.get_pt (); + pt1.move_x (env.argStack[i]); + PATH::line (env, param, pt1); + } + } + + static inline void vlineto (ENV &env, PARAM& param) + { + Point pt1; + unsigned int i = 0; + for (; i + 2 <= env.argStack.get_count (); i += 2) + { + pt1 = env.get_pt (); + pt1.move_y (env.argStack[i]); + PATH::line (env, param, pt1); + pt1.move_x (env.argStack[i+1]); + PATH::line (env, param, pt1); + } + if (i < env.argStack.get_count ()) + { + pt1 = env.get_pt (); + pt1.move_y (env.argStack[i]); + PATH::line (env, param, pt1); + } + } + + static inline void rrcurveto (ENV &env, PARAM& param) + { + for (unsigned int i = 0; i + 6 <= env.argStack.get_count (); i += 6) + { + Point pt1 = env.get_pt (); + pt1.move (env.argStack[i], env.argStack[i+1]); + Point pt2 = pt1; + pt2.move (env.argStack[i+2], env.argStack[i+3]); + Point pt3 = pt2; + pt3.move (env.argStack[i+4], env.argStack[i+5]); + PATH::curve (env, param, pt1, pt2, pt3); + } + } + + static inline void rcurveline (ENV &env, PARAM& param) + { + unsigned int i = 0; + for (; i + 6 <= env.argStack.get_count (); i += 6) + { + Point pt1 = env.get_pt (); + pt1.move (env.argStack[i], env.argStack[i+1]); + Point pt2 = pt1; + pt2.move (env.argStack[i+2], env.argStack[i+3]); + Point pt3 = pt2; + pt3.move (env.argStack[i+4], env.argStack[i+5]); + PATH::curve (env, param, pt1, pt2, pt3); + } + for (; i + 2 <= env.argStack.get_count (); i += 2) + { + Point pt1 = env.get_pt (); + pt1.move (env.argStack[i], env.argStack[i+1]); + PATH::line (env, param, pt1); + } + } + + static inline void rlinecurve (ENV &env, PARAM& param) + { + unsigned int i = 0; + unsigned int line_limit = (env.argStack.get_count () % 6); + for (; i + 2 <= line_limit; i += 2) + { + Point pt1 = env.get_pt (); + pt1.move (env.argStack[i], env.argStack[i+1]); + PATH::line (env, param, pt1); + } + for (; i + 6 <= env.argStack.get_count (); i += 6) + { + Point pt1 = env.get_pt (); + pt1.move (env.argStack[i], env.argStack[i+1]); + Point pt2 = pt1; + pt2.move (env.argStack[i+2], env.argStack[i+3]); + Point pt3 = pt2; + pt3.move (env.argStack[i+4], env.argStack[i+5]); + PATH::curve (env, param, pt1, pt2, pt3); + } + } + + static inline void vvcurveto (ENV &env, PARAM& param) + { + unsigned int i = 0; + Point pt1 = env.get_pt (); + if ((env.argStack.get_count () & 1) != 0) + pt1.move_x (env.argStack[i++]); + for (; i + 4 <= env.argStack.get_count (); i += 4) + { + pt1.move_y (env.argStack[i]); + Point pt2 = pt1; + pt2.move (env.argStack[i+1], env.argStack[i+2]); + Point pt3 = pt2; + pt3.move_y (env.argStack[i+3]); + PATH::curve (env, param, pt1, pt2, pt3); + pt1 = env.get_pt (); + } + } + + static inline void hhcurveto (ENV &env, PARAM& param) + { + unsigned int i = 0; + Point pt1 = env.get_pt (); + if ((env.argStack.get_count () & 1) != 0) + pt1.move_y (env.argStack[i++]); + for (; i + 4 <= env.argStack.get_count (); i += 4) + { + pt1.move_x (env.argStack[i]); + Point pt2 = pt1; + pt2.move (env.argStack[i+1], env.argStack[i+2]); + Point pt3 = pt2; + pt3.move_x (env.argStack[i+3]); + PATH::curve (env, param, pt1, pt2, pt3); + pt1 = env.get_pt (); + } + } + + static inline void vhcurveto (ENV &env, PARAM& param) + { + Point pt1, pt2, pt3; + unsigned int i = 0; + if ((env.argStack.get_count () % 8) >= 4) + { + Point pt1 = env.get_pt (); + pt1.move_y (env.argStack[i]); + Point pt2 = pt1; + pt2.move (env.argStack[i+1], env.argStack[i+2]); + Point pt3 = pt2; + pt3.move_x (env.argStack[i+3]); + i += 4; + + for (; i + 8 <= env.argStack.get_count (); i += 8) + { + PATH::curve (env, param, pt1, pt2, pt3); + pt1 = env.get_pt (); + pt1.move_x (env.argStack[i]); + pt2 = pt1; + pt2.move (env.argStack[i+1], env.argStack[i+2]); + pt3 = pt2; + pt3.move_y (env.argStack[i+3]); + PATH::curve (env, param, pt1, pt2, pt3); + + pt1 = pt3; + pt1.move_y (env.argStack[i+4]); + pt2 = pt1; + pt2.move (env.argStack[i+5], env.argStack[i+6]); + pt3 = pt2; + pt3.move_x (env.argStack[i+7]); + } + if (i < env.argStack.get_count ()) + pt3.move_y (env.argStack[i]); + PATH::curve (env, param, pt1, pt2, pt3); + } + else + { + for (; i + 8 <= env.argStack.get_count (); i += 8) + { + pt1 = env.get_pt (); + pt1.move_y (env.argStack[i]); + pt2 = pt1; + pt2.move (env.argStack[i+1], env.argStack[i+2]); + pt3 = pt2; + pt3.move_x (env.argStack[i+3]); + PATH::curve (env, param, pt1, pt2, pt3); + + pt1 = pt3; + pt1.move_x (env.argStack[i+4]); + pt2 = pt1; + pt2.move (env.argStack[i+5], env.argStack[i+6]); + pt3 = pt2; + pt3.move_y (env.argStack[i+7]); + if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0)) + pt3.move_x (env.argStack[i+8]); + PATH::curve (env, param, pt1, pt2, pt3); + } + } + } + + static inline void hvcurveto (ENV &env, PARAM& param) + { + Point pt1, pt2, pt3; + unsigned int i = 0; + if ((env.argStack.get_count () % 8) >= 4) + { + Point pt1 = env.get_pt (); + pt1.move_x (env.argStack[i]); + Point pt2 = pt1; + pt2.move (env.argStack[i+1], env.argStack[i+2]); + Point pt3 = pt2; + pt3.move_y (env.argStack[i+3]); + i += 4; + + for (; i + 8 <= env.argStack.get_count (); i += 8) + { + PATH::curve (env, param, pt1, pt2, pt3); + pt1 = env.get_pt (); + pt1.move_y (env.argStack[i]); + pt2 = pt1; + pt2.move (env.argStack[i+1], env.argStack[i+2]); + pt3 = pt2; + pt3.move_x (env.argStack[i+3]); + PATH::curve (env, param, pt1, pt2, pt3); + + pt1 = pt3; + pt1.move_x (env.argStack[i+4]); + pt2 = pt1; + pt2.move (env.argStack[i+5], env.argStack[i+6]); + pt3 = pt2; + pt3.move_y (env.argStack[i+7]); + } + if (i < env.argStack.get_count ()) + pt3.move_x (env.argStack[i]); + PATH::curve (env, param, pt1, pt2, pt3); + } + else + { + for (; i + 8 <= env.argStack.get_count (); i += 8) + { + pt1 = env.get_pt (); + pt1.move_x (env.argStack[i]); + pt2 = pt1; + pt2.move (env.argStack[i+1], env.argStack[i+2]); + pt3 = pt2; + pt3.move_y (env.argStack[i+3]); + PATH::curve (env, param, pt1, pt2, pt3); + + pt1 = pt3; + pt1.move_y (env.argStack[i+4]); + pt2 = pt1; + pt2.move (env.argStack[i+5], env.argStack[i+6]); + pt3 = pt2; + pt3.move_x (env.argStack[i+7]); + if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0)) + pt3.move_y (env.argStack[i+8]); + PATH::curve (env, param, pt1, pt2, pt3); + } + } + } + + /* default actions to be overridden */ + static inline void moveto (ENV &env, PARAM& param, const Point &pt) + { env.moveto (pt); } + + static inline void line (ENV &env, PARAM& param, const Point &pt1) + { PATH::moveto (env, param, pt1); } + + static inline void curve (ENV &env, PARAM& param, const Point &pt1, const Point &pt2, const Point &pt3) + { PATH::moveto (env, param, pt3); } +}; + template struct CSInterpreter : Interpreter { diff --git a/src/hb-cff1-interp-cs.hh b/src/hb-cff1-interp-cs.hh index 01faa44ba..29c4ad356 100644 --- a/src/hb-cff1-interp-cs.hh +++ b/src/hb-cff1-interp-cs.hh @@ -52,9 +52,9 @@ struct CFF1CSInterpEnv : CSInterpEnv { if (!processed_width) { - if ((SUPER::argStack.count & 1) != 0) + if ((SUPER::argStack.get_count () & 1) != 0) { - width = SUPER::argStack.elements[0]; + width = SUPER::argStack[0]; has_width = true; } processed_width = true; @@ -72,8 +72,8 @@ struct CFF1CSInterpEnv : CSInterpEnv typedef CSInterpEnv SUPER; }; -template -struct CFF1CSOpSet : CSOpSet +template > +struct CFF1CSOpSet : CSOpSet { static inline bool process_op (OpCode op, CFF1CSInterpEnv &env, PARAM& param) { @@ -167,8 +167,8 @@ struct CFF1CSOpSet : CSOpSet if (unlikely (!env.argStack.check_pop_num (n1))) return false; int i = n1.to_int (); if (i < 0) i = 0; - if (unlikely (i >= env.argStack.count || !env.argStack.check_overflow (1))) return false; - env.argStack.push (env.argStack.elements[env.argStack.count - i - 1]); + if (unlikely (i >= env.argStack.get_count () || !env.argStack.check_overflow (1))) return false; + env.argStack.push (env.argStack[env.argStack.get_count () - i - 1]); } break; case OpCode_roll: @@ -176,13 +176,13 @@ struct CFF1CSOpSet : CSOpSet if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; int n = n1.to_int (); int j = n2.to_int (); - if (unlikely (n < 0 || n > env.argStack.count)) return false; + if (unlikely (n < 0 || n > env.argStack.get_count ())) return false; if (likely (n > 0)) { if (j < 0) j = n - (-j % n); j %= n; - unsigned int top = env.argStack.count - 1; + unsigned int top = env.argStack.get_count () - 1; unsigned int bot = top - n + 1; env.argStack.reverse_range (top - j + 1, top); env.argStack.reverse_range (bot, top - j); @@ -205,7 +205,7 @@ struct CFF1CSOpSet : CSOpSet } private: - typedef CSOpSet SUPER; + typedef CSOpSet SUPER; }; template diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh index b5f1f8fb1..2f40de6d4 100644 --- a/src/hb-cff2-interp-cs.hh +++ b/src/hb-cff2-interp-cs.hh @@ -120,8 +120,8 @@ struct CFF2CSInterpEnv : CSInterpEnv typedef CSInterpEnv SUPER; }; -template -struct CFF2CSOpSet : CSOpSet +template > +struct CFF2CSOpSet : CSOpSet { static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, PARAM& param) { @@ -158,10 +158,10 @@ struct CFF2CSOpSet : CSOpSet /* copy the blend values into blend array of the default values */ unsigned int start = env.argStack.get_count () - ((k+1) * n); for (unsigned int i = 0; i < n; i++) - env.argStack.elements[start + i].set_blends (n, i, k, &env.argStack.elements[start + n + (i * k)]); + env.argStack[start + i].set_blends (n, i, k, &env.argStack[start + n + (i * k)]); /* pop off blend values leaving default values now adorned with blend values */ - env.argStack.count -= k * n; + env.argStack.pop (k * n); return true; } @@ -172,7 +172,7 @@ struct CFF2CSOpSet : CSOpSet } private: - typedef CSOpSet SUPER; + typedef CSOpSet SUPER; }; template diff --git a/src/hb-null.hh b/src/hb-null.hh index b7f1c1d8f..0b533c78c 100644 --- a/src/hb-null.hh +++ b/src/hb-null.hh @@ -36,7 +36,7 @@ /* Global nul-content Null pool. Enlarge as necessary. */ -#define HB_NULL_POOL_SIZE 800 +#define HB_NULL_POOL_SIZE 9880 extern HB_INTERNAL hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)]; diff --git a/src/hb-ot-cff1-table.cc b/src/hb-ot-cff1-table.cc index 9ac2f1590..6bd29834f 100644 --- a/src/hb-ot-cff1-table.cc +++ b/src/hb-ot-cff1-table.cc @@ -25,6 +25,9 @@ */ #include "hb-ot-cff1-table.hh" +#include "hb-cff1-interp-cs.hh" + +using namespace CFF; /* SID to code */ static const uint8_t standard_encoding [] = @@ -128,3 +131,82 @@ hb_codepoint_t OT::cff1::lookup_expert_subset_charset (hb_codepoint_t glyph) else return 0; } + +struct ExtentsParam +{ + inline void init (void) + { + min_x.set_int (INT32_MAX); + min_y.set_int (INT32_MAX); + max_x.set_int (INT32_MIN); + max_y.set_int (INT32_MIN); + } + + inline void update_bounds (const Point &pt) + { + if (pt.x < min_x) min_x = pt.x; + if (pt.x > max_x) max_x = pt.x; + if (pt.y < min_y) min_y = pt.y; + if (pt.y > max_y) max_y = pt.y; + } + + Number min_x; + Number min_y; + Number max_x; + Number max_y; +}; + +struct CFF1PathProcs_Extents : PathProcs +{ + static inline void line (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt1) + { + param.update_bounds (env.get_pt ()); + env.moveto (pt1); + param.update_bounds (env.get_pt ()); + } + + static inline void curve (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt1, const Point &pt2, const Point &pt3) + { + param.update_bounds (env.get_pt ()); + env.moveto (pt3); + param.update_bounds (env.get_pt ()); + } +}; + +struct CFF1CSOpSet_Extents : CFF1CSOpSet {}; + +bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const +{ + if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; + + unsigned int fd = fdSelect->get_fd (glyph); + CFF1CSInterpreter interp; + const ByteStr str = (*charStrings)[glyph]; + interp.env.init (str, *this, fd); + ExtentsParam param; + param.init (); + if (unlikely (!interp.interpret (param))) return false; + + if (param.min_x >= param.max_x) + { + extents->width = 0; + extents->x_bearing = 0; + } + else + { + extents->x_bearing = (int32_t)param.min_x.floor (); + extents->width = (int32_t)param.max_x.ceil () - extents->x_bearing; + } + if (param.min_y >= param.max_y) + { + extents->height = 0; + extents->y_bearing = 0; + } + else + { + extents->y_bearing = (int32_t)param.max_y.ceil (); + extents->height = (int32_t)param.min_y.floor () - extents->y_bearing; + } + + return true; +} diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index c3cb6ab89..cd3b9dd13 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -1007,11 +1007,6 @@ struct cff1 if (unlikely (!top_interp.interpret (topDict))) { fini (); return; } } - encoding = &Null(Encoding); - charset = &StructAtOffsetOrNull (cff, topDict.CharsetOffset); - if (unlikely (is_CID () && (charset == &Null(Charset)))) - { fini (); return; } - fdCount = 1; if (is_CID ()) { @@ -1027,12 +1022,6 @@ struct cff1 { fdArray = &Null(CFF1FDArray); fdSelect = &Null(CFF1FDSelect); - if (!is_predef_encoding ()) - { - encoding = &StructAtOffsetOrNull (cff, topDict.EncodingOffset); - if ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc)) - { fini (); return; } - } } stringIndex = &StructAtOffset (topDictIndex, topDictIndex->get_size ()); @@ -1112,6 +1101,56 @@ struct cff1 inline bool is_valid (void) const { return blob != nullptr; } inline bool is_CID (void) const { return topDict.is_CID (); } + protected: + hb_blob_t *blob; + hb_sanitize_context_t sc; + + public: + const CFF1NameIndex *nameIndex; + const CFF1TopDictIndex *topDictIndex; + const CFF1StringIndex *stringIndex; + const CFF1Subrs *globalSubrs; + const CFF1CharStrings *charStrings; + const CFF1FDArray *fdArray; + const CFF1FDSelect *fdSelect; + unsigned int fdCount; + + CFF1TopDictValues topDict; + hb_vector_t fontDicts; + hb_vector_t privateDicts; + + unsigned int num_glyphs; + }; + + struct accelerator_t : accelerator_templ_t + { + bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; + }; + + struct accelerator_subset_t : accelerator_templ_t + { + inline void init (hb_face_t *face) + { + SUPER::init (face); + if (blob == nullptr) return; + + const OT::cff1 *cff = this->blob->template as (); + encoding = &Null(Encoding); + charset = &StructAtOffsetOrNull (cff, topDict.CharsetOffset); + if (is_CID ()) + { + if (unlikely (charset == &Null(Charset))) { fini (); return; } + } + else + { + if (!is_predef_encoding ()) + { + encoding = &StructAtOffsetOrNull (cff, topDict.EncodingOffset); + if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; } + } + } + } + inline bool is_predef_encoding (void) const { return topDict.EncodingOffset <= ExpertEncoding; } inline bool is_predef_charset (void) const { return topDict.CharsetOffset <= ExpertSubsetCharset; } @@ -1164,42 +1203,13 @@ struct cff1 } } - inline bool get_extents (hb_codepoint_t glyph, - hb_glyph_extents_t *extents) const - { - // XXX: TODO - if (glyph >= num_glyphs) - return false; - - return true; - } - - protected: - hb_blob_t *blob; - hb_sanitize_context_t sc; - - public: - const CFF1NameIndex *nameIndex; - const CFF1TopDictIndex *topDictIndex; - const CFF1StringIndex *stringIndex; const Encoding *encoding; const Charset *charset; - const CFF1Subrs *globalSubrs; - const CFF1CharStrings *charStrings; - const CFF1FDArray *fdArray; - const CFF1FDSelect *fdSelect; - unsigned int fdCount; - CFF1TopDictValues topDict; - hb_vector_t fontDicts; - hb_vector_t privateDicts; - - unsigned int num_glyphs; + private: + typedef accelerator_templ_t SUPER; }; - typedef accelerator_templ_t accelerator_t; - typedef accelerator_templ_t accelerator_subset_t; - inline bool subset (hb_subset_plan_t *plan) const { hb_blob_t *cff_prime = nullptr; @@ -1233,6 +1243,7 @@ struct cff1 DEFINE_SIZE_STATIC (4); }; +struct cff1_accelerator_t : cff1::accelerator_t {}; } /* namespace OT */ #endif /* HB_OT_CFF1_TABLE_HH */ diff --git a/src/hb-ot-face.cc b/src/hb-ot-face.cc index 388a59720..a06e0537d 100644 --- a/src/hb-ot-face.cc +++ b/src/hb-ot-face.cc @@ -28,6 +28,7 @@ #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" +#include "hb-ot-cff1-table.hh" #include "hb-ot-hmtx-table.hh" #include "hb-ot-kern-table.hh" #include "hb-ot-post-table.hh" diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh index 5ac3538e4..ee808dc90 100644 --- a/src/hb-ot-face.hh +++ b/src/hb-ot-face.hh @@ -68,6 +68,7 @@ HB_OT_LAYOUT_ACCELERATOR(OT, post) \ HB_OT_LAYOUT_ACCELERATOR(OT, kern) \ HB_OT_LAYOUT_ACCELERATOR(OT, glyf) \ + HB_OT_LAYOUT_ACCELERATOR(OT, cff1) \ HB_OT_LAYOUT_ACCELERATOR(OT, CBDT) \ /* */ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 7921fb890..5874c72a2 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -145,6 +145,8 @@ hb_ot_get_glyph_extents (hb_font_t *font, { const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; bool ret = ot_face->glyf->get_extents (glyph, extents); + if (!ret) + ret = ot_face->cff1->get_extents (glyph, extents); if (!ret) ret = ot_face->CBDT->get_extents (glyph, extents); // TODO Hook up side-bearings variations. diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc index 2f3d691ad..0218da7c2 100644 --- a/src/hb-subset-cff1.cc +++ b/src/hb-subset-cff1.cc @@ -299,8 +299,8 @@ struct CFF1CSOpSet_Flatten : CFF1CSOpSet static inline void flush_n_args (unsigned int n, CFF1CSInterpEnv &env, FlattenParam& param) { - for (unsigned int i = env.argStack.count - n; i < env.argStack.count; i++) - param.flatStr.encode_num (env.argStack.elements[i]); + for (unsigned int i = env.argStack.get_count () - n; i < env.argStack.get_count (); i++) + param.flatStr.encode_num (env.argStack[i]); SUPER::flush_n_args (n, env, param); } diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc index a58ca6aea..6ee1caa28 100644 --- a/src/hb-subset-cff2.cc +++ b/src/hb-subset-cff2.cc @@ -111,9 +111,9 @@ struct CFF2CSOpSet_Flatten : CFF2CSOpSet static inline void flush_n_args (unsigned int n, CFF2CSInterpEnv &env, FlattenParam& param) { - for (unsigned int i = env.argStack.count - n; i < env.argStack.count;) + for (unsigned int i = env.argStack.get_count () - n; i < env.argStack.get_count ();) { - const BlendArg &arg = env.argStack.elements[i]; + const BlendArg &arg = env.argStack[i]; if (arg.blended ()) { assert ((arg.numValues > 0) && (n >= arg.numValues)); @@ -134,7 +134,7 @@ struct CFF2CSOpSet_Flatten : CFF2CSOpSet /* flatten the default values */ for (unsigned int j = 0; j < arg.numValues; j++) { - const BlendArg &arg1 = env.argStack.elements[i + j]; + const BlendArg &arg1 = env.argStack[i + j]; assert (arg1.blended () && (arg.numValues == arg1.numValues) && (arg1.valueIndex == j) && (arg1.deltas.len == env.get_region_count ())); param.flatStr.encode_num (arg1); @@ -142,7 +142,7 @@ struct CFF2CSOpSet_Flatten : CFF2CSOpSet /* flatten deltas for each value */ for (unsigned int j = 0; j < arg.numValues; j++) { - const BlendArg &arg1 = env.argStack.elements[i + j]; + const BlendArg &arg1 = env.argStack[i + j]; for (unsigned int k = 0; k < arg1.deltas.len; k++) param.flatStr.encode_num (arg1.deltas[k]); } @@ -165,7 +165,7 @@ struct CFF2CSOpSet_Flatten : CFF2CSOpSet private: typedef CFF2CSOpSet SUPER; - typedef CSOpSet CSOPSET; + typedef CSOpSet CSOPSET; }; struct cff2_subset_plan {