reot 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/Gemfile +4 -0
- data/README.md +13 -0
- data/Rakefile +16 -0
- data/ext/reot/OpenTypeUtilities.cpp +334 -0
- data/ext/reot/OpenTypeUtilities.h +38 -0
- data/ext/reot/extconf.rb +13 -0
- data/ext/reot/reot.cpp +70 -0
- data/lib/reot/version.rb +3 -0
- data/reot.gemspec +22 -0
- data/test/fonts/Metalista.ttf +0 -0
- data/test/helper.rb +5 -0
- data/test/reot_test.rb +16 -0
- metadata +73 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Reot
|
2
|
+
====
|
3
|
+
|
4
|
+
Simple library for converting [ttf](http://en.wikipedia.org/wiki/TrueType) to [eot](http://en.wikipedia.org/wiki/Embedded_OpenType) format. It is using [ttf2eot](http://code.google.com/p/ttf2eot/), just instead of using console, you can use simple ruby module.
|
5
|
+
|
6
|
+
Example
|
7
|
+
-------
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
Reot.convert!('awesome_webfont.ttf', 'awesome_webfont.eot') #=> true
|
11
|
+
```
|
12
|
+
|
13
|
+
Generates ```awesome_webfont.eot```!
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/extensiontask'
|
5
|
+
|
6
|
+
Bundler::GemHelper.install_tasks
|
7
|
+
Rake::ExtensionTask.new('reot')
|
8
|
+
|
9
|
+
desc "Build eventmachine, then run tests."
|
10
|
+
task :default => [:clean,:compile, :test]
|
11
|
+
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,334 @@
|
|
1
|
+
/* Modified for use with ttf2eot, originally from WebKit. */
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Copyright (C) 2008 Apple Inc. All rights reserved.
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions
|
8
|
+
* are met:
|
9
|
+
* 1. Redistributions of source code must retain the above copyright
|
10
|
+
* notice, this list of conditions and the following disclaimer.
|
11
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer in the
|
13
|
+
* documentation and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
16
|
+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
18
|
+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
19
|
+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
20
|
+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
21
|
+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
22
|
+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
23
|
+
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
24
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
25
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
#include <string.h>
|
29
|
+
#include <vector>
|
30
|
+
|
31
|
+
#ifndef _MSC_VER
|
32
|
+
# include <stdint.h>
|
33
|
+
#else
|
34
|
+
typedef unsigned char uint8_t;
|
35
|
+
#endif
|
36
|
+
|
37
|
+
#include "OpenTypeUtilities.h"
|
38
|
+
|
39
|
+
|
40
|
+
using std::vector;
|
41
|
+
|
42
|
+
typedef unsigned Fixed;
|
43
|
+
|
44
|
+
#define DEFAULT_CHARSET 1
|
45
|
+
|
46
|
+
struct BigEndianUShort {
|
47
|
+
operator unsigned short() const { return (v & 0x00ff) << 8 | v >> 8; }
|
48
|
+
BigEndianUShort(unsigned short u) : v((u & 0x00ff) << 8 | u >> 8) { }
|
49
|
+
unsigned short v;
|
50
|
+
};
|
51
|
+
|
52
|
+
struct BigEndianULong {
|
53
|
+
operator unsigned() const { return (v & 0xff) << 24 | (v & 0xff00) << 8 | (v & 0xff0000) >> 8 | v >> 24; }
|
54
|
+
BigEndianULong(unsigned u) : v((u & 0xff) << 24 | (u & 0xff00) << 8 | (u & 0xff0000) >> 8 | u >> 24) { }
|
55
|
+
unsigned v;
|
56
|
+
};
|
57
|
+
|
58
|
+
#pragma pack(1)
|
59
|
+
|
60
|
+
struct EOTPrefix {
|
61
|
+
unsigned eotSize;
|
62
|
+
unsigned fontDataSize;
|
63
|
+
unsigned version;
|
64
|
+
unsigned flags;
|
65
|
+
uint8_t fontPANOSE[10];
|
66
|
+
uint8_t charset;
|
67
|
+
uint8_t italic;
|
68
|
+
unsigned weight;
|
69
|
+
unsigned short fsType;
|
70
|
+
unsigned short magicNumber;
|
71
|
+
unsigned unicodeRange[4];
|
72
|
+
unsigned codePageRange[2];
|
73
|
+
unsigned checkSumAdjustment;
|
74
|
+
unsigned reserved[4];
|
75
|
+
unsigned short padding1;
|
76
|
+
};
|
77
|
+
|
78
|
+
struct TableDirectoryEntry {
|
79
|
+
BigEndianULong tag;
|
80
|
+
BigEndianULong checkSum;
|
81
|
+
BigEndianULong offset;
|
82
|
+
BigEndianULong length;
|
83
|
+
};
|
84
|
+
|
85
|
+
struct sfntHeader {
|
86
|
+
Fixed version;
|
87
|
+
BigEndianUShort numTables;
|
88
|
+
BigEndianUShort searchRange;
|
89
|
+
BigEndianUShort entrySelector;
|
90
|
+
BigEndianUShort rangeShift;
|
91
|
+
TableDirectoryEntry tables[1];
|
92
|
+
};
|
93
|
+
|
94
|
+
struct OS2Table {
|
95
|
+
BigEndianUShort version;
|
96
|
+
BigEndianUShort avgCharWidth;
|
97
|
+
BigEndianUShort weightClass;
|
98
|
+
BigEndianUShort widthClass;
|
99
|
+
BigEndianUShort fsType;
|
100
|
+
BigEndianUShort subscriptXSize;
|
101
|
+
BigEndianUShort subscriptYSize;
|
102
|
+
BigEndianUShort subscriptXOffset;
|
103
|
+
BigEndianUShort subscriptYOffset;
|
104
|
+
BigEndianUShort superscriptXSize;
|
105
|
+
BigEndianUShort superscriptYSize;
|
106
|
+
BigEndianUShort superscriptXOffset;
|
107
|
+
BigEndianUShort superscriptYOffset;
|
108
|
+
BigEndianUShort strikeoutSize;
|
109
|
+
BigEndianUShort strikeoutPosition;
|
110
|
+
BigEndianUShort familyClass;
|
111
|
+
uint8_t panose[10];
|
112
|
+
BigEndianULong unicodeRange[4];
|
113
|
+
uint8_t vendID[4];
|
114
|
+
BigEndianUShort fsSelection;
|
115
|
+
BigEndianUShort firstCharIndex;
|
116
|
+
BigEndianUShort lastCharIndex;
|
117
|
+
BigEndianUShort typoAscender;
|
118
|
+
BigEndianUShort typoDescender;
|
119
|
+
BigEndianUShort typoLineGap;
|
120
|
+
BigEndianUShort winAscent;
|
121
|
+
BigEndianUShort winDescent;
|
122
|
+
BigEndianULong codePageRange[2];
|
123
|
+
BigEndianUShort xHeight;
|
124
|
+
BigEndianUShort capHeight;
|
125
|
+
BigEndianUShort defaultChar;
|
126
|
+
BigEndianUShort breakChar;
|
127
|
+
BigEndianUShort maxContext;
|
128
|
+
};
|
129
|
+
|
130
|
+
struct headTable {
|
131
|
+
Fixed version;
|
132
|
+
Fixed fontRevision;
|
133
|
+
BigEndianULong checkSumAdjustment;
|
134
|
+
BigEndianULong magicNumber;
|
135
|
+
BigEndianUShort flags;
|
136
|
+
BigEndianUShort unitsPerEm;
|
137
|
+
long long created;
|
138
|
+
long long modified;
|
139
|
+
BigEndianUShort xMin;
|
140
|
+
BigEndianUShort xMax;
|
141
|
+
BigEndianUShort yMin;
|
142
|
+
BigEndianUShort yMax;
|
143
|
+
BigEndianUShort macStyle;
|
144
|
+
BigEndianUShort lowestRectPPEM;
|
145
|
+
BigEndianUShort fontDirectionHint;
|
146
|
+
BigEndianUShort indexToLocFormat;
|
147
|
+
BigEndianUShort glyphDataFormat;
|
148
|
+
};
|
149
|
+
|
150
|
+
struct nameRecord {
|
151
|
+
BigEndianUShort platformID;
|
152
|
+
BigEndianUShort encodingID;
|
153
|
+
BigEndianUShort languageID;
|
154
|
+
BigEndianUShort nameID;
|
155
|
+
BigEndianUShort length;
|
156
|
+
BigEndianUShort offset;
|
157
|
+
};
|
158
|
+
|
159
|
+
struct nameTable {
|
160
|
+
BigEndianUShort format;
|
161
|
+
BigEndianUShort count;
|
162
|
+
BigEndianUShort stringOffset;
|
163
|
+
nameRecord nameRecords[1];
|
164
|
+
};
|
165
|
+
|
166
|
+
#pragma pack()
|
167
|
+
|
168
|
+
static void appendBigEndianStringToEOTHeader(vector<uint8_t>&eotHeader, const BigEndianUShort* string, unsigned short length)
|
169
|
+
{
|
170
|
+
size_t size = eotHeader.size();
|
171
|
+
eotHeader.resize(size + length + 2 * sizeof(unsigned short));
|
172
|
+
unsigned short* dst = reinterpret_cast<unsigned short*>(&eotHeader[0] + size);
|
173
|
+
unsigned i = 0;
|
174
|
+
dst[i++] = length;
|
175
|
+
unsigned numCharacters = length / 2;
|
176
|
+
for (unsigned j = 0; j < numCharacters; j++)
|
177
|
+
dst[i++] = string[j];
|
178
|
+
dst[i] = 0;
|
179
|
+
}
|
180
|
+
|
181
|
+
bool getEOTHeader(unsigned char* fontData, size_t fontSize, vector<uint8_t>& eotHeader, size_t& overlayDst, size_t& overlaySrc, size_t& overlayLength)
|
182
|
+
{
|
183
|
+
overlayDst = 0;
|
184
|
+
overlaySrc = 0;
|
185
|
+
overlayLength = 0;
|
186
|
+
|
187
|
+
size_t dataLength = fontSize;
|
188
|
+
const char* data = (const char *) fontData;
|
189
|
+
|
190
|
+
eotHeader.resize(sizeof(EOTPrefix));
|
191
|
+
EOTPrefix* prefix = reinterpret_cast<EOTPrefix*>(&eotHeader[0]);
|
192
|
+
|
193
|
+
prefix->fontDataSize = dataLength;
|
194
|
+
prefix->version = 0x00020001;
|
195
|
+
prefix->flags = 0;
|
196
|
+
|
197
|
+
if (dataLength < offsetof(sfntHeader, tables))
|
198
|
+
return false;
|
199
|
+
|
200
|
+
const sfntHeader* sfnt = reinterpret_cast<const sfntHeader*>(data);
|
201
|
+
|
202
|
+
if (dataLength < offsetof(sfntHeader, tables) + sfnt->numTables * sizeof(TableDirectoryEntry))
|
203
|
+
return false;
|
204
|
+
|
205
|
+
bool haveOS2 = false;
|
206
|
+
bool haveHead = false;
|
207
|
+
bool haveName = false;
|
208
|
+
|
209
|
+
const BigEndianUShort* familyName = 0;
|
210
|
+
unsigned short familyNameLength = 0;
|
211
|
+
const BigEndianUShort* subfamilyName = 0;
|
212
|
+
unsigned short subfamilyNameLength = 0;
|
213
|
+
const BigEndianUShort* fullName = 0;
|
214
|
+
unsigned short fullNameLength = 0;
|
215
|
+
const BigEndianUShort* versionString = 0;
|
216
|
+
unsigned short versionStringLength = 0;
|
217
|
+
|
218
|
+
for (unsigned i = 0; i < sfnt->numTables; i++) {
|
219
|
+
unsigned tableOffset = sfnt->tables[i].offset;
|
220
|
+
unsigned tableLength = sfnt->tables[i].length;
|
221
|
+
|
222
|
+
if (dataLength < tableOffset || dataLength < tableLength || dataLength < tableOffset + tableLength)
|
223
|
+
return false;
|
224
|
+
|
225
|
+
unsigned tableTag = sfnt->tables[i].tag;
|
226
|
+
switch (tableTag) {
|
227
|
+
case 'OS/2':
|
228
|
+
{
|
229
|
+
if (dataLength < tableOffset + sizeof(OS2Table))
|
230
|
+
return false;
|
231
|
+
|
232
|
+
haveOS2 = true;
|
233
|
+
const OS2Table* OS2 = reinterpret_cast<const OS2Table*>(data + tableOffset);
|
234
|
+
for (unsigned j = 0; j < 10; j++)
|
235
|
+
prefix->fontPANOSE[j] = OS2->panose[j];
|
236
|
+
prefix->italic = OS2->fsSelection & 0x01;
|
237
|
+
prefix->weight = OS2->weightClass;
|
238
|
+
// FIXME: Should use OS2->fsType, but some TrueType fonts set it to an over-restrictive value.
|
239
|
+
// Since ATS does not enforce this on Mac OS X, we do not enforce it either.
|
240
|
+
prefix->fsType = 0;
|
241
|
+
for (unsigned j = 0; j < 4; j++)
|
242
|
+
prefix->unicodeRange[j] = OS2->unicodeRange[j];
|
243
|
+
for (unsigned j = 0; j < 2; j++)
|
244
|
+
prefix->codePageRange[j] = OS2->codePageRange[j];
|
245
|
+
break;
|
246
|
+
}
|
247
|
+
case 'head':
|
248
|
+
{
|
249
|
+
if (dataLength < tableOffset + sizeof(headTable))
|
250
|
+
return false;
|
251
|
+
|
252
|
+
haveHead = true;
|
253
|
+
const headTable* head = reinterpret_cast<const headTable*>(data + tableOffset);
|
254
|
+
prefix->checkSumAdjustment = head->checkSumAdjustment;
|
255
|
+
break;
|
256
|
+
}
|
257
|
+
case 'name':
|
258
|
+
{
|
259
|
+
if (dataLength < tableOffset + offsetof(nameTable, nameRecords))
|
260
|
+
return false;
|
261
|
+
|
262
|
+
haveName = true;
|
263
|
+
const nameTable* name = reinterpret_cast<const nameTable*>(data + tableOffset);
|
264
|
+
for (int j = 0; j < name->count; j++) {
|
265
|
+
if (dataLength < tableOffset + offsetof(nameTable, nameRecords) + (j + 1) * sizeof(nameRecord))
|
266
|
+
return false;
|
267
|
+
if (name->nameRecords[j].platformID == 3 && name->nameRecords[j].encodingID == 1 && name->nameRecords[j].languageID == 0x0409) {
|
268
|
+
if (dataLength < tableOffset + name->stringOffset + name->nameRecords[j].offset + name->nameRecords[j].length)
|
269
|
+
return false;
|
270
|
+
|
271
|
+
unsigned short nameLength = name->nameRecords[j].length;
|
272
|
+
const BigEndianUShort* nameString = reinterpret_cast<const BigEndianUShort*>(data + tableOffset + name->stringOffset + name->nameRecords[j].offset);
|
273
|
+
|
274
|
+
switch (name->nameRecords[j].nameID) {
|
275
|
+
case 1:
|
276
|
+
familyNameLength = nameLength;
|
277
|
+
familyName = nameString;
|
278
|
+
break;
|
279
|
+
case 2:
|
280
|
+
subfamilyNameLength = nameLength;
|
281
|
+
subfamilyName = nameString;
|
282
|
+
break;
|
283
|
+
case 4:
|
284
|
+
fullNameLength = nameLength;
|
285
|
+
fullName = nameString;
|
286
|
+
break;
|
287
|
+
case 5:
|
288
|
+
versionStringLength = nameLength;
|
289
|
+
versionString = nameString;
|
290
|
+
break;
|
291
|
+
default:
|
292
|
+
break;
|
293
|
+
}
|
294
|
+
}
|
295
|
+
}
|
296
|
+
break;
|
297
|
+
}
|
298
|
+
default:
|
299
|
+
break;
|
300
|
+
}
|
301
|
+
if (haveOS2 && haveHead && haveName)
|
302
|
+
break;
|
303
|
+
}
|
304
|
+
|
305
|
+
prefix->charset = DEFAULT_CHARSET;
|
306
|
+
prefix->magicNumber = 0x504c;
|
307
|
+
prefix->reserved[0] = 0;
|
308
|
+
prefix->reserved[1] = 0;
|
309
|
+
prefix->reserved[2] = 0;
|
310
|
+
prefix->reserved[3] = 0;
|
311
|
+
prefix->padding1 = 0;
|
312
|
+
|
313
|
+
appendBigEndianStringToEOTHeader(eotHeader, familyName, familyNameLength);
|
314
|
+
appendBigEndianStringToEOTHeader(eotHeader, subfamilyName, subfamilyNameLength);
|
315
|
+
appendBigEndianStringToEOTHeader(eotHeader, versionString, versionStringLength);
|
316
|
+
|
317
|
+
// If possible, ensure that the family name is a prefix of the full name.
|
318
|
+
if (fullNameLength >= familyNameLength && memcmp(familyName, fullName, familyNameLength)) {
|
319
|
+
overlaySrc = reinterpret_cast<const char*>(fullName) - data;
|
320
|
+
overlayDst = reinterpret_cast<const char*>(familyName) - data;
|
321
|
+
overlayLength = familyNameLength;
|
322
|
+
}
|
323
|
+
|
324
|
+
appendBigEndianStringToEOTHeader(eotHeader, fullName, fullNameLength);
|
325
|
+
|
326
|
+
unsigned short padding = 0;
|
327
|
+
eotHeader.push_back(padding);
|
328
|
+
eotHeader.push_back(padding);
|
329
|
+
|
330
|
+
prefix = reinterpret_cast<EOTPrefix*>(&eotHeader[0]);
|
331
|
+
prefix->eotSize = eotHeader.size() + fontSize;
|
332
|
+
|
333
|
+
return true;
|
334
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
/* Modified for use with ttf2eot, originally from WebKit. */
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Copyright (C) 2008 Apple Inc. All rights reserved.
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions
|
8
|
+
* are met:
|
9
|
+
* 1. Redistributions of source code must retain the above copyright
|
10
|
+
* notice, this list of conditions and the following disclaimer.
|
11
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer in the
|
13
|
+
* documentation and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
16
|
+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
18
|
+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
19
|
+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
20
|
+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
21
|
+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
22
|
+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
23
|
+
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
24
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
25
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
#ifndef OpenTypeUtilities_h
|
29
|
+
#define OpenTypeUtilities_h
|
30
|
+
|
31
|
+
#include <cstddef>
|
32
|
+
#include <vector>
|
33
|
+
using std::vector;
|
34
|
+
|
35
|
+
bool getEOTHeader(unsigned char * fontData, size_t fontSize, vector<uint8_t>& eotHeader, size_t& overlayDst, size_t& overlaySrc, size_t& overlayLength);
|
36
|
+
|
37
|
+
|
38
|
+
#endif // OpenTypeUtilities_h
|
data/ext/reot/extconf.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Loads mkmf which is used to make makefiles for Ruby extensions
|
2
|
+
require 'mkmf'
|
3
|
+
|
4
|
+
$CFLAGS = "-Wall -Wno-multichar"
|
5
|
+
|
6
|
+
# Give it a name
|
7
|
+
extension_name = 'reot'
|
8
|
+
|
9
|
+
# The destination
|
10
|
+
dir_config(extension_name)
|
11
|
+
|
12
|
+
# Do the work
|
13
|
+
create_makefile(extension_name)
|
data/ext/reot/reot.cpp
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
// ttf2eot for ruby
|
2
|
+
// just using ruby Module with singleton method instead of cli
|
3
|
+
// Orignial code:
|
4
|
+
// http://code.google.com/p/ttf2eot/
|
5
|
+
|
6
|
+
// Include the Ruby headers and goodies
|
7
|
+
#include "ruby.h"
|
8
|
+
#include "OpenTypeUtilities.h"
|
9
|
+
|
10
|
+
VALUE Reot = Qnil;
|
11
|
+
|
12
|
+
extern "C" void Init_reot();
|
13
|
+
|
14
|
+
extern "C" VALUE method_convert(VALUE self, VALUE filepath, VALUE destination);
|
15
|
+
|
16
|
+
extern "C" void Init_reot() {
|
17
|
+
Reot = rb_define_module("Reot");
|
18
|
+
rb_define_singleton_method(Reot, "convert!", (VALUE(*)(...))&method_convert, 2);
|
19
|
+
}
|
20
|
+
|
21
|
+
extern "C" VALUE method_convert(VALUE self, VALUE filepath, VALUE destination) {
|
22
|
+
const size_t kFontInitSize = 8192;
|
23
|
+
vector<uint8_t> eotHeader(512);
|
24
|
+
size_t overlayDst = 0;
|
25
|
+
size_t overlaySrc = 0;
|
26
|
+
size_t overlayLength = 0;
|
27
|
+
size_t fontSize = kFontInitSize;
|
28
|
+
size_t fontOff = 0;
|
29
|
+
FILE *input, *output;
|
30
|
+
unsigned char *fontData;
|
31
|
+
|
32
|
+
char *input_file, *output_file;
|
33
|
+
input_file = StringValuePtr(filepath);
|
34
|
+
output_file = StringValuePtr(destination);
|
35
|
+
|
36
|
+
|
37
|
+
input = fopen(input_file, "rb");
|
38
|
+
output = fopen(output_file, "wb");
|
39
|
+
|
40
|
+
if ((fontData = (unsigned char *) malloc(fontSize)) == NULL) {
|
41
|
+
return Qfalse;
|
42
|
+
}
|
43
|
+
|
44
|
+
if(!input && !output) {
|
45
|
+
return Qfalse;
|
46
|
+
}
|
47
|
+
|
48
|
+
do {
|
49
|
+
size_t ret = fread(fontData + fontOff, 1, fontSize - fontOff, input);
|
50
|
+
if (ret && fontSize <= SIZE_MAX / 2) {
|
51
|
+
fontOff += ret;
|
52
|
+
if ((fontData = (unsigned char *) realloc(fontData, fontSize *= 2)) == NULL) {
|
53
|
+
return Qfalse;
|
54
|
+
}
|
55
|
+
} else if (ret) {
|
56
|
+
return Qfalse;
|
57
|
+
} else {
|
58
|
+
fontData = (unsigned char *) realloc(fontData, fontSize = fontOff);
|
59
|
+
break;
|
60
|
+
}
|
61
|
+
} while (true);
|
62
|
+
|
63
|
+
if (getEOTHeader(fontData, fontSize, eotHeader, overlayDst, overlaySrc, overlayLength)) {
|
64
|
+
fwrite(&eotHeader[0], eotHeader.size(), 1, output);
|
65
|
+
fwrite(fontData, fontSize, 1, output);
|
66
|
+
return Qtrue;
|
67
|
+
} else {
|
68
|
+
return Qfalse;
|
69
|
+
}
|
70
|
+
}
|
data/lib/reot/version.rb
ADDED
data/reot.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "reot/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "reot"
|
7
|
+
s.version = Reot::VERSION
|
8
|
+
s.authors = ["Josef Šimánek"]
|
9
|
+
s.email = ["retro@ballgag.cz"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{ttf2eot ruby wrapper}
|
12
|
+
s.description = %q{Simple ttf2eot convertor}
|
13
|
+
s.extensions = ["ext/reot/extconf.rb"]
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
s.add_development_dependency "rake-compiler"
|
22
|
+
end
|
Binary file
|
data/test/helper.rb
ADDED
data/test/reot_test.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestReot < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
File.delete('test/fonts/Metalista.ttf.eot') if File.exists?("test/fonts/Metalista.ttf.eot")
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_reot_converts_ttf_to_eot
|
9
|
+
assert Reot.convert!("test/fonts/Metalista.ttf", "test/fonts/Metalista.eot")
|
10
|
+
assert_equal 28672, File.size("test/fonts/Metalista.eot")
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_returns_false_for_bad_file_path
|
14
|
+
assert !Reot.convert!("un/ex/isting/path.ttf", "please/here.eot")
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: reot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Josef Šimánek
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake-compiler
|
16
|
+
requirement: &4034600 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *4034600
|
25
|
+
description: Simple ttf2eot convertor
|
26
|
+
email:
|
27
|
+
- retro@ballgag.cz
|
28
|
+
executables: []
|
29
|
+
extensions:
|
30
|
+
- ext/reot/extconf.rb
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- Gemfile
|
35
|
+
- README.md
|
36
|
+
- Rakefile
|
37
|
+
- ext/reot/OpenTypeUtilities.cpp
|
38
|
+
- ext/reot/OpenTypeUtilities.h
|
39
|
+
- ext/reot/extconf.rb
|
40
|
+
- ext/reot/reot.cpp
|
41
|
+
- lib/reot/version.rb
|
42
|
+
- reot.gemspec
|
43
|
+
- test/fonts/Metalista.ttf
|
44
|
+
- test/helper.rb
|
45
|
+
- test/reot_test.rb
|
46
|
+
homepage: ''
|
47
|
+
licenses: []
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
requirements: []
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.8.10
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: ttf2eot ruby wrapper
|
70
|
+
test_files:
|
71
|
+
- test/fonts/Metalista.ttf
|
72
|
+
- test/helper.rb
|
73
|
+
- test/reot_test.rb
|