Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ligature #267

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule has a significant performance cost. Will this feature work without this rule?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know a performance problem of optimizeLegibility. but, ligature fonts needs this property for rendering glyphs on browser. if you set ligature options to false, remove this properties.

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
77 changes: 63 additions & 14 deletions lib/fontcustom/scripts/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@
# Glyphs
#

NUMBER_GLYPH_NAMES = {
"0": "zero",
"1": "one",
"2": "two",
"3": "three",
"4": "four",
"5": "five",
"6": "six",
"7": "seven",
"8": "eight",
"9": "nine"
}

def resolveGlyphName( c ):
return NUMBER_GLYPH_NAMES[c] if c in NUMBER_GLYPH_NAMES else c

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

return tmpsvgfile.name

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 ):
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