1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
/*************************************************************************
** TTFTable.cpp **
** **
** This file is part of dvisvgm -- a fast DVI to SVG converter **
** Copyright (C) 2005-2023 Martin Gieseking <martin.gieseking@uos.de> **
** **
** This program is free software; you can redistribute it and/or **
** modify it under the terms of the GNU General Public License as **
** published by the Free Software Foundation; either version 3 of **
** the License, or (at your option) any later version. **
** **
** This program is distributed in the hope that it will be useful, but **
** WITHOUT ANY WARRANTY; without even the implied warranty of **
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
** GNU General Public License for more details. **
** **
** You should have received a copy of the GNU General Public License **
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
#include <vectorstream.hpp>
#include <zlib.h>
#include "TTFTable.hpp"
using namespace std;
using namespace ttf;
TableBuffer::TableBuffer (uint32_t tag, vector<char> data)
: _tag(tag), _unpaddedSize(data.size()), _compressedSize(_unpaddedSize), _data(std::move(data))
{
_data.resize((_unpaddedSize+3) & ~3, 0); // ensure data.size() % 4 == 0
for (size_t i=0; i < paddedSize(); i+=4) {
auto *bytes = reinterpret_cast<const uint8_t*>(_data.data());
_checksum += bytes[i]*0x1000000 + bytes[i+1]*0x010000 + bytes[i+2]*0x0100 + bytes[i+3];
}
}
TableBuffer::TableBuffer (uint32_t tag, vector<char> data, size_t checksumExcludeOffset)
: TableBuffer(tag, std::move(data))
{
if (checksumExcludeOffset+4 < _data.size())
_checksum -= getUInt32(checksumExcludeOffset);
}
string TableBuffer::name () const {
string ret;
for (int i=3; i >= 0; i--) {
char c = char(_tag >> (8*i));
ret += (c >= 32 && c <= 126 ? c : '*');
}
return ret;
}
/** Tries to compress the buffer data. If the size of the compressed buffer data is
* greater or equal than the size of the uncompressed data, the buffer stays uncompressed.
* @returns true if the data was compressed */
void TableBuffer::compress () {
if (_data.size() < 16)
return;
uLong compressedSize = compressBound(_data.size());
vector<char> compressedData(compressedSize, 0);
// Compress with zlib for now. We could also use zopfli for slightly better but much slower compression.
// Only use the compressed data if it actually leads to a size reduction. Otherwise, use the original table data.
auto source = reinterpret_cast<const Bytef*>(_data.data());
auto target = reinterpret_cast<Bytef*>(&compressedData[0]);
if (compress2(target, &compressedSize, source, _unpaddedSize, Z_BEST_COMPRESSION) == Z_OK && compressedSize < _unpaddedSize) {
_compressedSize = compressedSize;
_data = std::move(compressedData);
_data.resize((compressedSize+3) & ~3, 0); // reduce buffer to padded compressed size
}
}
////////////////////////////////////////////////////////////////////////////////////
/** Creates a buffer object containing the binary data represented by this table. */
TableBuffer TTFTable::createBuffer () const {
ovectorstream<vector<char>> vecstream;
write(vecstream);
vector<char> vec;
vecstream.swap_vector(vec); // move data from vector stream to vec
return TableBuffer(tag(), std::move(vec));
}
string TTFTable::name () const {
string ret;
for (int i=3; i >= 0; i--)
ret += char(tag() >> (8*i));
return ret;
}
|