fontcustom 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,20 @@
1
+ ## 0.1.3 (2/2/2013)
2
+ * Add --debug CLI option, which shows fontforge output ([#37](https://github.com/FontCustom/fontcustom/issues/37))
3
+ * Patch for Illustrator CS6 SVG output ([#42](https://github.com/FontCustom/fontcustom/pull/42))
4
+ * Generate IE7 stylesheet ([#43](https://github.com/FontCustom/fontcustom/pull/43))
5
+ * Option to set custom font path for @font-face ([#43](https://github.com/FontCustom/fontcustom/pull/43))
6
+ * Option to generate test HTML file showing all glyphs ([#43](https://github.com/FontCustom/fontcustom/pull/43))
7
+ * Use eotlite.py instead of mkeot ([#43](https://github.com/FontCustom/fontcustom/pull/43))
8
+
1
9
  ## 0.1.0 (12/2/2012)
2
10
 
3
11
  * Changed API to use Thor `class_option`s
4
- * Added option to change the name of the font and generated files ([#6](https://github.com/endtwist/fontcustom/issues/6))
5
- * Added option to disable the file name hash ([#13](https://github.com/endtwist/fontcustom/issues/13))
12
+ * Added option to change the name of the font and generated files ([#6](https://github.com/FontCustom/fontcustom/issues/6))
13
+ * Added option to disable the file name hash ([#13](https://github.com/FontCustom/fontcustom/issues/13))
6
14
  * `fontcustom watch` compiles automatically on the first run
7
15
  * Better help messages
8
16
 
9
17
  ## 0.0.2 (11/26/2012)
10
18
 
11
- * Fixed gemspec dependency bug ([#2](https://github.com/endtwist/fontcustom/pull/2))
12
- * Fixed Windows Chrome PUA bug ([#1](https://github.com/endtwist/fontcustom/issues/1))
19
+ * Fixed gemspec dependency bug ([#2](https://github.com/FontCustom/fontcustom/pull/2))
20
+ * Fixed Windows Chrome PUA bug ([#1](https://github.com/FontCustom/fontcustom/issues/1))
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
- FontCustom v0.1.2
1
+ FontCustom v0.1.3
2
2
  ==========
3
3
 
4
4
  **Generate custom icon webfonts from the comfort of the command line.**
5
5
 
6
- [Full documentation](http://endtwist.github.com/fontcustom/)<br/>
7
- [Feedback and issues](https://github.com/endtwist/fontcustom/issues)
6
+ [Full documentation](http://fontcustom.github.com/fontcustom/)<br/>
7
+ [Feedback and issues](https://github.com/FontCustom/fontcustom/issues)
8
8
 
9
9
 
10
10
  Installation
@@ -26,3 +26,9 @@ fontcustom watch path/to/vectors # Watch for changes
26
26
  ```
27
27
 
28
28
  Optional second parameter allows you to specify an output directory.
29
+
30
+ Need help?
31
+
32
+ ```sh
33
+ fontcustom --help
34
+ ```
@@ -7,6 +7,9 @@ module Fontcustom
7
7
  class_option :output, :aliases => '-o', :desc => 'Specify an output directory. Default: $DIR/fontcustom'
8
8
  class_option :name, :aliases => '-n', :desc => 'Specify a font name. This will be used in the generated fonts and CSS. Default: fontcustom'
9
9
  class_option :nohash, :type => :boolean, :default => false, :desc => 'Disable filename hashes. Default: false'
10
+ class_option :debug, :type => :boolean, :default => false, :desc => 'Display debug messages. Default: false'
11
+ class_option :font_path, :aliases => '-f', :desc => 'Specify a path for fonts in css @font-face declaration. Default: none'
12
+ class_option :html, :type => :boolean, :default => false, :desc => 'Generate html page with icons'
10
13
 
11
14
  desc 'compile DIR [options]', 'Generates webfonts and CSS from *.svg and *.eps files in DIR.'
12
15
  def compile(*args)
@@ -11,6 +11,9 @@ module Fontcustom
11
11
  class_option :output, :aliases => '-o'
12
12
  class_option :name, :aliases => '-n'
13
13
  class_option :nohash, :type => :boolean, :default => false
14
+ class_option :debug, :type => :boolean, :default => false
15
+ class_option :font_path, :aliases => '-f'
16
+ class_option :html, :type => :boolean, :default => false
14
17
 
15
18
  def self.source_root
16
19
  File.dirname(__FILE__)
@@ -45,6 +48,8 @@ module Fontcustom
45
48
 
46
49
  def cleanup_output_dir
47
50
  css = File.join(@output, 'fontcustom.css')
51
+ css_ie7 = File.join(@output, 'fontcustom-ie7.css')
52
+ test_html = File.join(@output, 'test.html')
48
53
  old_name = if File.exists? css
49
54
  line = IO.readlines(css)[5] # font-family: "Example Font";
50
55
  line.scan(/".+"/)[0][1..-2].gsub(/\W/, '-').downcase # => 'example-font'
@@ -54,6 +59,8 @@ module Fontcustom
54
59
 
55
60
  old_files = Dir[File.join(@output, old_name + '-*.{woff,ttf,eot,svg}')]
56
61
  old_files << css if File.exists?(css)
62
+ old_files << css_ie7 if File.exists?(css_ie7)
63
+ old_files << test_html if File.exists?(test_html)
57
64
  old_files.each {|file| remove_file file }
58
65
  end
59
66
 
@@ -64,7 +71,11 @@ module Fontcustom
64
71
 
65
72
  # suppress fontforge message
66
73
  # TODO get font name and classes from script (without showing fontforge message)
67
- `fontforge -script #{gem_file_path}/scripts/generate.py #{input} #{@output + name + nohash} > /dev/null 2>&1`
74
+ cmd = "fontforge -script #{gem_file_path}/scripts/generate.py #{input} #{@output + name + nohash}"
75
+ unless options.debug
76
+ cmd += " > /dev/null 2>&1"
77
+ end
78
+ `#{cmd}`
68
79
  end
69
80
 
70
81
  def show_paths
@@ -79,9 +90,16 @@ module Fontcustom
79
90
  def create_stylesheet
80
91
  files = Dir[File.join(input, '*.{svg,eps}')]
81
92
  @classes = files.map {|file| File.basename(file)[0..-5].gsub(/\W/, '-').downcase }
82
- @path = File.basename(@path)
93
+ if(!options.font_path.nil?)
94
+ font_path = (options.font_path) ? options.font_path : ''
95
+ @path = File.join(font_path, File.basename(@path))
96
+ else
97
+ @path = File.basename(@path)
98
+ end
83
99
 
84
100
  template('templates/fontcustom.css', File.join(@output, 'fontcustom.css'))
101
+ template('templates/fontcustom-ie7.css', File.join(@output, 'fontcustom-ie7.css'))
102
+ template('templates/test.html', File.join(@output, 'test.html')) if options.html
85
103
  end
86
104
  end
87
105
  end
@@ -0,0 +1,466 @@
1
+ #!/usr/bin/env python
2
+ # ***** BEGIN LICENSE BLOCK *****
3
+ # Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
+ #
5
+ # The contents of this file are subject to the Mozilla Public License Version
6
+ # 1.1 (the "License"); you may not use this file except in compliance with
7
+ # the License. You may obtain a copy of the License at
8
+ # http://www.mozilla.org/MPL/
9
+ #
10
+ # Software distributed under the License is distributed on an "AS IS" basis,
11
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
+ # for the specific language governing rights and limitations under the
13
+ # License.
14
+ #
15
+ # The Original Code is font utility code.
16
+ #
17
+ # The Initial Developer of the Original Code is Mozilla Corporation.
18
+ # Portions created by the Initial Developer are Copyright (C) 2009
19
+ # the Initial Developer. All Rights Reserved.
20
+ #
21
+ # Contributor(s):
22
+ # John Daggett <jdaggett@mozilla.com>
23
+ #
24
+ # Alternatively, the contents of this file may be used under the terms of
25
+ # either the GNU General Public License Version 2 or later (the "GPL"), or
26
+ # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
+ # in which case the provisions of the GPL or the LGPL are applicable instead
28
+ # of those above. If you wish to allow use of your version of this file only
29
+ # under the terms of either the GPL or the LGPL, and not to allow others to
30
+ # use your version of this file under the terms of the MPL, indicate your
31
+ # decision by deleting the provisions above and replace them with the notice
32
+ # and other provisions required by the GPL or the LGPL. If you do not delete
33
+ # the provisions above, a recipient may use your version of this file under
34
+ # the terms of any one of the MPL, the GPL or the LGPL.
35
+ #
36
+ # ***** END LICENSE BLOCK ***** */
37
+
38
+ # eotlitetool.py - create EOT version of OpenType font for use with IE
39
+ #
40
+ # Usage: eotlitetool.py [-o output-filename] font1 [font2 ...]
41
+ #
42
+
43
+ # OpenType file structure
44
+ # http://www.microsoft.com/typography/otspec/otff.htm
45
+ #
46
+ # Types:
47
+ #
48
+ # BYTE 8-bit unsigned integer.
49
+ # CHAR 8-bit signed integer.
50
+ # USHORT 16-bit unsigned integer.
51
+ # SHORT 16-bit signed integer.
52
+ # ULONG 32-bit unsigned integer.
53
+ # Fixed 32-bit signed fixed-point number (16.16)
54
+ # LONGDATETIME Date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a signed 64-bit integer.
55
+ #
56
+ # SFNT Header
57
+ #
58
+ # Fixed sfnt version // 0x00010000 for version 1.0.
59
+ # USHORT numTables // Number of tables.
60
+ # USHORT searchRange // (Maximum power of 2 <= numTables) x 16.
61
+ # USHORT entrySelector // Log2(maximum power of 2 <= numTables).
62
+ # USHORT rangeShift // NumTables x 16-searchRange.
63
+ #
64
+ # Table Directory
65
+ #
66
+ # ULONG tag // 4-byte identifier.
67
+ # ULONG checkSum // CheckSum for this table.
68
+ # ULONG offset // Offset from beginning of TrueType font file.
69
+ # ULONG length // Length of this table.
70
+ #
71
+ # OS/2 Table (Version 4)
72
+ #
73
+ # USHORT version // 0x0004
74
+ # SHORT xAvgCharWidth
75
+ # USHORT usWeightClass
76
+ # USHORT usWidthClass
77
+ # USHORT fsType
78
+ # SHORT ySubscriptXSize
79
+ # SHORT ySubscriptYSize
80
+ # SHORT ySubscriptXOffset
81
+ # SHORT ySubscriptYOffset
82
+ # SHORT ySuperscriptXSize
83
+ # SHORT ySuperscriptYSize
84
+ # SHORT ySuperscriptXOffset
85
+ # SHORT ySuperscriptYOffset
86
+ # SHORT yStrikeoutSize
87
+ # SHORT yStrikeoutPosition
88
+ # SHORT sFamilyClass
89
+ # BYTE panose[10]
90
+ # ULONG ulUnicodeRange1 // Bits 0-31
91
+ # ULONG ulUnicodeRange2 // Bits 32-63
92
+ # ULONG ulUnicodeRange3 // Bits 64-95
93
+ # ULONG ulUnicodeRange4 // Bits 96-127
94
+ # CHAR achVendID[4]
95
+ # USHORT fsSelection
96
+ # USHORT usFirstCharIndex
97
+ # USHORT usLastCharIndex
98
+ # SHORT sTypoAscender
99
+ # SHORT sTypoDescender
100
+ # SHORT sTypoLineGap
101
+ # USHORT usWinAscent
102
+ # USHORT usWinDescent
103
+ # ULONG ulCodePageRange1 // Bits 0-31
104
+ # ULONG ulCodePageRange2 // Bits 32-63
105
+ # SHORT sxHeight
106
+ # SHORT sCapHeight
107
+ # USHORT usDefaultChar
108
+ # USHORT usBreakChar
109
+ # USHORT usMaxContext
110
+ #
111
+ #
112
+ # The Naming Table is organized as follows:
113
+ #
114
+ # [name table header]
115
+ # [name records]
116
+ # [string data]
117
+ #
118
+ # Name Table Header
119
+ #
120
+ # USHORT format // Format selector (=0).
121
+ # USHORT count // Number of name records.
122
+ # USHORT stringOffset // Offset to start of string storage (from start of table).
123
+ #
124
+ # Name Record
125
+ #
126
+ # USHORT platformID // Platform ID.
127
+ # USHORT encodingID // Platform-specific encoding ID.
128
+ # USHORT languageID // Language ID.
129
+ # USHORT nameID // Name ID.
130
+ # USHORT length // String length (in bytes).
131
+ # USHORT offset // String offset from start of storage area (in bytes).
132
+ #
133
+ # head Table
134
+ #
135
+ # Fixed tableVersion // Table version number 0x00010000 for version 1.0.
136
+ # Fixed fontRevision // Set by font manufacturer.
137
+ # ULONG checkSumAdjustment // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum.
138
+ # ULONG magicNumber // Set to 0x5F0F3CF5.
139
+ # USHORT flags
140
+ # USHORT unitsPerEm // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
141
+ # LONGDATETIME created // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
142
+ # LONGDATETIME modified // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
143
+ # SHORT xMin // For all glyph bounding boxes.
144
+ # SHORT yMin
145
+ # SHORT xMax
146
+ # SHORT yMax
147
+ # USHORT macStyle
148
+ # USHORT lowestRecPPEM // Smallest readable size in pixels.
149
+ # SHORT fontDirectionHint
150
+ # SHORT indexToLocFormat // 0 for short offsets, 1 for long.
151
+ # SHORT glyphDataFormat // 0 for current format.
152
+ #
153
+ #
154
+ #
155
+ # Embedded OpenType (EOT) file format
156
+ # http://www.w3.org/Submission/EOT/
157
+ #
158
+ # EOT version 0x00020001
159
+ #
160
+ # An EOT font consists of a header with the original OpenType font
161
+ # appended at the end. Most of the data in the EOT header is simply a
162
+ # copy of data from specific tables within the font data. The exceptions
163
+ # are the 'Flags' field and the root string name field. The root string
164
+ # is a set of names indicating domains for which the font data can be
165
+ # used. A null root string implies the font data can be used anywhere.
166
+ # The EOT header is in little-endian byte order but the font data remains
167
+ # in big-endian order as specified by the OpenType spec.
168
+ #
169
+ # Overall structure:
170
+ #
171
+ # [EOT header]
172
+ # [EOT name records]
173
+ # [font data]
174
+ #
175
+ # EOT header
176
+ #
177
+ # ULONG eotSize // Total structure length in bytes (including string and font data)
178
+ # ULONG fontDataSize // Length of the OpenType font (FontData) in bytes
179
+ # ULONG version // Version number of this format - 0x00020001
180
+ # ULONG flags // Processing Flags (0 == no special processing)
181
+ # BYTE fontPANOSE[10] // OS/2 Table panose
182
+ # BYTE charset // DEFAULT_CHARSET (0x01)
183
+ # BYTE italic // 0x01 if ITALIC in OS/2 Table fsSelection is set, 0 otherwise
184
+ # ULONG weight // OS/2 Table usWeightClass
185
+ # USHORT fsType // OS/2 Table fsType (specifies embedding permission flags)
186
+ # USHORT magicNumber // Magic number for EOT file - 0x504C.
187
+ # ULONG unicodeRange1 // OS/2 Table ulUnicodeRange1
188
+ # ULONG unicodeRange2 // OS/2 Table ulUnicodeRange2
189
+ # ULONG unicodeRange3 // OS/2 Table ulUnicodeRange3
190
+ # ULONG unicodeRange4 // OS/2 Table ulUnicodeRange4
191
+ # ULONG codePageRange1 // OS/2 Table ulCodePageRange1
192
+ # ULONG codePageRange2 // OS/2 Table ulCodePageRange2
193
+ # ULONG checkSumAdjustment // head Table CheckSumAdjustment
194
+ # ULONG reserved[4] // Reserved - must be 0
195
+ # USHORT padding1 // Padding - must be 0
196
+ #
197
+ # EOT name records
198
+ #
199
+ # USHORT FamilyNameSize // Font family name size in bytes
200
+ # BYTE FamilyName[FamilyNameSize] // Font family name (name ID = 1), little-endian UTF-16
201
+ # USHORT Padding2 // Padding - must be 0
202
+ #
203
+ # USHORT StyleNameSize // Style name size in bytes
204
+ # BYTE StyleName[StyleNameSize] // Style name (name ID = 2), little-endian UTF-16
205
+ # USHORT Padding3 // Padding - must be 0
206
+ #
207
+ # USHORT VersionNameSize // Version name size in bytes
208
+ # bytes VersionName[VersionNameSize] // Version name (name ID = 5), little-endian UTF-16
209
+ # USHORT Padding4 // Padding - must be 0
210
+ #
211
+ # USHORT FullNameSize // Full name size in bytes
212
+ # BYTE FullName[FullNameSize] // Full name (name ID = 4), little-endian UTF-16
213
+ # USHORT Padding5 // Padding - must be 0
214
+ #
215
+ # USHORT RootStringSize // Root string size in bytes
216
+ # BYTE RootString[RootStringSize] // Root string, little-endian UTF-16
217
+
218
+
219
+
220
+ import optparse
221
+ import struct
222
+
223
+ class FontError(Exception):
224
+ """Error related to font handling"""
225
+ pass
226
+
227
+ def multichar(str):
228
+ vals = struct.unpack('4B', str[:4])
229
+ return (vals[0] << 24) + (vals[1] << 16) + (vals[2] << 8) + vals[3]
230
+
231
+ def multicharval(v):
232
+ return struct.pack('4B', (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF)
233
+
234
+ class EOT:
235
+ EOT_VERSION = 0x00020001
236
+ EOT_MAGIC_NUMBER = 0x504c
237
+ EOT_DEFAULT_CHARSET = 0x01
238
+ EOT_FAMILY_NAME_INDEX = 0 # order of names in variable portion of EOT header
239
+ EOT_STYLE_NAME_INDEX = 1
240
+ EOT_VERSION_NAME_INDEX = 2
241
+ EOT_FULL_NAME_INDEX = 3
242
+ EOT_NUM_NAMES = 4
243
+
244
+ EOT_HEADER_PACK = '<4L10B2BL2H7L18x'
245
+
246
+ class OpenType:
247
+ SFNT_CFF = multichar('OTTO') # Postscript CFF SFNT version
248
+ SFNT_TRUE = 0x10000 # Standard TrueType version
249
+ SFNT_APPLE = multichar('true') # Apple TrueType version
250
+
251
+ SFNT_UNPACK = '>I4H'
252
+ TABLE_DIR_UNPACK = '>4I'
253
+
254
+ TABLE_HEAD = multichar('head') # TrueType table tags
255
+ TABLE_NAME = multichar('name')
256
+ TABLE_OS2 = multichar('OS/2')
257
+ TABLE_GLYF = multichar('glyf')
258
+ TABLE_CFF = multichar('CFF ')
259
+
260
+ OS2_FSSELECTION_ITALIC = 0x1
261
+ OS2_UNPACK = '>4xH2xH22x10B4L4xH14x2L'
262
+
263
+ HEAD_UNPACK = '>8xL'
264
+
265
+ NAME_RECORD_UNPACK = '>6H'
266
+ NAME_ID_FAMILY = 1
267
+ NAME_ID_STYLE = 2
268
+ NAME_ID_UNIQUE = 3
269
+ NAME_ID_FULL = 4
270
+ NAME_ID_VERSION = 5
271
+ NAME_ID_POSTSCRIPT = 6
272
+ PLATFORM_ID_UNICODE = 0 # Mac OS uses this typically
273
+ PLATFORM_ID_MICROSOFT = 3
274
+ ENCODING_ID_MICROSOFT_UNICODEBMP = 1 # with Microsoft platformID BMP-only Unicode encoding
275
+ LANG_ID_MICROSOFT_EN_US = 0x0409 # with Microsoft platformID EN US lang code
276
+
277
+ def eotname(ttf):
278
+ i = ttf.rfind('.')
279
+ if i != -1:
280
+ ttf = ttf[:i]
281
+ return ttf + '.eotlite'
282
+
283
+ def readfont(f):
284
+ data = open(f, 'rb').read()
285
+ return data
286
+
287
+ def get_table_directory(data):
288
+ """read the SFNT header and table directory"""
289
+ datalen = len(data)
290
+ sfntsize = struct.calcsize(OpenType.SFNT_UNPACK)
291
+ if sfntsize > datalen:
292
+ raise FontError, 'truncated font data'
293
+ sfntvers, numTables = struct.unpack(OpenType.SFNT_UNPACK, data[:sfntsize])[:2]
294
+ if sfntvers != OpenType.SFNT_CFF and sfntvers != OpenType.SFNT_TRUE:
295
+ raise FontError, 'invalid font type';
296
+
297
+ font = {}
298
+ font['version'] = sfntvers
299
+ font['numTables'] = numTables
300
+
301
+ # create set of offsets, lengths for tables
302
+ table_dir_size = struct.calcsize(OpenType.TABLE_DIR_UNPACK)
303
+ if sfntsize + table_dir_size * numTables > datalen:
304
+ raise FontError, 'truncated font data, table directory extends past end of data'
305
+ table_dir = {}
306
+ for i in range(0, numTables):
307
+ start = sfntsize + i * table_dir_size
308
+ end = start + table_dir_size
309
+ tag, check, bongo, dirlen = struct.unpack(OpenType.TABLE_DIR_UNPACK, data[start:end])
310
+ table_dir[tag] = {'offset': bongo, 'length': dirlen, 'checksum': check}
311
+
312
+ font['tableDir'] = table_dir
313
+
314
+ return font
315
+
316
+ def get_name_records(nametable):
317
+ """reads through the name records within name table"""
318
+ name = {}
319
+ # read the header
320
+ headersize = 6
321
+ count, strOffset = struct.unpack('>2H', nametable[2:6])
322
+ namerecsize = struct.calcsize(OpenType.NAME_RECORD_UNPACK)
323
+ if count * namerecsize + headersize > len(nametable):
324
+ raise FontError, 'names exceed size of name table'
325
+ name['count'] = count
326
+ name['strOffset'] = strOffset
327
+
328
+ # read through the name records
329
+ namerecs = {}
330
+ for i in range(0, count):
331
+ start = headersize + i * namerecsize
332
+ end = start + namerecsize
333
+ platformID, encodingID, languageID, nameID, namelen, offset = struct.unpack(OpenType.NAME_RECORD_UNPACK, nametable[start:end])
334
+ if platformID != OpenType.PLATFORM_ID_MICROSOFT or \
335
+ encodingID != OpenType.ENCODING_ID_MICROSOFT_UNICODEBMP or \
336
+ languageID != OpenType.LANG_ID_MICROSOFT_EN_US:
337
+ continue
338
+ namerecs[nameID] = {'offset': offset, 'length': namelen}
339
+
340
+ name['namerecords'] = namerecs
341
+ return name
342
+
343
+ def make_eot_name_headers(fontdata, nameTableDir):
344
+ """extracts names from the name table and generates the names header portion of the EOT header"""
345
+ nameoffset = nameTableDir['offset']
346
+ namelen = nameTableDir['length']
347
+ name = get_name_records(fontdata[nameoffset : nameoffset + namelen])
348
+ namestroffset = name['strOffset']
349
+ namerecs = name['namerecords']
350
+
351
+ eotnames = (OpenType.NAME_ID_FAMILY, OpenType.NAME_ID_STYLE, OpenType.NAME_ID_VERSION, OpenType.NAME_ID_FULL)
352
+ nameheaders = []
353
+ for nameid in eotnames:
354
+ if nameid in namerecs:
355
+ namerecord = namerecs[nameid]
356
+ noffset = namerecord['offset']
357
+ nlen = namerecord['length']
358
+ nformat = '%dH' % (nlen / 2) # length is in number of bytes
359
+ start = nameoffset + namestroffset + noffset
360
+ end = start + nlen
361
+ nstr = struct.unpack('>' + nformat, fontdata[start:end])
362
+ nameheaders.append(struct.pack('<H' + nformat + '2x', nlen, *nstr))
363
+ else:
364
+ nameheaders.append(struct.pack('4x')) # len = 0, padding = 0
365
+
366
+ return ''.join(nameheaders)
367
+
368
+ # just return a null-string (len = 0)
369
+ def make_root_string():
370
+ return struct.pack('2x')
371
+
372
+ def make_eot_header(fontdata):
373
+ """given ttf font data produce an EOT header"""
374
+ fontDataSize = len(fontdata)
375
+ font = get_table_directory(fontdata)
376
+
377
+ # toss out .otf fonts, t2embed library doesn't support these
378
+ tableDir = font['tableDir']
379
+
380
+ # check for required tables
381
+ required = (OpenType.TABLE_HEAD, OpenType.TABLE_NAME, OpenType.TABLE_OS2)
382
+ for table in required:
383
+ if not (table in tableDir):
384
+ raise FontError, 'missing required table ' + multicharval(table)
385
+
386
+ # read name strings
387
+
388
+ # pull out data from individual tables to construct fixed header portion
389
+ # need to calculate eotSize before packing
390
+ version = EOT.EOT_VERSION
391
+ flags = 0
392
+ charset = EOT.EOT_DEFAULT_CHARSET
393
+ magicNumber = EOT.EOT_MAGIC_NUMBER
394
+
395
+ # read values from OS/2 table
396
+ os2Dir = tableDir[OpenType.TABLE_OS2]
397
+ os2offset = os2Dir['offset']
398
+ os2size = struct.calcsize(OpenType.OS2_UNPACK)
399
+
400
+ if os2size > os2Dir['length']:
401
+ raise FontError, 'OS/2 table invalid length'
402
+
403
+ os2fields = struct.unpack(OpenType.OS2_UNPACK, fontdata[os2offset : os2offset + os2size])
404
+
405
+ panose = []
406
+ urange = []
407
+ codepage = []
408
+
409
+ weight, fsType = os2fields[:2]
410
+ panose[:10] = os2fields[2:12]
411
+ urange[:4] = os2fields[12:16]
412
+ fsSelection = os2fields[16]
413
+ codepage[:2] = os2fields[17:19]
414
+
415
+ italic = fsSelection & OpenType.OS2_FSSELECTION_ITALIC
416
+
417
+ # read in values from head table
418
+ headDir = tableDir[OpenType.TABLE_HEAD]
419
+ headoffset = headDir['offset']
420
+ headsize = struct.calcsize(OpenType.HEAD_UNPACK)
421
+
422
+ if headsize > headDir['length']:
423
+ raise FontError, 'head table invalid length'
424
+
425
+ headfields = struct.unpack(OpenType.HEAD_UNPACK, fontdata[headoffset : headoffset + headsize])
426
+ checkSumAdjustment = headfields[0]
427
+
428
+ # make name headers
429
+ nameheaders = make_eot_name_headers(fontdata, tableDir[OpenType.TABLE_NAME])
430
+ rootstring = make_root_string()
431
+
432
+ # calculate the total eot size
433
+ eotSize = struct.calcsize(EOT.EOT_HEADER_PACK) + len(nameheaders) + len(rootstring) + fontDataSize
434
+ fixed = struct.pack(EOT.EOT_HEADER_PACK,
435
+ *([eotSize, fontDataSize, version, flags] + panose + [charset, italic] +
436
+ [weight, fsType, magicNumber] + urange + codepage + [checkSumAdjustment]))
437
+
438
+ return ''.join((fixed, nameheaders, rootstring))
439
+
440
+
441
+ def write_eot_font(eot, header, data):
442
+ open(eot,'wb').write(''.join((header, data)))
443
+ return
444
+
445
+ def main():
446
+
447
+ # deal with options
448
+ p = optparse.OptionParser()
449
+ p.add_option('--output', '-o', default="world")
450
+ options, args = p.parse_args()
451
+
452
+ # iterate over font files
453
+ for f in args:
454
+ data = readfont(f)
455
+ if len(data) == 0:
456
+ print 'Error reading %s' % f
457
+ else:
458
+ eot = eotname(f)
459
+ header = make_eot_header(data)
460
+ write_eot_font(eot, header, data)
461
+
462
+
463
+ if __name__ == '__main__':
464
+ main()
465
+
466
+
@@ -10,6 +10,7 @@ try:
10
10
  parser.add_argument('dir', metavar='directory', type=unicode, nargs=2, help='directory of vector files')
11
11
  parser.add_argument('--name', metavar='fontname', type=unicode, nargs='?', default='fontcustom', help='reference name of the font (no spaces)')
12
12
  parser.add_argument('--nohash', '-n', action='store_true', help='disable hash fingerprinting of font files')
13
+ parser.add_argument('--debug', '-d', action='store_true', help='display debug messages')
13
14
  args = parser.parse_args()
14
15
  indir = args.dir[0]
15
16
  outdir = args.dir[1]
@@ -19,6 +20,7 @@ except ImportError:
19
20
  parser = optparse.OptionParser(description='Convert a directory of svg and eps files into a unified font file.')
20
21
  parser.add_option('--name', metavar='fontname', type='string', nargs='?', default='fontcustom', help='reference name of the font (no spaces)')
21
22
  parser.add_option('--nohash', '-n', action='store_true', help='disable hash fingerprinting of font files')
23
+ parser.add_argument('--debug', '-d', action='store_true', help='display debug messages')
22
24
  (args, posargs) = parser.parse_args()
23
25
  indir = posargs[0]
24
26
  outdir = posargs[1]
@@ -39,6 +41,23 @@ for dirname, dirnames, filenames in os.walk(indir):
39
41
  size = os.path.getsize(filePath)
40
42
 
41
43
  if ext in ['.svg', '.eps']:
44
+ if ext in ['.svg']:
45
+ # hack removal of <switch> </switch> tags
46
+ svgfile = open(filePath, 'r+')
47
+ svgtext = svgfile.read()
48
+ svgfile.seek(0)
49
+
50
+ # replace the <switch> </switch> tags with 'nothing'
51
+ svgtext = svgtext.replace('<switch>', '')
52
+ svgtext = svgtext.replace('</switch>', '')
53
+
54
+ # remove all contents of file so that we can write out the new contents
55
+ svgfile.truncate()
56
+ svgfile.write(svgtext)
57
+
58
+ svgfile.close()
59
+ # end hack
60
+
42
61
  m.update(filename + str(size) + ';')
43
62
  glyph = f.createChar(cp)
44
63
  glyph.importOutlines(filePath)
@@ -82,7 +101,9 @@ except OSError:
82
101
  # sfnt2woff from source, simplifying install.
83
102
  subprocess.call(['sfnt2woff', fontfile + '.ttf'])
84
103
 
85
- subprocess.call('mkeot ' + fontfile + '.ttf > ' + fontfile + '.eot', shell=True)
104
+ # eotlitetool.py script to generate IE7-compatible .eot fonts
105
+ subprocess.call('python ' + scriptPath + '/eotlitetool.py ' + fontfile + '.ttf -o ' + fontfile + '.eot', shell=True)
106
+ subprocess.call('mv ' + fontfile + '.eotlite ' + fontfile + '.eot', shell=True)
86
107
 
87
108
  # Hint the TTF file
88
109
  subprocess.call('ttfautohint -s -n ' + fontfile + '.ttf ' + fontfile + '-hinted.ttf > /dev/null 2>&1 && mv ' + fontfile + '-hinted.ttf ' + fontfile + '.ttf', shell=True)
@@ -0,0 +1,18 @@
1
+ [class^="icon-"],
2
+ [class*=" icon-"] {
3
+ font-family: "<%= @name %>";
4
+ font-style: normal;
5
+ font-weight: normal;
6
+ }
7
+ .btn.dropdown-toggle [class^="icon-"],
8
+ .btn.dropdown-toggle [class*=" icon-"] {
9
+ /* keeps button heights with and without icons the same */
10
+
11
+ line-height: 1.4em;
12
+ }
13
+ .icon-large {
14
+ font-size: 1.3333em;
15
+ }
16
+
17
+ <% @classes.each_with_index do |name, index| %>
18
+ .icon-<%= name %> { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x<%= (61696+index).to_s(16) %>;&nbsp;');} <% end %>
@@ -0,0 +1,100 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>Your Font/Glyphs</title>
5
+ <!--[if IE]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
6
+
7
+ <link rel="stylesheet" href="fontcustom.css" />
8
+ <!--[if lte IE 7]>
9
+ <link rel="stylesheet" href="fontcustom-ie7.css" />
10
+ <![endif]-->
11
+
12
+
13
+ <style>
14
+ section, header, footer {display: block;}
15
+ body {
16
+ font-family: sans-serif;
17
+ color: #444;
18
+ line-height: 1.5;
19
+ font-size: 1em;
20
+ }
21
+ * {
22
+ -moz-box-sizing: border-box;
23
+ -webkit-box-sizing: border-box;
24
+ box-sizing: border-box;
25
+ margin: 0;
26
+ padding: 0;
27
+ }
28
+ .glyph {
29
+ float: left;
30
+ text-align: center;
31
+ background: #eee;
32
+ padding: .75em;
33
+ margin: .75em 1.5em .75em 0;
34
+ width: 7em;
35
+ border-radius: .25em;
36
+ box-shadow: inset 0 0 0 1px #f8f8f8, 0 0 0 1px #CCC;
37
+ }
38
+ .glyph input {
39
+ width: 100%;
40
+ text-align: center;
41
+ font-family: consolas, monospace;
42
+ }
43
+ .glyph input, .mtm {
44
+ margin-top: .75em;
45
+ }
46
+ .w-main {
47
+ width: 80%;
48
+ }
49
+ .centered {
50
+ margin-left: auto;
51
+ margin-right: auto;
52
+ }
53
+ .fs1 {
54
+ font-size: 2em;
55
+ }
56
+ header {
57
+ margin: 2em 0;
58
+ padding-bottom: .5em;
59
+ color: #666;
60
+ box-shadow: 0 2px #eee;
61
+ }
62
+ header h1 {
63
+ font-size: 2em;
64
+ font-weight: normal;
65
+ }
66
+ .clearfix:before, .clearfix:after { content: ""; display: table; }
67
+ .clearfix:after, .clear { clear: both; }
68
+ footer {
69
+ margin-top: 2em;
70
+ padding: .5em 0;
71
+ box-shadow: 0 -2px #eee;
72
+ }
73
+ a, a:visited {
74
+ color: #B35047;
75
+ text-decoration: none;
76
+ }
77
+ a:hover, a:focus {color: #000;}
78
+ .box1 {
79
+ display: inline-block;
80
+ width: 15em;
81
+ padding: .25em .5em;
82
+ background: #eee;
83
+ margin: .5em 1em .5em 0;
84
+ }
85
+ </style>
86
+ </head>
87
+ <body>
88
+ <div class="w-main centered">
89
+ <section class="mtm clearfix" id="glyphs">
90
+ <header> <h1>Your font contains the following glyphs</h1> </header>
91
+ <% @classes.each_with_index do |name, index| %>
92
+ <div class="glyph">
93
+ <div class="fs1" ><i class="icon-<%= name %>"></i></div>
94
+ <input type="text" readonly="readonly" value="&amp;#x<%= (61696+index).to_s(16) %>;" />
95
+ </div>
96
+ <% end %>
97
+ </section>
98
+ </div>
99
+ </body>
100
+ </html>
@@ -1,3 +1,3 @@
1
1
  module Fontcustom
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fontcustom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-12-09 00:00:00.000000000 Z
13
+ date: 2013-02-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -210,9 +210,12 @@ files:
210
210
  - lib/fontcustom.rb
211
211
  - lib/fontcustom/cli.rb
212
212
  - lib/fontcustom/generator.rb
213
+ - lib/fontcustom/scripts/eotlitetool.py
213
214
  - lib/fontcustom/scripts/generate.py
214
215
  - lib/fontcustom/scripts/sfnt2woff
216
+ - lib/fontcustom/templates/fontcustom-ie7.css
215
217
  - lib/fontcustom/templates/fontcustom.css
218
+ - lib/fontcustom/templates/test.html
216
219
  - lib/fontcustom/version.rb
217
220
  - lib/fontcustom/watcher.rb
218
221
  - spec/fixtures/empty/no_vectors_here.txt