summaryrefslogtreecommitdiff
path: root/dviware/dvisvgm/src/FontCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/dvisvgm/src/FontCache.cpp')
-rw-r--r--dviware/dvisvgm/src/FontCache.cpp128
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) {