Merge pull request #149 from garretrieger/overlap_bit
Add woff2 encoder/decoder support for overlapSimpleBitmap.
This commit is contained in:
@@ -26,8 +26,8 @@ struct WOFF2Params {
|
|||||||
|
|
||||||
// Returns an upper bound on the size of the compressed file.
|
// Returns an upper bound on the size of the compressed file.
|
||||||
size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length);
|
size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length);
|
||||||
size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length,
|
size_t MaxWOFF2CompressedSize(const uint8_t *data, size_t length,
|
||||||
const std::string& extended_metadata);
|
const std::string &extended_metadata);
|
||||||
|
|
||||||
// Compresses the font into the target buffer. *result_length should be at least
|
// Compresses the font into the target buffer. *result_length should be at least
|
||||||
// the value returned by MaxWOFF2CompressedSize(), upon return, it is set to the
|
// the value returned by MaxWOFF2CompressedSize(), upon return, it is set to the
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class WOFF2StringOut : public WOFF2Out {
|
|||||||
// Create a writer that writes its data to buf.
|
// Create a writer that writes its data to buf.
|
||||||
// buf->size() will grow to at most max_size
|
// buf->size() will grow to at most max_size
|
||||||
// buf may be sized (e.g. using EstimateWOFF2FinalSize) or empty.
|
// buf may be sized (e.g. using EstimateWOFF2FinalSize) or empty.
|
||||||
explicit WOFF2StringOut(std::string* buf);
|
explicit WOFF2StringOut(std::string *buf);
|
||||||
|
|
||||||
bool Write(const void *buf, size_t n) override;
|
bool Write(const void *buf, size_t n) override;
|
||||||
bool Write(const void *buf, size_t offset, size_t n) override;
|
bool Write(const void *buf, size_t offset, size_t n) override;
|
||||||
@@ -59,7 +59,7 @@ class WOFF2StringOut : public WOFF2Out {
|
|||||||
size_t MaxSize() { return max_size_; }
|
size_t MaxSize() { return max_size_; }
|
||||||
void SetMaxSize(size_t max_size);
|
void SetMaxSize(size_t max_size);
|
||||||
private:
|
private:
|
||||||
std::string* buf_;
|
std::string *buf_;
|
||||||
size_t max_size_;
|
size_t max_size_;
|
||||||
size_t offset_;
|
size_t offset_;
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-9
@@ -14,18 +14,14 @@
|
|||||||
|
|
||||||
namespace woff2 {
|
namespace woff2 {
|
||||||
|
|
||||||
using std::string;
|
inline std::string GetFileContent(std::string filename) {
|
||||||
|
|
||||||
|
|
||||||
inline string GetFileContent(string filename) {
|
|
||||||
std::ifstream ifs(filename.c_str(), std::ios::binary);
|
std::ifstream ifs(filename.c_str(), std::ios::binary);
|
||||||
return string(
|
return std::string(std::istreambuf_iterator<char>(ifs.rdbuf()),
|
||||||
std::istreambuf_iterator<char>(ifs.rdbuf()),
|
std::istreambuf_iterator<char>());
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetFileContents(string filename, string::iterator start,
|
inline void SetFileContents(std::string filename, std::string::iterator start,
|
||||||
string::iterator end) {
|
std::string::iterator end) {
|
||||||
std::ofstream ofs(filename.c_str(), std::ios::binary);
|
std::ofstream ofs(filename.c_str(), std::ios::binary);
|
||||||
std::copy(start, end, std::ostream_iterator<char>(ofs));
|
std::copy(start, end, std::ostream_iterator<char>(ofs));
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -21,6 +21,7 @@ static const int32_t kFLAG_YSHORT = 1 << 2;
|
|||||||
static const int32_t kFLAG_REPEAT = 1 << 3;
|
static const int32_t kFLAG_REPEAT = 1 << 3;
|
||||||
static const int32_t kFLAG_XREPEATSIGN = 1 << 4;
|
static const int32_t kFLAG_XREPEATSIGN = 1 << 4;
|
||||||
static const int32_t kFLAG_YREPEATSIGN = 1 << 5;
|
static const int32_t kFLAG_YREPEATSIGN = 1 << 5;
|
||||||
|
static const int32_t kFLAG_OVERLAP_SIMPLE = 1 << 6;
|
||||||
static const int32_t kFLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;
|
static const int32_t kFLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;
|
||||||
static const int32_t kFLAG_WE_HAVE_A_SCALE = 1 << 3;
|
static const int32_t kFLAG_WE_HAVE_A_SCALE = 1 << 3;
|
||||||
static const int32_t kFLAG_MORE_COMPONENTS = 1 << 5;
|
static const int32_t kFLAG_MORE_COMPONENTS = 1 << 5;
|
||||||
@@ -134,6 +135,10 @@ bool ReadGlyph(const uint8_t* data, size_t len, Glyph* glyph) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!flags.empty() && !flags[0].empty()) {
|
||||||
|
glyph->overlap_simple_flag_set = (flags[0][0] & kFLAG_OVERLAP_SIMPLE);
|
||||||
|
}
|
||||||
|
|
||||||
// Read the x coordinates.
|
// Read the x coordinates.
|
||||||
int prev_x = 0;
|
int prev_x = 0;
|
||||||
for (int i = 0; i < num_contours; ++i) {
|
for (int i = 0; i < num_contours; ++i) {
|
||||||
@@ -239,7 +244,7 @@ bool StoreEndPtsOfContours(const Glyph& glyph, size_t* offset, uint8_t* dst) {
|
|||||||
|
|
||||||
bool StorePoints(const Glyph& glyph, size_t* offset,
|
bool StorePoints(const Glyph& glyph, size_t* offset,
|
||||||
uint8_t* dst, size_t dst_size) {
|
uint8_t* dst, size_t dst_size) {
|
||||||
int last_flag = -1;
|
int previous_flag = -1;
|
||||||
int repeat_count = 0;
|
int repeat_count = 0;
|
||||||
int last_x = 0;
|
int last_x = 0;
|
||||||
int last_y = 0;
|
int last_y = 0;
|
||||||
@@ -250,6 +255,10 @@ bool StorePoints(const Glyph& glyph, size_t* offset,
|
|||||||
for (const auto& contour : glyph.contours) {
|
for (const auto& contour : glyph.contours) {
|
||||||
for (const auto& point : contour) {
|
for (const auto& point : contour) {
|
||||||
int flag = point.on_curve ? kFLAG_ONCURVE : 0;
|
int flag = point.on_curve ? kFLAG_ONCURVE : 0;
|
||||||
|
if (previous_flag == -1 && glyph.overlap_simple_flag_set) {
|
||||||
|
// First flag needs to have overlap simple bit set.
|
||||||
|
flag = flag | kFLAG_OVERLAP_SIMPLE;
|
||||||
|
}
|
||||||
int dx = point.x - last_x;
|
int dx = point.x - last_x;
|
||||||
int dy = point.y - last_y;
|
int dy = point.y - last_y;
|
||||||
if (dx == 0) {
|
if (dx == 0) {
|
||||||
@@ -268,7 +277,7 @@ bool StorePoints(const Glyph& glyph, size_t* offset,
|
|||||||
} else {
|
} else {
|
||||||
y_bytes += 2;
|
y_bytes += 2;
|
||||||
}
|
}
|
||||||
if (flag == last_flag && repeat_count != 255) {
|
if (flag == previous_flag && repeat_count != 255) {
|
||||||
dst[*offset - 1] |= kFLAG_REPEAT;
|
dst[*offset - 1] |= kFLAG_REPEAT;
|
||||||
repeat_count++;
|
repeat_count++;
|
||||||
} else {
|
} else {
|
||||||
@@ -286,7 +295,7 @@ bool StorePoints(const Glyph& glyph, size_t* offset,
|
|||||||
}
|
}
|
||||||
last_x = point.x;
|
last_x = point.x;
|
||||||
last_y = point.y;
|
last_y = point.y;
|
||||||
last_flag = flag;
|
previous_flag = flag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (repeat_count != 0) {
|
if (repeat_count != 0) {
|
||||||
|
|||||||
+10
-2
@@ -10,8 +10,10 @@
|
|||||||
#ifndef WOFF2_GLYPH_H_
|
#ifndef WOFF2_GLYPH_H_
|
||||||
#define WOFF2_GLYPH_H_
|
#define WOFF2_GLYPH_H_
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace woff2 {
|
namespace woff2 {
|
||||||
@@ -22,7 +24,10 @@ namespace woff2 {
|
|||||||
// is around.
|
// is around.
|
||||||
class Glyph {
|
class Glyph {
|
||||||
public:
|
public:
|
||||||
Glyph() : instructions_size(0), composite_data_size(0) {}
|
Glyph()
|
||||||
|
: instructions_size(0),
|
||||||
|
overlap_simple_flag_set(false),
|
||||||
|
composite_data_size(0) {}
|
||||||
|
|
||||||
// Bounding box.
|
// Bounding box.
|
||||||
int16_t x_min;
|
int16_t x_min;
|
||||||
@@ -34,6 +39,9 @@ class Glyph {
|
|||||||
uint16_t instructions_size;
|
uint16_t instructions_size;
|
||||||
const uint8_t* instructions_data;
|
const uint8_t* instructions_data;
|
||||||
|
|
||||||
|
// Flags.
|
||||||
|
bool overlap_simple_flag_set;
|
||||||
|
|
||||||
// Data model for simple glyphs.
|
// Data model for simple glyphs.
|
||||||
struct Point {
|
struct Point {
|
||||||
int x;
|
int x;
|
||||||
|
|||||||
+19
-1
@@ -22,6 +22,7 @@ namespace {
|
|||||||
|
|
||||||
const int FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;
|
const int FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;
|
||||||
const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8;
|
const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8;
|
||||||
|
const int FLAG_OVERLAP_SIMPLE_BITMAP = 1 << 0;
|
||||||
|
|
||||||
void WriteBytes(std::vector<uint8_t>* out, const uint8_t* data, size_t len) {
|
void WriteBytes(std::vector<uint8_t>* out, const uint8_t* data, size_t len) {
|
||||||
if (len == 0) return;
|
if (len == 0) return;
|
||||||
@@ -69,7 +70,10 @@ class GlyfEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GetTransformedGlyfBytes(std::vector<uint8_t>* result) {
|
void GetTransformedGlyfBytes(std::vector<uint8_t>* result) {
|
||||||
WriteLong(result, 0); // version
|
WriteUShort(result, 0); // Version
|
||||||
|
WriteUShort(result, overlap_bitmap_.empty()
|
||||||
|
? 0x00
|
||||||
|
: FLAG_OVERLAP_SIMPLE_BITMAP); // Flags
|
||||||
WriteUShort(result, n_glyphs_);
|
WriteUShort(result, n_glyphs_);
|
||||||
WriteUShort(result, 0); // index_format, will be set later
|
WriteUShort(result, 0); // index_format, will be set later
|
||||||
WriteLong(result, n_contour_stream_.size());
|
WriteLong(result, n_contour_stream_.size());
|
||||||
@@ -87,6 +91,9 @@ class GlyfEncoder {
|
|||||||
WriteBytes(result, bbox_bitmap_);
|
WriteBytes(result, bbox_bitmap_);
|
||||||
WriteBytes(result, bbox_stream_);
|
WriteBytes(result, bbox_stream_);
|
||||||
WriteBytes(result, instruction_stream_);
|
WriteBytes(result, instruction_stream_);
|
||||||
|
if (!overlap_bitmap_.empty()) {
|
||||||
|
WriteBytes(result, overlap_bitmap_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -127,6 +134,10 @@ class GlyfEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WriteSimpleGlyph(int glyph_id, const Glyph& glyph) {
|
void WriteSimpleGlyph(int glyph_id, const Glyph& glyph) {
|
||||||
|
if (glyph.overlap_simple_flag_set) {
|
||||||
|
EnsureOverlapBitmap();
|
||||||
|
overlap_bitmap_[glyph_id >> 3] |= 0x80 >> (glyph_id & 7);
|
||||||
|
}
|
||||||
int num_contours = glyph.contours.size();
|
int num_contours = glyph.contours.size();
|
||||||
WriteUShort(&n_contour_stream_, num_contours);
|
WriteUShort(&n_contour_stream_, num_contours);
|
||||||
if (ShouldWriteSimpleGlyphBbox(glyph)) {
|
if (ShouldWriteSimpleGlyphBbox(glyph)) {
|
||||||
@@ -214,6 +225,12 @@ class GlyfEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnsureOverlapBitmap() {
|
||||||
|
if (overlap_bitmap_.empty()) {
|
||||||
|
overlap_bitmap_.resize((n_glyphs_ + 7) >> 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> n_contour_stream_;
|
std::vector<uint8_t> n_contour_stream_;
|
||||||
std::vector<uint8_t> n_points_stream_;
|
std::vector<uint8_t> n_points_stream_;
|
||||||
std::vector<uint8_t> flag_byte_stream_;
|
std::vector<uint8_t> flag_byte_stream_;
|
||||||
@@ -222,6 +239,7 @@ class GlyfEncoder {
|
|||||||
std::vector<uint8_t> bbox_stream_;
|
std::vector<uint8_t> bbox_stream_;
|
||||||
std::vector<uint8_t> glyph_stream_;
|
std::vector<uint8_t> glyph_stream_;
|
||||||
std::vector<uint8_t> instruction_stream_;
|
std::vector<uint8_t> instruction_stream_;
|
||||||
|
std::vector<uint8_t> overlap_bitmap_;
|
||||||
int n_glyphs_;
|
int n_glyphs_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,22 +13,20 @@
|
|||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
using std::string;
|
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
fprintf(stderr, "One argument, the input filename, must be provided.\n");
|
fprintf(stderr, "One argument, the input filename, must be provided.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string filename(argv[1]);
|
std::string filename(argv[1]);
|
||||||
string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2";
|
std::string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2";
|
||||||
fprintf(stdout, "Processing %s => %s\n",
|
fprintf(stdout, "Processing %s => %s\n",
|
||||||
filename.c_str(), outfilename.c_str());
|
filename.c_str(), outfilename.c_str());
|
||||||
string input = woff2::GetFileContent(filename);
|
std::string input = woff2::GetFileContent(filename);
|
||||||
|
|
||||||
const uint8_t* input_data = reinterpret_cast<const uint8_t*>(input.data());
|
const uint8_t* input_data = reinterpret_cast<const uint8_t*>(input.data());
|
||||||
size_t output_size = woff2::MaxWOFF2CompressedSize(input_data, input.size());
|
size_t output_size = woff2::MaxWOFF2CompressedSize(input_data, input.size());
|
||||||
string output(output_size, 0);
|
std::string output(output_size, 0);
|
||||||
uint8_t* output_data = reinterpret_cast<uint8_t*>(&output[0]);
|
uint8_t* output_data = reinterpret_cast<uint8_t*>(&output[0]);
|
||||||
|
|
||||||
woff2::WOFF2Params params;
|
woff2::WOFF2Params params;
|
||||||
|
|||||||
+37
-10
@@ -32,10 +32,6 @@ namespace woff2 {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using std::string;
|
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
|
|
||||||
// simple glyph flags
|
// simple glyph flags
|
||||||
const int kGlyfOnCurve = 1 << 0;
|
const int kGlyfOnCurve = 1 << 0;
|
||||||
const int kGlyfXShort = 1 << 1;
|
const int kGlyfXShort = 1 << 1;
|
||||||
@@ -43,6 +39,7 @@ const int kGlyfYShort = 1 << 2;
|
|||||||
const int kGlyfRepeat = 1 << 3;
|
const int kGlyfRepeat = 1 << 3;
|
||||||
const int kGlyfThisXIsSame = 1 << 4;
|
const int kGlyfThisXIsSame = 1 << 4;
|
||||||
const int kGlyfThisYIsSame = 1 << 5;
|
const int kGlyfThisYIsSame = 1 << 5;
|
||||||
|
const int kOverlapSimple = 1 << 6;
|
||||||
|
|
||||||
// composite glyph flags
|
// composite glyph flags
|
||||||
// See CompositeGlyph.java in sfntly for full definitions
|
// 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_A_TWO_BY_TWO = 1 << 7;
|
||||||
const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8;
|
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 kCheckSumAdjustmentOffset = 8;
|
||||||
|
|
||||||
const size_t kEndPtsOfContoursOffset = 10;
|
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
|
// This function stores just the point data. On entry, dst points to the
|
||||||
// beginning of a simple glyph. Returns true on success.
|
// beginning of a simple glyph. Returns true on success.
|
||||||
bool StorePoints(unsigned int n_points, const Point* points,
|
bool StorePoints(unsigned int n_points, const Point* points,
|
||||||
unsigned int n_contours, unsigned int instruction_length,
|
unsigned int n_contours, unsigned int instruction_length,
|
||||||
uint8_t* dst, size_t dst_size, size_t* glyph_size) {
|
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
|
// I believe that n_contours < 65536, in which case this is safe. However, a
|
||||||
// comment and/or an assert would be good.
|
// comment and/or an assert would be good.
|
||||||
unsigned int flag_offset = kEndPtsOfContoursOffset + 2 * n_contours + 2 +
|
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) {
|
for (unsigned int i = 0; i < n_points; ++i) {
|
||||||
const Point& point = points[i];
|
const Point& point = points[i];
|
||||||
int flag = point.on_curve ? kGlyfOnCurve : 0;
|
int flag = point.on_curve ? kGlyfOnCurve : 0;
|
||||||
|
if (has_overlap_bit && i == 0) {
|
||||||
|
flag |= kOverlapSimple;
|
||||||
|
}
|
||||||
|
|
||||||
int dx = point.x - last_x;
|
int dx = point.x - last_x;
|
||||||
int dy = point.y - last_y;
|
int dy = point.y - last_y;
|
||||||
if (dx == 0) {
|
if (dx == 0) {
|
||||||
@@ -404,13 +409,20 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table,
|
|||||||
WOFF2Out* out) {
|
WOFF2Out* out) {
|
||||||
static const int kNumSubStreams = 7;
|
static const int kNumSubStreams = 7;
|
||||||
Buffer file(data, glyf_table->transform_length);
|
Buffer file(data, glyf_table->transform_length);
|
||||||
uint32_t version;
|
uint16_t version;
|
||||||
std::vector<std::pair<const uint8_t*, size_t> > substreams(kNumSubStreams);
|
std::vector<std::pair<const uint8_t*, size_t> > substreams(kNumSubStreams);
|
||||||
const size_t glyf_start = out->Size();
|
const size_t glyf_start = out->Size();
|
||||||
|
|
||||||
if (PREDICT_FALSE(!file.ReadU32(&version))) {
|
if (PREDICT_FALSE(!file.ReadU16(&version))) {
|
||||||
return FONT_COMPRESSION_FAILURE();
|
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) ||
|
if (PREDICT_FALSE(!file.ReadU16(&info->num_glyphs) ||
|
||||||
!file.ReadU16(&info->index_format))) {
|
!file.ReadU16(&info->index_format))) {
|
||||||
return FONT_COMPRESSION_FAILURE();
|
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 bbox_stream(substreams[5].first, substreams[5].second);
|
||||||
Buffer instruction_stream(substreams[6].first, substreams[6].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<uint32_t> loca_values(info->num_glyphs + 1);
|
||||||
std::vector<unsigned int> n_points_vec;
|
std::vector<unsigned int> n_points_vec;
|
||||||
std::unique_ptr<Point[]> points;
|
std::unique_ptr<Point[]> points;
|
||||||
@@ -601,8 +624,12 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table,
|
|||||||
}
|
}
|
||||||
glyph_size += instruction_size;
|
glyph_size += instruction_size;
|
||||||
|
|
||||||
if (PREDICT_FALSE(!StorePoints(total_n_points, points.get(), n_contours,
|
bool has_overlap_bit =
|
||||||
instruction_size, glyph_buf.get(), glyph_buf_size, &glyph_size))) {
|
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();
|
return FONT_COMPRESSION_FAILURE();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -14,21 +14,21 @@
|
|||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
using std::string;
|
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
fprintf(stderr, "One argument, the input filename, must be provided.\n");
|
fprintf(stderr, "One argument, the input filename, must be provided.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string filename(argv[1]);
|
std::string filename(argv[1]);
|
||||||
string outfilename = filename.substr(0, filename.find_last_of(".")) + ".ttf";
|
std::string outfilename = filename.substr(0, filename.find_last_of(".")) + ".ttf";
|
||||||
|
|
||||||
// Note: update woff2_dec_fuzzer_new_entry.cc if this pattern changes.
|
// Note: update woff2_dec_fuzzer_new_entry.cc if this pattern changes.
|
||||||
string input = woff2::GetFileContent(filename);
|
std::string input = woff2::GetFileContent(filename);
|
||||||
const uint8_t* raw_input = reinterpret_cast<const uint8_t*>(input.data());
|
const uint8_t* raw_input = reinterpret_cast<const uint8_t*>(input.data());
|
||||||
string output(std::min(woff2::ComputeWOFF2FinalSize(raw_input, input.size()),
|
std::string output(
|
||||||
woff2::kDefaultMaxSize), 0);
|
std::min(woff2::ComputeWOFF2FinalSize(raw_input, input.size()),
|
||||||
|
woff2::kDefaultMaxSize),
|
||||||
|
0);
|
||||||
woff2::WOFF2StringOut out(&output);
|
woff2::WOFF2StringOut out(&output);
|
||||||
|
|
||||||
const bool ok = woff2::ConvertWOFF2ToTTF(raw_input, input.size(), &out);
|
const bool ok = woff2::ConvertWOFF2ToTTF(raw_input, input.size(), &out);
|
||||||
|
|||||||
+2
-6
@@ -28,13 +28,9 @@
|
|||||||
|
|
||||||
namespace woff2 {
|
namespace woff2 {
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
using std::string;
|
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
|
|
||||||
const size_t kWoff2HeaderSize = 48;
|
const size_t kWoff2HeaderSize = 48;
|
||||||
const size_t kWoff2EntrySize = 20;
|
const size_t kWoff2EntrySize = 20;
|
||||||
|
|
||||||
@@ -183,7 +179,7 @@ size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length,
|
size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length,
|
||||||
const string& extended_metadata) {
|
const std::string& extended_metadata) {
|
||||||
// Except for the header size, which is 32 bytes larger in woff2 format,
|
// Except for the header size, which is 32 bytes larger in woff2 format,
|
||||||
// all other parts should be smaller (table header in short format,
|
// all other parts should be smaller (table header in short format,
|
||||||
// transformations and compression). Just to be sure, we will give some
|
// transformations and compression). Just to be sure, we will give some
|
||||||
|
|||||||
+3
-5
@@ -29,18 +29,16 @@ std::string PrintTag(int tag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
using std::string;
|
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
fprintf(stderr, "One argument, the input filename, must be provided.\n");
|
fprintf(stderr, "One argument, the input filename, must be provided.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string filename(argv[1]);
|
std::string filename(argv[1]);
|
||||||
string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2";
|
std::string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2";
|
||||||
fprintf(stdout, "Processing %s => %s\n",
|
fprintf(stdout, "Processing %s => %s\n",
|
||||||
filename.c_str(), outfilename.c_str());
|
filename.c_str(), outfilename.c_str());
|
||||||
string input = woff2::GetFileContent(filename);
|
std::string input = woff2::GetFileContent(filename);
|
||||||
|
|
||||||
woff2::Buffer file(reinterpret_cast<const uint8_t*>(input.data()),
|
woff2::Buffer file(reinterpret_cast<const uint8_t*>(input.data()),
|
||||||
input.size());
|
input.size());
|
||||||
|
|||||||
+2
-6
@@ -8,14 +8,10 @@
|
|||||||
|
|
||||||
#include <woff2/output.h>
|
#include <woff2/output.h>
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
namespace woff2 {
|
namespace woff2 {
|
||||||
|
|
||||||
WOFF2StringOut::WOFF2StringOut(string* buf)
|
WOFF2StringOut::WOFF2StringOut(std::string *buf)
|
||||||
: buf_(buf),
|
: buf_(buf), max_size_(kDefaultMaxSize), offset_(0) {}
|
||||||
max_size_(kDefaultMaxSize),
|
|
||||||
offset_(0) {}
|
|
||||||
|
|
||||||
bool WOFF2StringOut::Write(const void *buf, size_t n) {
|
bool WOFF2StringOut::Write(const void *buf, size_t n) {
|
||||||
return Write(buf, offset_, n);
|
return Write(buf, offset_, n);
|
||||||
|
|||||||
Reference in New Issue
Block a user