diff options
Diffstat (limited to 'dviware/dvisvgm/src/FontCache.cpp')
-rw-r--r-- | dviware/dvisvgm/src/FontCache.cpp | 128 |
1 files changed, 72 insertions, 56 deletions
diff --git a/dviware/dvisvgm/src/FontCache.cpp b/dviware/dvisvgm/src/FontCache.cpp index 5f61fc341c..34478542df 100644 --- a/dviware/dvisvgm/src/FontCache.cpp +++ b/dviware/dvisvgm/src/FontCache.cpp @@ -23,13 +23,12 @@ #include <fstream> #include <iomanip> #include <sstream> -#include "CRC32.hpp" #include "FileSystem.hpp" #include "FontCache.hpp" -#include "Glyph.hpp" #include "Pair.hpp" #include "StreamReader.hpp" #include "StreamWriter.hpp" +#include "XXHashFunction.hpp" using namespace std; @@ -78,10 +77,9 @@ bool FontCache::write (const string &fontname, const string &dir) const { return true; if (!fontname.empty()) { - string dirstr = dir.empty() ? FileSystem::getcwd() : dir; - ostringstream oss; - oss << dirstr << '/' << fontname << ".fgd"; - ofstream ofs(oss.str(), ios::binary); + string pathstr = dir.empty() ? FileSystem::getcwd() : dir; + pathstr += "/" + fontname + ".fgd"; + ofstream ofs(pathstr, ios::binary); return write(fontname, ofs); } return false; @@ -94,7 +92,7 @@ bool FontCache::write (const string &dir) const { /** Returns the minimal number of bytes needed to store the given value. */ -static int max_int_size (int32_t value) { +static int max_number_of_bytes (int32_t value) { int32_t limit = 0x7f; for (int i=1; i <= 4; i++) { if ((value < 0 && -value <= limit+1) || (value >= 0 && value <= limit)) @@ -104,19 +102,49 @@ static int max_int_size (int32_t value) { return 4; } +static int max_int_size () { + return 0; +} -/** Returns the minimal number of bytes needed to store the biggest - * pair component of the given vector. */ -static int max_int_size (const Pair<int32_t> *pairs, size_t n) { - int ret=0; - for (size_t i=0; i < n; i++) { - ret = max(ret, max_int_size(pairs[i].x())); - ret = max(ret, max_int_size(pairs[i].y())); - } - return ret; +template <typename ...Args> +static int max_int_size (const Glyph::Point &p1, const Args& ...args) { + int max1 = max(max_number_of_bytes(p1.x()), max_number_of_bytes(p1.y())); + return max(max1, max_int_size(args...)); } +struct WriteActions : Glyph::IterationActions { + WriteActions (StreamWriter &sw, HashFunction &hashfunc) : _sw(sw), _hashfunc(hashfunc) {} + + using Point = Glyph::Point; + void moveto (const Point &p) override {write('M', p);} + void lineto (const Point &p) override {write('L', p);} + void quadto (const Point &p1, const Point &p2) override {write('Q', p1, p2);} + void cubicto (const Point &p1, const Point &p2, const Point &p3) override {write('C', p1, p2, p3); } + void closepath () override {write('Z');} + + template <typename ...Args> + void write (char cmd, Args ...args) { + int bytesPerValue = max_int_size(args...); + int cmdchar = (bytesPerValue << 5) | (cmd - 'A'); + _sw.writeUnsigned(cmdchar, 1, _hashfunc); + writeParams(bytesPerValue, args...); + } + + static void writeParams (int bytesPerValue) {} + + template <typename ...Args> + void writeParams (int bytesPerValue, const Point &p, const Args& ...args) { + _sw.writeSigned(p.x(), bytesPerValue, _hashfunc); + _sw.writeSigned(p.y(), bytesPerValue, _hashfunc); + writeParams(bytesPerValue, args...); + } + + StreamWriter &_sw; + HashFunction &_hashfunc; +}; + + /** Writes the current cache data to a stream (only if anything changed after * the last call of read()). * @param[in] fontname name of current font @@ -129,36 +157,22 @@ bool FontCache::write (const string &fontname, ostream &os) const { return false; StreamWriter sw(os); - CRC32 crc32; - - struct WriteActions : Glyph::Actions { - WriteActions (StreamWriter &sw, CRC32 &crc32) : _sw(sw), _crc32(crc32) {} - - void draw (char cmd, const Glyph::Point *points, int n) override { - int bytes = max_int_size(points, n); - int cmdchar = (bytes << 5) | (cmd - 'A'); - _sw.writeUnsigned(cmdchar, 1, _crc32); - for (int i=0; i < n; i++) { - _sw.writeSigned(points[i].x(), bytes, _crc32); - _sw.writeSigned(points[i].y(), bytes, _crc32); - } - } - StreamWriter &_sw; - CRC32 &_crc32; - } actions(sw, crc32); - - sw.writeUnsigned(FORMAT_VERSION, 1, crc32); - sw.writeUnsigned(0, 4); // space for checksum - sw.writeString(fontname, crc32, true); - sw.writeUnsigned(_glyphs.size(), 4, crc32); + XXH32HashFunction hashfunc; + + sw.writeUnsigned(FORMAT_VERSION, 1, hashfunc); + sw.writeBytes(hashfunc.digestValue()); // space for checksum + sw.writeString(fontname, hashfunc, true); + sw.writeUnsigned(_glyphs.size(), 4, hashfunc); + WriteActions actions(sw, hashfunc); for (const auto &charglyphpair : _glyphs) { const Glyph &glyph = charglyphpair.second; - sw.writeUnsigned(charglyphpair.first, 4, crc32); - sw.writeUnsigned(glyph.size(), 2, crc32); + sw.writeUnsigned(charglyphpair.first, 4, hashfunc); + sw.writeUnsigned(glyph.size(), 2, hashfunc); glyph.iterate(actions, false); } os.seekp(1); - sw.writeUnsigned(crc32.get(), 4); // insert CRC32 checksum + auto digest = hashfunc.digestValue(); + sw.writeBytes(digest); // insert checksum os.seekp(0, ios::end); return true; } @@ -195,17 +209,17 @@ bool FontCache::read (const string &fontname, istream &is) { return false; StreamReader sr(is); - CRC32 crc32; - if (sr.readUnsigned(1, crc32) != FORMAT_VERSION) + XXH32HashFunction hashfunc; + if (sr.readUnsigned(1, hashfunc) != FORMAT_VERSION) return false; - uint32_t crc32_cmp = sr.readUnsigned(4); - crc32.update(is); - if (crc32.get() != crc32_cmp) + auto hashcmp = sr.readBytes(hashfunc.digestSize()); + hashfunc.update(is); + if (hashfunc.digestValue() != hashcmp) return false; is.clear(); - is.seekg(5); // continue reading after checksum + is.seekg(hashfunc.digestSize()+1); // continue reading after checksum string fname = sr.readString(); if (fname != fontname) @@ -237,7 +251,7 @@ bool FontCache::read (const string &fontname, istream &is) { case 'Q': { Pair32 p1 = read_pair(bytes, sr); Pair32 p2 = read_pair(bytes, sr); - glyph.conicto(p1, p2); + glyph.quadto(p1, p2); break; } case 'Z': @@ -289,17 +303,17 @@ bool FontCache::fontinfo (std::istream &is, FontInfo &info) { is.seekg(0); try { StreamReader sr(is); - CRC32 crc32; - if ((info.version = sr.readUnsigned(1, crc32)) != FORMAT_VERSION) + XXH32HashFunction hashfunc; + if ((info.version = sr.readUnsigned(1, hashfunc)) != FORMAT_VERSION) return false; - info.checksum = sr.readUnsigned(4); - crc32.update(is); - if (crc32.get() != info.checksum) + info.checksum = sr.readBytes(hashfunc.digestSize()); + hashfunc.update(is); + if (hashfunc.digestValue() != info.checksum) return false; is.clear(); - is.seekg(5); // continue reading after checksum + is.seekg(hashfunc.digestSize()+1); // continue reading after checksum info.name = sr.readString(); info.numchars = sr.readUnsigned(4); @@ -361,8 +375,10 @@ void FontCache::fontinfo (const string &dirname, ostream &os, bool purge) { << setw(5) << right << strinfopair.second->numchars << " glyph" << (strinfopair.second->numchars == 1 ? ' ':'s') << setw(10) << right << strinfopair.second->numcmds << " cmd" << (strinfopair.second->numcmds == 1 ? ' ':'s') << setw(12) << right << strinfopair.second->numbytes << " byte" << (strinfopair.second->numbytes == 1 ? ' ':'s') - << setw(6) << "crc:" << setw(8) << hex << right << setfill('0') << strinfopair.second->checksum - << endl; + << " hash:" << hex; + for (int byte : strinfopair.second->checksum) + os << setw(2) << setfill('0') << byte; + os << '\n'; } } if (purge) { |