Add woff2 encoder/decoder support for overlapSimpleBitmap.

overlapSimpleBitmap is a new field in the transformed glyf table (https://www.w3.org/TR/WOFF2/#glyf_table_format). It allows the overlap simple flag set on glyphs in the original font to be saved into the woff2 encoding.
This commit is contained in:
Garret Rieger
2022-03-29 13:49:27 -07:00
parent a0d0ed7da2
commit 62ae7a4c1e
12 changed files with 105 additions and 59 deletions
+37 -10
View File
@@ -32,10 +32,6 @@ namespace woff2 {
namespace {
using std::string;
using std::vector;
// simple glyph flags
const int kGlyfOnCurve = 1 << 0;
const int kGlyfXShort = 1 << 1;
@@ -43,6 +39,7 @@ const int kGlyfYShort = 1 << 2;
const int kGlyfRepeat = 1 << 3;
const int kGlyfThisXIsSame = 1 << 4;
const int kGlyfThisYIsSame = 1 << 5;
const int kOverlapSimple = 1 << 6;
// composite glyph flags
// See CompositeGlyph.java in sfntly for full definitions
@@ -53,6 +50,9 @@ const int FLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6;
const int FLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7;
const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8;
// glyf flags
const int FLAG_OVERLAP_SIMPLE_BITMAP = 1 << 0;
const size_t kCheckSumAdjustmentOffset = 8;
const size_t kEndPtsOfContoursOffset = 10;
@@ -191,8 +191,9 @@ bool TripletDecode(const uint8_t* flags_in, const uint8_t* in, size_t in_size,
// This function stores just the point data. On entry, dst points to the
// beginning of a simple glyph. Returns true on success.
bool StorePoints(unsigned int n_points, const Point* points,
unsigned int n_contours, unsigned int instruction_length,
uint8_t* dst, size_t dst_size, size_t* glyph_size) {
unsigned int n_contours, unsigned int instruction_length,
bool has_overlap_bit, uint8_t* dst, size_t dst_size,
size_t* glyph_size) {
// I believe that n_contours < 65536, in which case this is safe. However, a
// comment and/or an assert would be good.
unsigned int flag_offset = kEndPtsOfContoursOffset + 2 * n_contours + 2 +
@@ -207,6 +208,10 @@ bool StorePoints(unsigned int n_points, const Point* points,
for (unsigned int i = 0; i < n_points; ++i) {
const Point& point = points[i];
int flag = point.on_curve ? kGlyfOnCurve : 0;
if (has_overlap_bit && i == 0) {
flag |= kOverlapSimple;
}
int dx = point.x - last_x;
int dy = point.y - last_y;
if (dx == 0) {
@@ -404,13 +409,20 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table,
WOFF2Out* out) {
static const int kNumSubStreams = 7;
Buffer file(data, glyf_table->transform_length);
uint32_t version;
uint16_t version;
std::vector<std::pair<const uint8_t*, size_t> > substreams(kNumSubStreams);
const size_t glyf_start = out->Size();
if (PREDICT_FALSE(!file.ReadU32(&version))) {
if (PREDICT_FALSE(!file.ReadU16(&version))) {
return FONT_COMPRESSION_FAILURE();
}
uint16_t flags;
if (PREDICT_FALSE(!file.ReadU16(&flags))) {
return FONT_COMPRESSION_FAILURE();
}
bool has_overlap_bitmap = (flags & FLAG_OVERLAP_SIMPLE_BITMAP);
if (PREDICT_FALSE(!file.ReadU16(&info->num_glyphs) ||
!file.ReadU16(&info->index_format))) {
return FONT_COMPRESSION_FAILURE();
@@ -448,6 +460,17 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table,
Buffer bbox_stream(substreams[5].first, substreams[5].second);
Buffer instruction_stream(substreams[6].first, substreams[6].second);
const uint8_t* overlap_bitmap = nullptr;
unsigned int overlap_bitmap_length = 0;
if (has_overlap_bitmap) {
overlap_bitmap_length = (info->num_glyphs + 7) >> 3;
overlap_bitmap = data + offset;
if (PREDICT_FALSE(overlap_bitmap_length >
glyf_table->transform_length - offset)) {
return FONT_COMPRESSION_FAILURE();
}
}
std::vector<uint32_t> loca_values(info->num_glyphs + 1);
std::vector<unsigned int> n_points_vec;
std::unique_ptr<Point[]> points;
@@ -601,8 +624,12 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table,
}
glyph_size += instruction_size;
if (PREDICT_FALSE(!StorePoints(total_n_points, points.get(), n_contours,
instruction_size, glyph_buf.get(), glyph_buf_size, &glyph_size))) {
bool has_overlap_bit =
has_overlap_bitmap && overlap_bitmap[i >> 3] & (0x80 >> (i & 7));
if (PREDICT_FALSE(!StorePoints(
total_n_points, points.get(), n_contours, instruction_size,
has_overlap_bit, glyph_buf.get(), glyph_buf_size, &glyph_size))) {
return FONT_COMPRESSION_FAILURE();
}
} else {