summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh')
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh126
1 files changed, 126 insertions, 0 deletions
diff --git a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
index 6df978cf13..b99665d6a0 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
@@ -206,6 +206,132 @@ struct SimpleGlyph
&& read_points (p, points_, end, &contour_point_t::y,
FLAG_Y_SHORT, FLAG_Y_SAME);
}
+
+ static void encode_coord (int value,
+ uint8_t &flag,
+ const simple_glyph_flag_t short_flag,
+ const simple_glyph_flag_t same_flag,
+ hb_vector_t<uint8_t> &coords /* OUT */)
+ {
+ if (value == 0)
+ {
+ flag |= same_flag;
+ }
+ else if (value >= -255 && value <= 255)
+ {
+ flag |= short_flag;
+ if (value > 0) flag |= same_flag;
+ else value = -value;
+
+ coords.push ((uint8_t)value);
+ }
+ else
+ {
+ int16_t val = value;
+ coords.push (val >> 8);
+ coords.push (val & 0xff);
+ }
+ }
+
+ static void encode_flag (uint8_t &flag,
+ uint8_t &repeat,
+ uint8_t &lastflag,
+ hb_vector_t<uint8_t> &flags /* OUT */)
+ {
+ if (flag == lastflag && repeat != 255)
+ {
+ repeat = repeat + 1;
+ if (repeat == 1)
+ {
+ flags.push(flag);
+ }
+ else
+ {
+ unsigned len = flags.length;
+ flags[len-2] = flag | FLAG_REPEAT;
+ flags[len-1] = repeat;
+ }
+ }
+ else
+ {
+ repeat = 0;
+ flags.push (flag);
+ }
+ lastflag = flag;
+ }
+
+ bool compile_bytes_with_deltas (const contour_point_vector_t &all_points,
+ bool no_hinting,
+ hb_bytes_t &dest_bytes /* OUT */)
+ {
+ if (header.numberOfContours == 0 || all_points.length <= 4)
+ {
+ dest_bytes = hb_bytes_t ();
+ return true;
+ }
+ //convert absolute values to relative values
+ unsigned num_points = all_points.length - 4;
+ hb_vector_t<hb_pair_t<int, int>> deltas;
+ deltas.resize (num_points);
+
+ for (unsigned i = 0; i < num_points; i++)
+ {
+ deltas[i].first = i == 0 ? roundf (all_points[i].x) : roundf (all_points[i].x) - roundf (all_points[i-1].x);
+ deltas[i].second = i == 0 ? roundf (all_points[i].y) : roundf (all_points[i].y) - roundf (all_points[i-1].y);
+ }
+
+ hb_vector_t<uint8_t> flags, x_coords, y_coords;
+ flags.alloc (num_points);
+ x_coords.alloc (2*num_points);
+ y_coords.alloc (2*num_points);
+
+ uint8_t lastflag = 0, repeat = 0;
+
+ for (unsigned i = 0; i < num_points; i++)
+ {
+ uint8_t flag = all_points[i].flag;
+ flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
+
+ encode_coord (deltas[i].first, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
+ encode_coord (deltas[i].second, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
+ if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point
+ encode_flag (flag, repeat, lastflag, flags);
+ }
+
+ unsigned len_before_instrs = 2 * header.numberOfContours + 2;
+ unsigned len_instrs = instructions_length ();
+ unsigned total_len = len_before_instrs + flags.length + x_coords.length + y_coords.length;
+
+ if (!no_hinting)
+ total_len += len_instrs;
+
+ char *p = (char *) hb_calloc (total_len, sizeof (char));
+ if (unlikely (!p)) return false;
+
+ const char *src = bytes.arrayZ + GlyphHeader::static_size;
+ char *cur = p;
+ memcpy (p, src, len_before_instrs);
+
+ cur += len_before_instrs;
+ src += len_before_instrs;
+
+ if (!no_hinting)
+ {
+ memcpy (cur, src, len_instrs);
+ cur += len_instrs;
+ }
+
+ memcpy (cur, flags.arrayZ, flags.length);
+ cur += flags.length;
+
+ memcpy (cur, x_coords.arrayZ, x_coords.length);
+ cur += x_coords.length;
+
+ memcpy (cur, y_coords.arrayZ, y_coords.length);
+
+ dest_bytes = hb_bytes_t (p, total_len);
+ return true;
+ }
};