Skip to content

Commit

Permalink
Support ligatures
Browse files Browse the repository at this point in the history
  • Loading branch information
rosylilly committed Jun 18, 2017
1 parent 4ff2fbf commit ed48772
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 21 deletions.
1 change: 1 addition & 0 deletions lib/fontcustom.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def gem_lib
:autowidth => false,
:no_hash => false,
:css3 => false,
:ligature => false,
:debug => false,
:force => false,
:quiet => false,
Expand Down
4 changes: 4 additions & 0 deletions lib/fontcustom/generator/font.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ def set_glyph_info
data[:codepoint] = codepoint
codepoint = codepoint + 1
end

if @options[:ligature]
data[:ligature] = name.to_s.gsub(/[^a-zA-Z0-9]+/, '')
end
end
@manifest.set :glyphs, glyphs
end
Expand Down
15 changes: 13 additions & 2 deletions lib/fontcustom/generator/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ def glyph_selectors
end

def glyph_properties
%Q| display: inline-block;
properties = %Q| display: inline-block;
font-family: "#{font_name}";
font-style: normal;
font-weight: normal;
Expand All @@ -209,11 +209,22 @@ def glyph_properties
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-smoothing: antialiased;|
if @options[:ligature]
properties += %Q|
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;|
end

properties
end

def glyphs
output = @glyphs.map do |name, value|
%Q|#{@options[:css_selector].sub('{{glyph}}', name.to_s)}#{@pseudo_element} { content: "\\#{value[:codepoint].to_s(16)}"; }|
content = @options[:ligature] ? name.to_s : "\\#{value[:codepoint].to_s(16)}"
%Q|#{@options[:css_selector].sub('{{glyph}}', name.to_s)}#{@pseudo_element} { content: "\\#{content}"; }|
end
output.join "\n"
end
Expand Down
87 changes: 72 additions & 15 deletions lib/fontcustom/scripts/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,30 @@
# Glyphs
#

def resolveGlyphName( c ):
if c == "0":
c = "zero"
elif c == "1":
c = "one"
elif c == "2":
c = "two"
elif c == "3":
c = "three"
elif c == "4":
c = "four"
elif c == "5":
c = "five"
elif c == "6":
c = "six"
elif c == "7":
c = "seven"
elif c == "8":
c = "eight"
elif c == "9":
c = "nine"

return c;

def removeSwitchFromSvg( file ):
svgfile = open(file, 'r')
svgtext = svgfile.read()
Expand All @@ -59,46 +83,79 @@ def removeSwitchFromSvg( file ):

return tmpsvgfile.name

def createGlyph( name, source, code ):
def setGlyphWidth( glyph ):
if options['autowidth']:
glyph.left_side_bearing = glyph.right_side_bearing = 0
glyph.round()
else:
glyph.width = options['font_em']
width = glyph.width - glyph.left_side_bearing - glyph.right_side_bearing
aligned_to_pixel_grid = (width % design_px == 0)
if (aligned_to_pixel_grid):
shift = glyph.left_side_bearing % design_px
glyph.left_side_bearing = glyph.left_side_bearing - shift
glyph.right_side_bearing = glyph.right_side_bearing + shift

def createEmptyGlyph(code):
glyph = font.createChar(ord(code), resolveGlyphName(code))
pen = glyph.glyphPen()
pen.moveTo(0, 0)
pen = None

def createGlyph( name, source, code, data ):
frag, ext = os.path.splitext(source)

if ext == '.svg':
temp = removeSwitchFromSvg(source)
glyph = font.createChar(code, name)
if options['ligature']:
glyph = font.createChar(code, str(name))
else:
glyph = font.createChar(code)
glyph.importOutlines(temp)
os.unlink(temp)

