Permalink
Browse files

Refactored loading of web fonts

  • Loading branch information...
nvh committed Jul 20, 2017
1 parent 6c82841 commit f1e64b93ec4feab9661006e87a161fa8137b1977
Showing with 183 additions and 19 deletions.
  1. +4 −0 framer/TextLayer.coffee
  2. +88 −18 framer/Utils.coffee
  3. +1 −0 test/phantomjs/index.html
  4. +90 −1 test/tests/UtilsTest.coffee
View
@@ -165,6 +165,10 @@ class exports.TextLayer extends Layer
@define "fontFamily", textProperty(@, "fontFamily", null, _.isString, fontFamilyFromObject, (layer, value) ->
return if value is null
layer.font = value
promise = Utils.isFontFamilyLoaded(value)
if _.isObject(promise)
promise.then ->
layer.renderText()
)
@define "fontWeight", textProperty(@, "fontWeight")
@define "fontStyle", textProperty(@, "fontStyle", "normal", _.isString)
View
@@ -1,7 +1,7 @@
{_} = require "./Underscore"
{Screen} = require "./Screen"
{Matrix} = require "./Matrix"
WebFont = require('webfontloader')
Utils = {}
Utils.reset = ->
@@ -493,24 +493,94 @@ Utils.deviceFont = (os) ->
return appleFont
# Load fonts from Google Web Fonts
_loadedFonts = []
Utils.loadWebFont = (font, weight) ->
fontToLoad = font
fontToLoad += ":#{weight}" if weight?
fontObject = {fontFamily: font, fontWeight: weight}
if fontToLoad in _loadedFonts
return fontObject
link = document.createElement("link")
_isFontLoadedResults = {}
Utils.isFontFamilyLoaded = (font, timeout = 10000) ->
return Utils.loadWebFontConfig
custom:
families: [font]
timeout: timeout
fontsFromConfig = (config) ->
result = []
if _.isArray(config?.custom?.families)
result = result.concat(config?.custom?.families)
if _.isArray(config?.google?.families)
result = result.concat(config?.google?.families)
return result
link.href = "https://fonts.googleapis.com/css?family=#{fontToLoad}"
link.rel = "stylesheet"
document.getElementsByTagName("head")[0].appendChild(link) unless window.TESTING
_loadedFonts.push(fontToLoad)
return fontObject
Utils.loadWebFontConfig = (config) ->
fonts = fontsFromConfig(config)
allLoadedResult = null
for currentFont in fonts
currentFontLoaded = _isFontLoadedResults[currentFont]
if not currentFontLoaded?
allLoadedResult = null
break
allLoadedResult ?= currentFontLoaded
allLoadedResult = allLoadedResult and currentFontLoaded
if allLoadedResult?
return allLoadedResult
promise =
resolved: false
error: null
resolve: null
reject: null
'then': (cb) ->
@resolve = cb
@resolve?() if @resolved
return @
'catch': (cb) ->
@reject = cb
@reject?(@error) if @error?
return @
customActive = config.active
customInactive = config.inactive
customFontactive = config.fontactive
customFontinactive = config.fontinactive
config.fontloading = (font) ->
console.log "loading", font
config.fontactive = (font) ->
console.log "active", font
_isFontLoadedResults[font] = true
customFontactive?()
config.fontinactive = (font) ->
console.log "inactive", font
_isFontLoadedResults[font] = false
customFontinactive?()
config.active = ->
console.log "allactive", fonts
promise.resolve?()
promise.resolved = true
customActive?()
config.inactive = ->
console.log "allinactive", fonts
error = new Error("#{fonts.join(', ')} failed to load")
promise.reject?(error)
promise.error = error
customInactive?()
WebFont.load config
return promise
Utils.loadWebFont = (font, weight, source = "google") ->
delete _isFontLoadedResults[font]
config = {}
if source is "google"
fontToLoad = font
fontToLoad += ":#{weight}" if weight?
config.google =
families: [fontToLoad]
Utils.loadWebFontConfig config
return {fontFamily: font, fontWeight: weight}
######################################################
# MATH FUNCTIONS
@@ -2,6 +2,7 @@
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style type="text/css">
<style type="text/css">
.framerContext {visibility: hidden}
</style>
</head>
@@ -271,6 +271,96 @@ describe "Utils", ->
# it "should return the right size with height constraint", ->
# Utils.textSize(text, style, {height: 100}).should.eql(width: 168, height: 100)
describe "loadWebFontConfig", ->
it "should resolve the promise if the font is loaded", (done) ->
promise = Utils.loadWebFontConfig
custom:
families: ["Liberation Test"]
urls: ["static/fonts/liberation.css"]
promise.then ->
done()
return
it "should return true if the font is already correctly loaded", (done) ->
promise = Utils.loadWebFontConfig
custom:
families: ["Liberation Sans"]
promise.then ->
result = Utils.loadWebFontConfig
custom:
families: ["Liberation Sans"]
result.should.equal true
done()
return
it "should return a promise", (done) ->
promise = Utils.loadWebFontConfig
custom:
families: ["Test"]
timeout: 100
promise.catch ->
done()
return
it "should reject the promise if the font can't be loaded", (done) ->
promise = Utils.loadWebFontConfig
custom:
families: ["Test2"]
timeout: 100
promise.catch (error) ->
error.message.should.equal "Test2 failed to load"
done()
return
it "should return false if the font has already failed loading", (done) ->
promise = Utils.loadWebFontConfig
custom:
families: ["Test3"]
timeout: 100
promise.catch ->
result = Utils.loadWebFontConfig
custom:
families: ["Test3"]
result.should.equal false
done()
return
it "should support loading webfonts with WebFontConfig syntax", (done) ->
result = Utils.loadWebFontConfig
custom:
families: ['Random font']
timeout: 100
result.catch (e) ->
e.message.should.equal "Random font failed to load"
done()
return
it.skip "should not interfere with each other", (done) ->
Utils.loadWebFont("Raleway")
roboto = Utils.loadWebFontConfig
google:
families: ['Roboto']
roboto.then ->
done()
return
it "should cache loading of google fonts"
it "should support loading multiple fonts at the same time"
it "should return a promise if one of the fonts is not yet loaded"
it "should return true if all the fonts are loaded"
it "should return false if any fonts are already failed loading"
it "should return an promise like object"
it "should cache the specific fonts that succeeded loading"
it "should call the custom active and inactive handlers"
it "should cache the specific fonts that failed loading"
it "should override the active and inactive callbacks"
describe "isFontFamilyLoaded", ->
it "should reset the result if a new load request is made", ->
Utils.loadWebFont("Raleway")
promise = Utils.isFontFamilyLoaded("Raleway", 100)
promise.should.have.property('then')
describe "loadWebFont", ->
it "loads fonts at different weights" , ->
raleway = Utils.loadWebFont("Raleway")
@@ -286,7 +376,6 @@ describe "Utils", ->
raleway200 = Utils.loadWebFont("Raleway", 800)
raleway200.should.eql {fontFamily: "Raleway", fontWeight: 800}
describe "frameSortByAbsoluteDistance", ->
it "should sort x", ->

0 comments on commit f1e64b9

Please sign in to comment.