if options['autowidth']:
glyph.left_side_bearing = glyph.right_side_bearing = 0
glyph.round()
else:
glyph.width = options['font_em']
width = glyph.width - glyph.left_side_bearing - glyph.right_side_bearing
aligned_to_pixel_grid = (width % design_px == 0)
if (aligned_to_pixel_grid):
shift = glyph.left_side_bearing % design_px
glyph.left_side_bearing = glyph.left_side_bearing - shift
glyph.right_side_bearing = glyph.right_side_bearing + shift
setGlyphWidth(glyph)

if options['ligature']:
liganame = str(data['ligature'])
chars = []
for char in liganame:
createEmptyGlyph(char)
charName = resolveGlyphName(char)
chars.append(charName)
liga = tuple(chars)
print liga
glyph.addPosSub('liga', liga)

# Add valid space glyph to avoid "unknown character" box on IE11
glyph = font.createChar(32)
glyph.width = 200

if options['ligature']:
font.addLookup('liga', 'gsub_ligature', (), (('liga', (('latn', ('dflt')), )), ))
font.addLookupSubtable('liga', 'liga')

for glyph, data in manifest['glyphs'].items():
name = createGlyph(glyph, data['source'], data['codepoint'])

#
# Generate Files
#

def generateFont( filename ):
if options['ligature']:
font.generate(filename, flags=('opentype'))
else:
font.generate(filename)

try:
fontfile = options['output']['fonts'] + '/' + options['font_name']
if not options['no_hash']:
fontfile += '_' + manifest['checksum']['current'][:32]

# Generate TTF and SVG
font.generate(fontfile + '.ttf')
font.generate(fontfile + '.svg')
generateFont(fontfile + '.ttf')
generateFont(fontfile + '.svg')
manifest['fonts'].append(fontfile + '.ttf')
manifest['fonts'].append(fontfile + '.svg')

Expand Down
5 changes: 4 additions & 1 deletion lib/fontcustom/templates/fontcustom-preview.html
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
text-align: center;
}

.usage .point { width: 150px; }
.usage .point, .usage .liagture { width: 150px; }

.usage .class { width: 250px; }

Expand Down Expand Up @@ -162,6 +162,9 @@ <h1><%= font_name %> contains <%= @glyphs.length %> glyphs:</h1>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value="<%= selector %>" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#x<%= value[:codepoint].to_s(16) %>;" />
<% if @options[:ligature] %>
<input class="ligature" type="text" readonly="readonly" onClick="this.select();" value="<%= value[:ligature].to_s %>" />
<% end %>
</div>
</div>
<% end %>
Expand Down
3 changes: 3 additions & 0 deletions lib/fontcustom/templates/fontcustom.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,6 @@

# Horizontally fit glyphs to their individual vector widths.
#autowidth: false

# Activate ligature mode.
#ligature: false
16 changes: 13 additions & 3 deletions spec/fontcustom/generator/template_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
live_test do |testdir|
FileUtils.cp_r fixture("generators/mixed-output"), "fontcustom"
test_manifest(
:input => "vectors",
:input => "vectors",
:quiet => true,
:templates => %w|preview css scss scss-rails|
)
Expand Down Expand Up @@ -85,9 +85,9 @@
gen.send :create_files
end
end

context ".font_face" do
it "should return base64 when options are set" do
it "should return base64 when options are set" do
gen = Fontcustom::Generator::Template.new fixture("generators/.fontcustom-manifest.json")
allow(gen).to receive(:woff_base64).and_return("3xampled4ta")
options = gen.instance_variable_get :@options
Expand All @@ -97,6 +97,16 @@
end
end

context ".glyph_properties" do
it "should contain optimizeLegibility when options are set" do
gen = Fontcustom::Generator::Template.new fixture("generators/.fontcustom-manifest.json")
options = gen.instance_variable_get :@options
options[:ligature] = true

expect(gen.send(:glyph_properties)).to match("optimizeLegibility")
end
end

context ".get_target_path" do
it "should generate the correct preview target when using default font_name" do
gen = Fontcustom::Generator::Template.new fixture("generators/.fontcustom-manifest.json")
Expand Down

0 comments on commit ed48772

Please sign in to comment.