├── .gitignore
├── .npmignore
├── LICENSE.md
├── README.md
├── demo
├── FordAntenna.png
├── demo-sdf.html
├── demo.html
├── fonts.json
├── gl-load-textures.js
├── index.js
├── js
│ ├── bundle.js
│ └── sdf-bundle.js
├── sdf.js
├── sdf
│ ├── DejaVu-sdf.fnt
│ ├── DejaVu-sdf.json
│ ├── DejaVu-sdf.png
│ ├── LatoBlack-sdf.fnt
│ ├── LatoBlack-sdf.json
│ ├── LatoBlack-sdf.png
│ ├── dummy.txt
│ ├── frag.glsl
│ └── vert.glsl
└── simple.js
├── index.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | bower_components
2 | node_modules
3 | *.log
4 | .DS_Store
5 | bundle.js
6 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | bower_components
2 | node_modules
3 | *.log
4 | .DS_Store
5 | bundle.js
6 | test
7 | test.js
8 | demo/
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2014 Matt DesLauriers
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
20 | OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gl-sprite-text
2 |
3 | [](http://github.com/badges/stability-badges)
4 |
5 | 
6 |
7 | A solution for bitmap and [SDF](http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf) text rendering in stack.gl. This uses [gl-sprite-batch](https://nodei.co/npm/gl-sprite-batch/) and [fontpath](https://www.npmjs.org/package/fontpath-simple-renderer) under the hood.
8 |
9 | The [BMFont spec](https://www.npmjs.org/package/bmfont2json) is used for glyph and font data. You also need to pass an array of [gl-texture2d](https://www.npmjs.org/package/gl-texture2d) items matching the `paths` specified by the font file. (Multi-page fonts are supported.)
10 |
11 | The `font` object can also include an `images` array (ndarray/HTMLImage), which will get piped into `gl-texture2d`. You can use [bmfont-lato](https://www.npmjs.org/package/bmfont-lato) for testing; it includes Lato Regular in a few sizes and the base64-inlined `images` ndarray.
12 |
13 | ```js
14 | var createText = require('gl-sprite-text')
15 | var Lato = require('bmfont-lato')
16 |
17 | //build the text
18 | text = createText(gl, {
19 | font: Lato,
20 | text: 'Hello, World!'
21 | })
22 |
23 | //optionally word-wrap it to a specific width
24 | text.layout(500)
25 |
26 | function render() {
27 | //draws the text with lower-left origin
28 | text.draw(shader)
29 | }
30 | ```
31 |
32 | See [demo/simple.js](demo/simple.js) for an example. After `npm install`, you can run it with:
33 |
34 | ```npm run demo-simple```
35 |
36 | ## Tools
37 |
38 | After you've exported the BMFont with [your favourite tool](https://github.com/libgdx/libgdx/wiki/Hiero), you can run it through [bmfont2json](https://www.npmjs.org/package/bmfont2json) to produce valid output:
39 |
40 | ```sh
41 | # if you haven't already, install the tool globally
42 | npm install bmfont2json -g
43 |
44 | # then you can use it like so..
45 | bmfont2json Lato32.fnt > Lato32.json
46 | ```
47 |
48 | ## Signed Distance Fields
49 |
50 | Bitmap fonts are great for fixed-size text, but if you need large fonts, or fonts that scale smoothly (i.e. if it's being 3D transformed), it's better to use alpha testing to avoid aliasing artifacts. To generate SDF font atlases, you can use [Hiero and LibGDX](https://github.com/libgdx/libgdx/wiki/Distance-field-fonts). Then, you need to render it with a signed distance field shader. See the [demo/sdf.js](demo/sdf.js) example:
51 |
52 | ```npm run demo-sdf```
53 |
54 | As you can see from the demo, you can also achieve drop shadows, outlines, glows and other effects with independent colors.
55 |
56 | ## Static Text
57 |
58 | By default, the text is pushed to dynamic buffers every frame. This allows it to animate (e.g. changing position, start/end indices, text content), and also ensures that underlines and multi-page textures will work.
59 |
60 | Basic static text is supported with the `cache()` method. Static text only supports a single texture page, and no underlines.
61 |
62 | ```js
63 | var text = createText(gl, {
64 | font: myFont,
65 | textures: textures,
66 | text: str,
67 |
68 | //hint to buffers that they will be static
69 | dynamic: false
70 | })
71 |
72 | //cache the current text state
73 | text.cache(x, y, start, end)
74 |
75 | function render() {
76 | text.draw(shader)
77 | }
78 | ```
79 |
80 | ## Usage
81 |
82 | [](https://nodei.co/npm/gl-sprite-text/)
83 |
84 | Inherits from `fontpath-simple-renderer` so the API should work, but this module may diverge from it in the future. Here is the current public API:
85 |
86 | #### `text = createText(opts)`
87 |
88 | The following options can be provided:
89 |
90 | - `font` the bitmap font object, required
91 | - `textures` an array of gl textures to match `font.paths`. If this is not specified, it will look for an `images` array in the `font` object, which can be ndarrays, HTMLImage objects, or anything that gets piped to `createTexture`.
92 | - `text` the string of text we will be rendering, default to empty string
93 | - `align` a string 'left', 'center', 'right', default left
94 | - `underline` boolean, whether to underline the text, default false
95 | - `underlinePosition` the position of underline in pixels, defaults to a fraction of font size
96 | - `underlineThickness` the underline thickness in pixels, defaults to a fraction of font size
97 | - `lineHeight` a line height in pixels, otherwise defaults to an automatic gap
98 | - `letterSpacing` the letter spacing in pixels, default 0
99 | - `wrapMode` can be `normal`, `pre`, or `nowrap`, default `normal`
100 | - `wrapWidth` an initial number in pixels which is passed to `layout()` after the other options have been set. Otherwise, defaults to no layout (a single line, no breaks)
101 | - `capacity` an initial capacity to use for gl-sprite-batch
102 | - `dynamic` whether the WebGL buffers should use `DYNAMIC_DRAW`, default true
103 |
104 | All options except for `font`, `wrapMode` and `wrapWidth` are fields which be changed at runtime, before calling `draw()`.
105 |
106 | *Note:* Changing the `text` currently calls `clearLayout()`. You will need to call `layout()` again.
107 |
108 | #### `text.draw(shader[, x, y, start, end])`
109 |
110 | Draws the text with the given shader, at the specified pixel position (lower-left origin).
111 |
112 | The `start` (inclusive) and `end` (exclusive) indices will draw the laid out glyphs within those bounds. This can be used to style and colour different pieces of text. If not specified, they will default to 0 and the text length, respectively.
113 |
114 | If text is cached, the `x, y, start, end` parameters are ignored.
115 |
116 | #### `text.layout([wrapWidth])`
117 |
118 | Word-wraps the text with the current wrap mode to the optional given width. You can change the wrap mode like so:
119 |
120 | ```js
121 | text.wordwrap.mode = 'pre'
122 | text.layout(250)
123 | ```
124 |
125 | If no width is specified, it will only break on explicit newline characters `\n`.
126 |
127 | This creates some new objects in memory, so you may not want to do it every frame.
128 |
129 | #### `text.clearLayout()`
130 |
131 | Clears the current word-wrapping. This leads to a single line of text, no line-breaks.
132 |
133 | #### `text.getBounds()`
134 |
135 | Returns an object with the computed bounds of the text box:
136 |
137 | ```{ x, y, width height }```
138 |
139 | This can be used to draw the text at an upper-left origin instead.
140 |
141 | #### `text.cache([x, y, start, end])`
142 |
143 | Caches the current text parameters into a static buffer. Underlines are not supported; and this only works with one texture page (e.g. all glyphs in a single sprite sheet).
144 |
145 | The parameters replace those in `draw()`. When cached, `draw()` will ignore the `x, y, start, end` parameters.
146 |
147 | #### `text.uncache()`
148 |
149 | Disables caching, allowing it to be animated dynamically again.
150 |
151 | #### `text.dispose([textures])`
152 |
153 | If no `batch` was provided during the constructor, this will dispose of the default (internally created) batch.
154 |
155 | Specifying true for `textures` (default false) will also dispose of the texture array associated with this text object.
156 |
157 | ## License
158 |
159 | MIT, see [LICENSE.md](http://github.com/mattdesl/gl-sprite-text/blob/master/LICENSE.md) for details.
--------------------------------------------------------------------------------
/demo/FordAntenna.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattdesl/gl-sprite-text/d9cac3c5413e591d54115e8b4f4a31ed5cd32bdf/demo/FordAntenna.png
--------------------------------------------------------------------------------
/demo/demo-sdf.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SDF fonts
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/demo/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | test
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/demo/gl-load-textures.js:
--------------------------------------------------------------------------------
1 |
2 | var Promise = require('bluebird')
3 | var Texture = require('gl-texture2d')
4 |
5 | var imgAsync = Promise.promisify(require('img'))
6 |
7 | function texAsync(gl, path) {
8 | return imgAsync(path).then(function(img) {
9 | return Texture(gl, img)
10 | })
11 | }
12 |
13 | module.exports = function(gl, paths) {
14 | return Promise.all(paths.map(function(p) {
15 | return texAsync(gl, p)
16 | }))
17 | }
--------------------------------------------------------------------------------
/demo/index.js:
--------------------------------------------------------------------------------
1 | //This is a fairly complex demo, the sdf.js or simple.js demos
2 | //might be a better place to look!
3 |
4 | require('canvas-testbed')(render, start, { context: 'webgl' })
5 |
6 | var createText = require('../')
7 | var bmfont = require('./fonts.json')[12]
8 | var bmfont2 = require('./fonts.json')[8]
9 | var bmfontSmall = require('./fonts.json')[17]
10 |
11 | var Shader = require('gl-basic-shader')
12 | var Batch = require('gl-sprite-batch')
13 | var mat4 = require('gl-mat4')
14 |
15 | var loadTextures = require('./gl-load-textures')
16 |
17 | var ortho = mat4.create()
18 | var renderer, batch, shader
19 | var staticBatch
20 | var bigText
21 |
22 | var transform = mat4.create()
23 | var DPR = (window.devicePixelRatio||1)
24 | var time = 0
25 |
26 | function render(gl, width, height, dt) {
27 | time += dt
28 | if (!renderer)
29 | return
30 |
31 | gl.clearColor(0,0,0,1)
32 | gl.clear(gl.COLOR_BUFFER_BIT)
33 |
34 | gl.enable(gl.BLEND)
35 | gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
36 |
37 | shader.bind()
38 | shader.uniforms.texture0 = 0
39 |
40 |
41 | //setup projection & camera matrices
42 | mat4.ortho(ortho, 0, width, height, 0, 0, 1)
43 |
44 |
45 | shader.uniforms.projection = ortho
46 | shader.uniforms.tint = [1, 1, 1, 1]
47 |
48 | //set some new text
49 | renderer.text = 'this field is dynamic '+ (time/1000).toFixed(1)
50 |
51 | //get new bounds
52 | var bounds = renderer.getBounds()
53 |
54 | //retina scale it and translate it to top left
55 | mat4.identity(transform)
56 | mat4.scale(transform, transform, [1/DPR, 1/DPR, 1.0])
57 | mat4.translate(transform, transform, [0, bounds.height, 0])
58 |
59 | shader.uniforms.model = transform
60 |
61 | //draw the dynamic text
62 | var anim = Math.round((Math.sin(time/1000)/2+0.5)*renderer.text.length)
63 | renderer.draw(shader, 20, 20, 0, anim)
64 |
65 | shader.uniforms.tint = [1, 0.5, 0.5, 1.0]
66 | textSmall.draw(shader, 100, 140)
67 |
68 | /////draw some static text with custom texture
69 | shader.uniforms.tint = [1, 1, 1, 1]
70 | gl.enable(gl.SCISSOR_TEST)
71 |
72 | //clip some of our text
73 | var pad = 250
74 | gl.scissor(0, pad, width*DPR, height*DPR-pad*2)
75 |
76 | var off = 100,
77 | yoff = -(Math.sin(time/2000)/2+0.5) * 500
78 |
79 | mat4.identity(transform)
80 | mat4.scale(transform, transform, [1/DPR, 1/DPR, 1.0])
81 | mat4.translate(transform, transform, [off, yoff + bigText.getBounds().height+off, 0])
82 | shader.uniforms.model = transform
83 |
84 | bigText.draw(shader)
85 |
86 | gl.disable(gl.SCISSOR_TEST)
87 | }
88 |
89 | function start(gl, width) {
90 | batch = Batch(gl)
91 |
92 | shader = Shader(gl, {
93 | color: true,
94 | texcoord: true
95 | })
96 |
97 | //bmfont.pages is an array of image paths for each sheet
98 | //uses promises to async load and upload some textures
99 | loadTextures(gl, bmfont.pages).then(function(p) {
100 | renderer = createText(gl, {
101 | font: bmfont,
102 | textures: p
103 | })
104 |
105 | textSmall = createText(gl, {
106 | font: bmfontSmall,
107 | text: [
108 | 'all text rendered in pure WebGL',
109 | 'a 2048x2048 texture holds 25 different font sizes/styles',
110 | 'the text area below is drawn with a static buffer on the GPU'
111 | ].join('\n'),
112 | textures: p
113 | })
114 | //wrap newlines
115 | textSmall.layout()
116 |
117 | //We can only create static text once the texture
118 | //size is known, otherwise the texcoords will be wrong.
119 | createStaticText(p, width*1.5)
120 | })
121 | }
122 |
123 | function createStaticText(textures, wrapWidth) {
124 | //if we know that the static text uses a SINGLE
125 | //texture sheet and no underlines, we can pack it all
126 | //into the same buffer and keep it static on GPU.
127 |
128 | //This is an advanced optimization only worth doing in
129 | //certain edge cases.
130 |
131 | var text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam rutrum sollicitudin nunc pellentesque condimentum. Morbi nec ipsum nec ipsum imperdiet imperdiet non eget mi. Fusce vitae ante et nisl malesuada luctus et et dui. Suspendisse gravida accumsan metus, a vestibulum justo malesuada at. Duis in luctus erat. Cras pellentesque placerat felis eget pretium. Donec lobortis nulla vitae velit congue, id commodo purus venenatis. Phasellus varius, magna ac efficitur tincidunt, turpis ipsum cursus diam, vel cursus nisl lorem eget enim. Aliquam sollicitudin lacinia nunc, eu hendrerit libero consequat nec. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec varius semper neque, eget rutrum urna egestas et. Proin et lorem feugiat ligula pulvinar porta at semper dolor. Proin efficitur, est et scelerisque tempus, nulla est gravida augue, in commodo ipsum nibh ac ipsum. In odio ex, semper eu felis et, tristique vestibulum metus. Morbi tristique pretium elit, non placerat ipsum sodales a. Integer diam odio, laoreet non venenatis sed, sollicitudin vel turpis. Vivamus pellentesque imperdiet metus. Nullam molestie bibendum tellus vel dignissim. Cras a diam sollicitudin, vehicula mi at, lobortis augue. Morbi vestibulum eget leo eget ultricies. Curabitur pellentesque, nisi a consequat mattis, arcu arcu ullamcorper felis, in finibus diam nulla ac erat. Nulla tempus justo nunc, at rutrum arcu luctus vitae. Nulla sit amet accumsan sem, at vestibulum nunc. Vestibulum dictum ligula ut neque dapibus rutrum. Curabitur ultrices leo egestas, ullamcorper enim eu, scelerisque ligula. Ut sed augue risus. Cras ut enim diam. Quisque id commodo quam, non commodo tortor. Fusce justo risus, scelerisque vel blandit eu, lacinia nec neque. Aenean iaculis porttitor condimentum. Aliquam congue fermentum odio, a molestie sem posuere ac. Nam et diam sit amet leo auctor tempus. Nam eu diam justo. Sed quis cursus risus. Nullam ultricies risus id sapien commodo finibus. Donec quis magna lacinia, feugiat mi quis, dignissim tortor.'
132 | text = text+text
133 | bigText = createText(gl, {
134 | font: bmfont2,
135 | align: 'left',
136 | text: text,
137 | wrapWidth: wrapWidth,
138 | textures: textures,
139 | dyanmic: false
140 | })
141 |
142 | bigText.cache()
143 | }
--------------------------------------------------------------------------------
/demo/sdf.js:
--------------------------------------------------------------------------------
1 | require('canvas-testbed')(render, start, { context: 'webgl' })
2 |
3 | var createText = require('../')
4 | var createTexture = require('gl-texture2d')
5 | var createBackground = require('gl-checker-background')
6 | var clear = require('gl-clear')({ color: [0.25,0.25,0.25,1] })
7 | var loadImage = require('img')
8 |
9 | var fs = require('fs')
10 | var lerp = require('lerp')
11 | var ease = require('eases/quart-in')
12 | var mat4 = require('gl-mat4')
13 |
14 | //LatoBlack-sdf is also ready to go..
15 | var Font = require('./sdf/DejaVu-sdf.json')
16 | var texturePath = 'sdf/DejaVu-sdf.png'
17 |
18 | //the text to show on screen
19 | var copy = fs.readFileSync(__dirname+'/sdf/frag.glsl', 'utf8')
20 |
21 | //setup our SDF shader
22 | var glslify = require('glslify')
23 | var createShader = glslify({
24 | vertex: __dirname+'/sdf/vert.glsl',
25 | fragment: __dirname+'/sdf/frag.glsl'
26 | })
27 |
28 | var text,
29 | ortho = mat4.create(),
30 | scale = mat4.create(),
31 | shader,
32 | time = 600
33 |
34 | //let's do a bit of syntax styling..
35 | var reg = /\/\/(.*)$/gm.exec(copy)
36 | if (!reg)
37 | reg = { index: 0, '0': '' }
38 |
39 | function render(gl, width, height, dt) {
40 | time += dt/1000
41 | clear(gl)
42 |
43 | if (!text)
44 | return
45 |
46 | gl.enable(gl.BLEND)
47 | gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
48 |
49 | background.draw()
50 |
51 | mat4.ortho(ortho, 0, width, height, 0, 0, 1)
52 |
53 | var anim = ease(Math.sin(time/2)/2+0.5)
54 | var s = lerp(0.5, 2.0, anim)
55 | mat4.identity(scale)
56 | mat4.scale(scale, scale, [s, s, 0])
57 |
58 | //gl-basic-shader gives us some matrices we can use
59 | shader.bind()
60 | shader.uniforms.projection = ortho
61 | shader.uniforms.view = scale
62 |
63 | var bounds = text.getBounds()
64 |
65 | var white = [1,1,1,1]
66 | var x = 20,
67 | y = 10+bounds.height
68 |
69 | //NOTE: real syntax highlighting would want to manipulate
70 | //the underlying batch for vertex coloring
71 | shader.uniforms.tint = white
72 | text.draw(shader, x, y, 0, reg.index)
73 |
74 | shader.uniforms.tint = [140/255, 218/255, 115/255, 1.0]
75 | text.draw(shader, x, y, reg.index, reg.index+reg[0].length)
76 |
77 | shader.uniforms.tint = white
78 | text.draw(shader, x, y, reg.index+reg[0].length)
79 | }
80 |
81 | function start(gl, width, height) {
82 | //generate a basic shader with some custom frag source
83 | shader = createShader(gl)
84 | shader.bind()
85 | shader.uniforms.tint = [1, 1, 1, 1]
86 |
87 | background = createBackground(gl, {
88 | colors: [
89 | [0x50,0x50,0x50,0xff],
90 | [0x46,0x46,0x46,0xff]
91 | ]
92 | })
93 |
94 | //load textures, then build our text
95 | loadImage(texturePath, function(err, img) {
96 | var tex = createTexture(gl, img)
97 | tex.generateMipmap()
98 |
99 | //smoother filtering
100 | tex.minFilter = gl.LINEAR_MIPMAP_LINEAR
101 | tex.magFilter = gl.LINEAR
102 |
103 | text = createText(gl, {
104 | font: Font,
105 | wrapMode: 'pre',
106 | // wrapWidth: 1200,
107 | text: copy,
108 | textures: [ tex ]
109 | })
110 | })
111 | }
--------------------------------------------------------------------------------
/demo/sdf/DejaVu-sdf.fnt:
--------------------------------------------------------------------------------
1 | info face="DejaVu Sans Mono" size=32 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=4,4,4,4 spacing=-8,-8
2 | common lineHeight=38 base=30 scaleW=512 scaleH=512 pages=1 packed=0
3 | page id=0 file="DejaVu.png"
4 | chars count=95
5 | char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=30 xadvance=19 page=0 chnl=0
6 | char id=124 x=0 y=0 width=13 height=42 xoffset=4 yoffset=1 xadvance=19 page=0 chnl=0
7 | char id=106 x=13 y=0 width=19 height=41 xoffset=-1 yoffset=1 xadvance=19 page=0 chnl=0
8 | char id=36 x=32 y=0 width=25 height=40 xoffset=-1 yoffset=0 xadvance=19 page=0 chnl=0
9 | char id=125 x=57 y=0 width=23 height=40 xoffset=-1 yoffset=1 xadvance=19 page=0 chnl=0
10 | char id=123 x=80 y=0 width=23 height=40 xoffset=-1 yoffset=1 xadvance=19 page=0 chnl=0
11 | char id=93 x=103 y=0 width=17 height=39 xoffset=1 yoffset=1 xadvance=19 page=0 chnl=0
12 | char id=91 x=120 y=0 width=17 height=39 xoffset=3 yoffset=1 xadvance=19 page=0 chnl=0
13 | char id=41 x=137 y=0 width=17 height=39 xoffset=2 yoffset=1 xadvance=19 page=0 chnl=0
14 | char id=40 x=154 y=0 width=16 height=39 xoffset=3 yoffset=1 xadvance=19 page=0 chnl=0
15 | char id=127 x=170 y=0 width=26 height=38 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
16 | char id=64 x=196 y=0 width=28 height=37 xoffset=-3 yoffset=3 xadvance=19 page=0 chnl=0
17 | char id=81 x=224 y=0 width=26 height=37 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
18 | char id=92 x=250 y=0 width=24 height=36 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
19 | char id=47 x=274 y=0 width=24 height=36 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
20 | char id=121 x=298 y=0 width=25 height=35 xoffset=-2 yoffset=7 xadvance=19 page=0 chnl=0
21 | char id=113 x=323 y=0 width=25 height=35 xoffset=-2 yoffset=7 xadvance=19 page=0 chnl=0
22 | char id=112 x=348 y=0 width=25 height=35 xoffset=-1 yoffset=7 xadvance=19 page=0 chnl=0
23 | char id=103 x=373 y=0 width=25 height=35 xoffset=-2 yoffset=7 xadvance=19 page=0 chnl=0
24 | char id=108 x=398 y=0 width=25 height=34 xoffset=-3 yoffset=1 xadvance=19 page=0 chnl=0
25 | char id=107 x=423 y=0 width=24 height=34 xoffset=0 yoffset=1 xadvance=19 page=0 chnl=0
26 | char id=105 x=447 y=0 width=25 height=34 xoffset=-2 yoffset=1 xadvance=19 page=0 chnl=0
27 | char id=104 x=472 y=0 width=23 height=34 xoffset=-1 yoffset=1 xadvance=19 page=0 chnl=0
28 | char id=102 x=0 y=42 width=24 height=34 xoffset=-1 yoffset=1 xadvance=19 page=0 chnl=0
29 | char id=100 x=24 y=42 width=25 height=34 xoffset=-2 yoffset=1 xadvance=19 page=0 chnl=0
30 | char id=98 x=49 y=42 width=25 height=34 xoffset=-1 yoffset=1 xadvance=19 page=0 chnl=0
31 | char id=38 x=74 y=42 width=28 height=33 xoffset=-3 yoffset=2 xadvance=19 page=0 chnl=0
32 | char id=35 x=102 y=42 width=29 height=33 xoffset=-4 yoffset=2 xadvance=19 page=0 chnl=0
33 | char id=63 x=131 y=42 width=22 height=33 xoffset=0 yoffset=2 xadvance=19 page=0 chnl=0
34 | char id=33 x=153 y=42 width=13 height=33 xoffset=4 yoffset=2 xadvance=19 page=0 chnl=0
35 | char id=48 x=166 y=42 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
36 | char id=57 x=191 y=42 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
37 | char id=56 x=216 y=42 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
38 | char id=55 x=241 y=42 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
39 | char id=54 x=266 y=42 width=24 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
40 | char id=53 x=290 y=42 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
41 | char id=52 x=315 y=42 width=26 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
42 | char id=51 x=341 y=42 width=24 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
43 | char id=50 x=365 y=42 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
44 | char id=49 x=390 y=42 width=23 height=33 xoffset=0 yoffset=2 xadvance=19 page=0 chnl=0
45 | char id=116 x=413 y=42 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
46 | char id=90 x=438 y=42 width=26 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
47 | char id=89 x=464 y=42 width=26 height=33 xoffset=-3 yoffset=2 xadvance=19 page=0 chnl=0
48 | char id=88 x=0 y=76 width=28 height=33 xoffset=-3 yoffset=2 xadvance=19 page=0 chnl=0
49 | char id=87 x=28 y=76 width=28 height=33 xoffset=-4 yoffset=2 xadvance=19 page=0 chnl=0
50 | char id=86 x=56 y=76 width=26 height=33 xoffset=-3 yoffset=2 xadvance=19 page=0 chnl=0
51 | char id=85 x=82 y=76 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
52 | char id=84 x=107 y=76 width=27 height=33 xoffset=-3 yoffset=2 xadvance=19 page=0 chnl=0
53 | char id=83 x=134 y=76 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
54 | char id=82 x=159 y=76 width=26 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
55 | char id=80 x=185 y=76 width=24 height=33 xoffset=-1 yoffset=2 xadvance=19 page=0 chnl=0
56 | char id=79 x=209 y=76 width=26 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
57 | char id=78 x=235 y=76 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
58 | char id=77 x=260 y=76 width=27 height=33 xoffset=-3 yoffset=2 xadvance=19 page=0 chnl=0
59 | char id=76 x=287 y=76 width=24 height=33 xoffset=-1 yoffset=2 xadvance=19 page=0 chnl=0
60 | char id=75 x=311 y=76 width=26 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
61 | char id=74 x=337 y=76 width=23 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
62 | char id=73 x=360 y=76 width=23 height=33 xoffset=-1 yoffset=2 xadvance=19 page=0 chnl=0
63 | char id=72 x=383 y=76 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
64 | char id=71 x=408 y=76 width=26 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
65 | char id=70 x=434 y=76 width=24 height=33 xoffset=-1 yoffset=2 xadvance=19 page=0 chnl=0
66 | char id=69 x=458 y=76 width=24 height=33 xoffset=-1 yoffset=2 xadvance=19 page=0 chnl=0
67 | char id=68 x=482 y=76 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
68 | char id=67 x=0 y=109 width=25 height=33 xoffset=-2 yoffset=2 xadvance=19 page=0 chnl=0
69 | char id=66 x=25 y=109 width=25 height=33 xoffset=-1 yoffset=2 xadvance=19 page=0 chnl=0
70 | char id=65 x=50 y=109 width=27 height=33 xoffset=-3 yoffset=2 xadvance=19 page=0 chnl=0
71 | char id=37 x=77 y=109 width=27 height=32 xoffset=-3 yoffset=3 xadvance=19 page=0 chnl=0
72 | char id=59 x=104 y=109 width=16 height=31 xoffset=2 yoffset=8 xadvance=19 page=0 chnl=0
73 | char id=122 x=120 y=109 width=23 height=28 xoffset=-1 yoffset=7 xadvance=19 page=0 chnl=0
74 | char id=120 x=143 y=109 width=26 height=28 xoffset=-3 yoffset=7 xadvance=19 page=0 chnl=0
75 | char id=119 x=169 y=109 width=28 height=28 xoffset=-4 yoffset=7 xadvance=19 page=0 chnl=0
76 | char id=118 x=197 y=109 width=25 height=28 xoffset=-2 yoffset=7 xadvance=19 page=0 chnl=0
77 | char id=117 x=222 y=109 width=23 height=28 xoffset=-1 yoffset=7 xadvance=19 page=0 chnl=0
78 | char id=115 x=245 y=109 width=23 height=28 xoffset=-1 yoffset=7 xadvance=19 page=0 chnl=0
79 | char id=114 x=268 y=109 width=22 height=28 xoffset=2 yoffset=7 xadvance=19 page=0 chnl=0
80 | char id=111 x=290 y=109 width=25 height=28 xoffset=-2 yoffset=7 xadvance=19 page=0 chnl=0
81 | char id=110 x=315 y=109 width=23 height=28 xoffset=-1 yoffset=7 xadvance=19 page=0 chnl=0
82 | char id=109 x=338 y=109 width=27 height=28 xoffset=-2 yoffset=7 xadvance=19 page=0 chnl=0
83 | char id=99 x=365 y=109 width=24 height=28 xoffset=-1 yoffset=7 xadvance=19 page=0 chnl=0
84 | char id=97 x=389 y=109 width=25 height=28 xoffset=-2 yoffset=7 xadvance=19 page=0 chnl=0
85 | char id=43 x=414 y=109 width=27 height=27 xoffset=-3 yoffset=6 xadvance=19 page=0 chnl=0
86 | char id=58 x=441 y=109 width=14 height=27 xoffset=4 yoffset=8 xadvance=19 page=0 chnl=0
87 | char id=101 x=455 y=109 width=25 height=27 xoffset=-2 yoffset=8 xadvance=19 page=0 chnl=0
88 | char id=62 x=480 y=109 width=27 height=25 xoffset=-3 yoffset=8 xadvance=19 page=0 chnl=0
89 | char id=60 x=0 y=142 width=27 height=25 xoffset=-3 yoffset=8 xadvance=19 page=0 chnl=0
90 | char id=42 x=27 y=142 width=23 height=24 xoffset=-1 yoffset=2 xadvance=19 page=0 chnl=0
91 | char id=61 x=50 y=142 width=27 height=20 xoffset=-3 yoffset=10 xadvance=19 page=0 chnl=0
92 | char id=94 x=77 y=142 width=26 height=19 xoffset=-3 yoffset=2 xadvance=19 page=0 chnl=0
93 | char id=44 x=103 y=142 width=16 height=19 xoffset=2 yoffset=20 xadvance=19 page=0 chnl=0
94 | char id=39 x=119 y=142 width=13 height=19 xoffset=4 yoffset=2 xadvance=19 page=0 chnl=0
95 | char id=34 x=132 y=142 width=19 height=19 xoffset=1 yoffset=2 xadvance=19 page=0 chnl=0
96 | char id=96 x=151 y=142 width=16 height=16 xoffset=0 yoffset=-1 xadvance=19 page=0 chnl=0
97 | char id=126 x=167 y=142 width=27 height=15 xoffset=-3 yoffset=12 xadvance=19 page=0 chnl=0
98 | char id=46 x=194 y=142 width=14 height=15 xoffset=4 yoffset=20 xadvance=19 page=0 chnl=0
99 | char id=95 x=208 y=142 width=29 height=13 xoffset=-4 yoffset=30 xadvance=19 page=0 chnl=0
100 | char id=45 x=237 y=142 width=18 height=13 xoffset=2 yoffset=15 xadvance=19 page=0 chnl=0
101 | kernings count=-1
102 |
--------------------------------------------------------------------------------
/demo/sdf/DejaVu-sdf.json:
--------------------------------------------------------------------------------
1 | {"pages":["DejaVu.png"],"chars":[{"id":32,"x":0,"y":0,"width":0,"height":0,"xoffset":0,"yoffset":30,"xadvance":19,"page":0,"chnl":0},{"id":124,"x":0,"y":0,"width":13,"height":42,"xoffset":4,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":106,"x":13,"y":0,"width":19,"height":41,"xoffset":-1,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":36,"x":32,"y":0,"width":25,"height":40,"xoffset":-1,"yoffset":0,"xadvance":19,"page":0,"chnl":0},{"id":125,"x":57,"y":0,"width":23,"height":40,"xoffset":-1,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":123,"x":80,"y":0,"width":23,"height":40,"xoffset":-1,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":93,"x":103,"y":0,"width":17,"height":39,"xoffset":1,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":91,"x":120,"y":0,"width":17,"height":39,"xoffset":3,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":41,"x":137,"y":0,"width":17,"height":39,"xoffset":2,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":40,"x":154,"y":0,"width":16,"height":39,"xoffset":3,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":127,"x":170,"y":0,"width":26,"height":38,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":64,"x":196,"y":0,"width":28,"height":37,"xoffset":-3,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":81,"x":224,"y":0,"width":26,"height":37,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":92,"x":250,"y":0,"width":24,"height":36,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":47,"x":274,"y":0,"width":24,"height":36,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":121,"x":298,"y":0,"width":25,"height":35,"xoffset":-2,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":113,"x":323,"y":0,"width":25,"height":35,"xoffset":-2,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":112,"x":348,"y":0,"width":25,"height":35,"xoffset":-1,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":103,"x":373,"y":0,"width":25,"height":35,"xoffset":-2,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":108,"x":398,"y":0,"width":25,"height":34,"xoffset":-3,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":107,"x":423,"y":0,"width":24,"height":34,"xoffset":0,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":105,"x":447,"y":0,"width":25,"height":34,"xoffset":-2,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":104,"x":472,"y":0,"width":23,"height":34,"xoffset":-1,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":102,"x":0,"y":42,"width":24,"height":34,"xoffset":-1,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":100,"x":24,"y":42,"width":25,"height":34,"xoffset":-2,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":98,"x":49,"y":42,"width":25,"height":34,"xoffset":-1,"yoffset":1,"xadvance":19,"page":0,"chnl":0},{"id":38,"x":74,"y":42,"width":28,"height":33,"xoffset":-3,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":35,"x":102,"y":42,"width":29,"height":33,"xoffset":-4,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":63,"x":131,"y":42,"width":22,"height":33,"xoffset":0,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":33,"x":153,"y":42,"width":13,"height":33,"xoffset":4,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":48,"x":166,"y":42,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":57,"x":191,"y":42,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":56,"x":216,"y":42,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":55,"x":241,"y":42,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":54,"x":266,"y":42,"width":24,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":53,"x":290,"y":42,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":52,"x":315,"y":42,"width":26,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":51,"x":341,"y":42,"width":24,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":50,"x":365,"y":42,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":49,"x":390,"y":42,"width":23,"height":33,"xoffset":0,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":116,"x":413,"y":42,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":90,"x":438,"y":42,"width":26,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":89,"x":464,"y":42,"width":26,"height":33,"xoffset":-3,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":88,"x":0,"y":76,"width":28,"height":33,"xoffset":-3,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":87,"x":28,"y":76,"width":28,"height":33,"xoffset":-4,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":86,"x":56,"y":76,"width":26,"height":33,"xoffset":-3,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":85,"x":82,"y":76,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":84,"x":107,"y":76,"width":27,"height":33,"xoffset":-3,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":83,"x":134,"y":76,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":82,"x":159,"y":76,"width":26,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":80,"x":185,"y":76,"width":24,"height":33,"xoffset":-1,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":79,"x":209,"y":76,"width":26,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":78,"x":235,"y":76,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":77,"x":260,"y":76,"width":27,"height":33,"xoffset":-3,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":76,"x":287,"y":76,"width":24,"height":33,"xoffset":-1,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":75,"x":311,"y":76,"width":26,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":74,"x":337,"y":76,"width":23,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":73,"x":360,"y":76,"width":23,"height":33,"xoffset":-1,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":72,"x":383,"y":76,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":71,"x":408,"y":76,"width":26,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":70,"x":434,"y":76,"width":24,"height":33,"xoffset":-1,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":69,"x":458,"y":76,"width":24,"height":33,"xoffset":-1,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":68,"x":482,"y":76,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":67,"x":0,"y":109,"width":25,"height":33,"xoffset":-2,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":66,"x":25,"y":109,"width":25,"height":33,"xoffset":-1,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":65,"x":50,"y":109,"width":27,"height":33,"xoffset":-3,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":37,"x":77,"y":109,"width":27,"height":32,"xoffset":-3,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":59,"x":104,"y":109,"width":16,"height":31,"xoffset":2,"yoffset":8,"xadvance":19,"page":0,"chnl":0},{"id":122,"x":120,"y":109,"width":23,"height":28,"xoffset":-1,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":120,"x":143,"y":109,"width":26,"height":28,"xoffset":-3,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":119,"x":169,"y":109,"width":28,"height":28,"xoffset":-4,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":118,"x":197,"y":109,"width":25,"height":28,"xoffset":-2,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":117,"x":222,"y":109,"width":23,"height":28,"xoffset":-1,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":115,"x":245,"y":109,"width":23,"height":28,"xoffset":-1,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":114,"x":268,"y":109,"width":22,"height":28,"xoffset":2,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":111,"x":290,"y":109,"width":25,"height":28,"xoffset":-2,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":110,"x":315,"y":109,"width":23,"height":28,"xoffset":-1,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":109,"x":338,"y":109,"width":27,"height":28,"xoffset":-2,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":99,"x":365,"y":109,"width":24,"height":28,"xoffset":-1,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":97,"x":389,"y":109,"width":25,"height":28,"xoffset":-2,"yoffset":7,"xadvance":19,"page":0,"chnl":0},{"id":43,"x":414,"y":109,"width":27,"height":27,"xoffset":-3,"yoffset":6,"xadvance":19,"page":0,"chnl":0},{"id":58,"x":441,"y":109,"width":14,"height":27,"xoffset":4,"yoffset":8,"xadvance":19,"page":0,"chnl":0},{"id":101,"x":455,"y":109,"width":25,"height":27,"xoffset":-2,"yoffset":8,"xadvance":19,"page":0,"chnl":0},{"id":62,"x":480,"y":109,"width":27,"height":25,"xoffset":-3,"yoffset":8,"xadvance":19,"page":0,"chnl":0},{"id":60,"x":0,"y":142,"width":27,"height":25,"xoffset":-3,"yoffset":8,"xadvance":19,"page":0,"chnl":0},{"id":42,"x":27,"y":142,"width":23,"height":24,"xoffset":-1,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":61,"x":50,"y":142,"width":27,"height":20,"xoffset":-3,"yoffset":10,"xadvance":19,"page":0,"chnl":0},{"id":94,"x":77,"y":142,"width":26,"height":19,"xoffset":-3,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":44,"x":103,"y":142,"width":16,"height":19,"xoffset":2,"yoffset":20,"xadvance":19,"page":0,"chnl":0},{"id":39,"x":119,"y":142,"width":13,"height":19,"xoffset":4,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":34,"x":132,"y":142,"width":19,"height":19,"xoffset":1,"yoffset":2,"xadvance":19,"page":0,"chnl":0},{"id":96,"x":151,"y":142,"width":16,"height":16,"xoffset":0,"yoffset":-1,"xadvance":19,"page":0,"chnl":0},{"id":126,"x":167,"y":142,"width":27,"height":15,"xoffset":-3,"yoffset":12,"xadvance":19,"page":0,"chnl":0},{"id":46,"x":194,"y":142,"width":14,"height":15,"xoffset":4,"yoffset":20,"xadvance":19,"page":0,"chnl":0},{"id":95,"x":208,"y":142,"width":29,"height":13,"xoffset":-4,"yoffset":30,"xadvance":19,"page":0,"chnl":0},{"id":45,"x":237,"y":142,"width":18,"height":13,"xoffset":2,"yoffset":15,"xadvance":19,"page":0,"chnl":0}],"kernings":[],"info":{"face":"DejaVu Sans Mono","size":32,"bold":0,"italic":0,"charset":"","unicode":0,"stretchH":100,"smooth":1,"aa":1,"padding":[4,4,4,4],"spacing":[-8,-8]},"common":{"lineHeight":38,"base":30,"scaleW":512,"scaleH":512,"pages":1,"packed":0}}
--------------------------------------------------------------------------------
/demo/sdf/DejaVu-sdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattdesl/gl-sprite-text/d9cac3c5413e591d54115e8b4f4a31ed5cd32bdf/demo/sdf/DejaVu-sdf.png
--------------------------------------------------------------------------------
/demo/sdf/LatoBlack-sdf.fnt:
--------------------------------------------------------------------------------
1 | info face="Lato Black" size=32 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=4,4,4,4 spacing=-8,-8
2 | common lineHeight=39 base=32 scaleW=512 scaleH=512 pages=1 packed=0
3 | page id=0 file="LatoBlack-sdf.png"
4 | chars count=95
5 | char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=32 xadvance=6 page=0 chnl=0
6 | char id=41 x=0 y=0 width=17 height=41 xoffset=-3 yoffset=2 xadvance=10 page=0 chnl=0
7 | char id=40 x=17 y=0 width=17 height=41 xoffset=-3 yoffset=2 xadvance=10 page=0 chnl=0
8 | char id=36 x=34 y=0 width=27 height=40 xoffset=-4 yoffset=0 xadvance=19 page=0 chnl=0
9 | char id=124 x=61 y=0 width=14 height=40 xoffset=-2 yoffset=2 xadvance=10 page=0 chnl=0
10 | char id=125 x=75 y=0 width=19 height=40 xoffset=-4 yoffset=2 xadvance=10 page=0 chnl=0
11 | char id=123 x=94 y=0 width=18 height=40 xoffset=-4 yoffset=2 xadvance=10 page=0 chnl=0
12 | char id=93 x=112 y=0 width=18 height=40 xoffset=-4 yoffset=2 xadvance=10 page=0 chnl=0
13 | char id=91 x=130 y=0 width=17 height=40 xoffset=-3 yoffset=2 xadvance=10 page=0 chnl=0
14 | char id=106 x=147 y=0 width=18 height=38 xoffset=-5 yoffset=4 xadvance=9 page=0 chnl=0
15 | char id=81 x=165 y=0 width=36 height=38 xoffset=-4 yoffset=3 xadvance=26 page=0 chnl=0
16 | char id=92 x=201 y=0 width=24 height=36 xoffset=-5 yoffset=3 xadvance=13 page=0 chnl=0
17 | char id=64 x=225 y=0 width=35 height=36 xoffset=-4 yoffset=5 xadvance=26 page=0 chnl=0
18 | char id=47 x=260 y=0 width=24 height=36 xoffset=-5 yoffset=3 xadvance=13 page=0 chnl=0
19 | char id=127 x=284 y=0 width=27 height=34 xoffset=-4 yoffset=3 xadvance=18 page=0 chnl=0
20 | char id=38 x=311 y=0 width=33 height=34 xoffset=-4 yoffset=3 xadvance=23 page=0 chnl=0
21 | char id=35 x=344 y=0 width=28 height=34 xoffset=-4 yoffset=3 xadvance=19 page=0 chnl=0
22 | char id=37 x=372 y=0 width=35 height=34 xoffset=-4 yoffset=3 xadvance=26 page=0 chnl=0
23 | char id=63 x=407 y=0 width=23 height=34 xoffset=-4 yoffset=3 xadvance=14 page=0 chnl=0
24 | char id=33 x=430 y=0 width=15 height=34 xoffset=-1 yoffset=3 xadvance=12 page=0 chnl=0
25 | char id=48 x=445 y=0 width=27 height=34 xoffset=-4 yoffset=3 xadvance=19 page=0 chnl=0
26 | char id=56 x=472 y=0 width=27 height=34 xoffset=-4 yoffset=3 xadvance=19 page=0 chnl=0
27 | char id=55 x=0 y=41 width=26 height=34 xoffset=-3 yoffset=3 xadvance=19 page=0 chnl=0
28 | char id=54 x=26 y=41 width=26 height=34 xoffset=-3 yoffset=3 xadvance=19 page=0 chnl=0
29 | char id=53 x=52 y=41 width=26 height=34 xoffset=-4 yoffset=3 xadvance=19 page=0 chnl=0
30 | char id=52 x=78 y=41 width=28 height=34 xoffset=-4 yoffset=3 xadvance=19 page=0 chnl=0
31 | char id=51 x=106 y=41 width=26 height=34 xoffset=-3 yoffset=3 xadvance=19 page=0 chnl=0
32 | char id=50 x=132 y=41 width=26 height=34 xoffset=-3 yoffset=3 xadvance=19 page=0 chnl=0
33 | char id=49 x=158 y=41 width=25 height=34 xoffset=-2 yoffset=3 xadvance=19 page=0 chnl=0
34 | char id=108 x=183 y=41 width=15 height=34 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0
35 | char id=107 x=198 y=41 width=27 height=34 xoffset=-3 yoffset=3 xadvance=18 page=0 chnl=0
36 | char id=104 x=225 y=41 width=25 height=34 xoffset=-3 yoffset=3 xadvance=19 page=0 chnl=0
37 | char id=100 x=250 y=41 width=26 height=34 xoffset=-4 yoffset=3 xadvance=19 page=0 chnl=0
38 | char id=98 x=276 y=41 width=26 height=34 xoffset=-3 yoffset=3 xadvance=19 page=0 chnl=0
39 | char id=90 x=302 y=41 width=28 height=34 xoffset=-4 yoffset=3 xadvance=20 page=0 chnl=0
40 | char id=89 x=330 y=41 width=32 height=34 xoffset=-5 yoffset=3 xadvance=22 page=0 chnl=0
41 | char id=88 x=362 y=41 width=32 height=34 xoffset=-4 yoffset=3 xadvance=23 page=0 chnl=0
42 | char id=87 x=394 y=41 width=44 height=34 xoffset=-4 yoffset=3 xadvance=34 page=0 chnl=0
43 | char id=86 x=438 y=41 width=33 height=34 xoffset=-4 yoffset=3 xadvance=24 page=0 chnl=0
44 | char id=85 x=471 y=41 width=30 height=34 xoffset=-3 yoffset=3 xadvance=23 page=0 chnl=0
45 | char id=84 x=0 y=75 width=28 height=34 xoffset=-4 yoffset=3 xadvance=19 page=0 chnl=0
46 | char id=83 x=28 y=75 width=26 height=34 xoffset=-4 yoffset=3 xadvance=17 page=0 chnl=0
47 | char id=82 x=54 y=75 width=29 height=34 xoffset=-3 yoffset=3 xadvance=21 page=0 chnl=0
48 | char id=80 x=83 y=75 width=28 height=34 xoffset=-3 yoffset=3 xadvance=20 page=0 chnl=0
49 | char id=79 x=111 y=75 width=34 height=34 xoffset=-4 yoffset=3 xadvance=26 page=0 chnl=0
50 | char id=78 x=145 y=75 width=31 height=34 xoffset=-3 yoffset=3 xadvance=24 page=0 chnl=0
51 | char id=77 x=176 y=75 width=37 height=34 xoffset=-3 yoffset=3 xadvance=30 page=0 chnl=0
52 | char id=76 x=213 y=75 width=24 height=34 xoffset=-3 yoffset=3 xadvance=17 page=0 chnl=0
53 | char id=75 x=237 y=75 width=31 height=34 xoffset=-3 yoffset=3 xadvance=23 page=0 chnl=0
54 | char id=74 x=268 y=75 width=21 height=34 xoffset=-4 yoffset=3 xadvance=14 page=0 chnl=0
55 | char id=73 x=289 y=75 width=15 height=34 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0
56 | char id=72 x=304 y=75 width=31 height=34 xoffset=-3 yoffset=3 xadvance=24 page=0 chnl=0
57 | char id=71 x=335 y=75 width=31 height=34 xoffset=-4 yoffset=3 xadvance=23 page=0 chnl=0
58 | char id=70 x=366 y=75 width=25 height=34 xoffset=-3 yoffset=3 xadvance=18 page=0 chnl=0
59 | char id=69 x=391 y=75 width=25 height=34 xoffset=-3 yoffset=3 xadvance=18 page=0 chnl=0
60 | char id=68 x=416 y=75 width=32 height=34 xoffset=-3 yoffset=3 xadvance=24 page=0 chnl=0
61 | char id=67 x=448 y=75 width=30 height=34 xoffset=-4 yoffset=3 xadvance=21 page=0 chnl=0
62 | char id=66 x=478 y=75 width=28 height=34 xoffset=-3 yoffset=3 xadvance=21 page=0 chnl=0
63 | char id=65 x=0 y=109 width=33 height=34 xoffset=-4 yoffset=3 xadvance=24 page=0 chnl=0
64 | char id=57 x=33 y=109 width=27 height=33 xoffset=-3 yoffset=4 xadvance=19 page=0 chnl=0
65 | char id=105 x=60 y=109 width=16 height=33 xoffset=-3 yoffset=4 xadvance=9 page=0 chnl=0
66 | char id=102 x=76 y=109 width=21 height=33 xoffset=-4 yoffset=4 xadvance=12 page=0 chnl=0
67 | char id=121 x=97 y=109 width=27 height=32 xoffset=-4 yoffset=10 xadvance=18 page=0 chnl=0
68 | char id=116 x=124 y=109 width=22 height=32 xoffset=-4 yoffset=5 xadvance=13 page=0 chnl=0
69 | char id=113 x=146 y=109 width=26 height=32 xoffset=-4 yoffset=10 xadvance=19 page=0 chnl=0
70 | char id=112 x=172 y=109 width=26 height=32 xoffset=-3 yoffset=10 xadvance=19 page=0 chnl=0
71 | char id=103 x=198 y=109 width=26 height=32 xoffset=-4 yoffset=10 xadvance=17 page=0 chnl=0
72 | char id=59 x=224 y=109 width=16 height=31 xoffset=-3 yoffset=11 xadvance=9 page=0 chnl=0
73 | char id=122 x=240 y=109 width=23 height=27 xoffset=-3 yoffset=10 xadvance=15 page=0 chnl=0
74 | char id=120 x=263 y=109 width=27 height=27 xoffset=-4 yoffset=10 xadvance=18 page=0 chnl=0
75 | char id=119 x=290 y=109 width=35 height=27 xoffset=-4 yoffset=10 xadvance=26 page=0 chnl=0
76 | char id=118 x=325 y=109 width=27 height=27 xoffset=-4 yoffset=10 xadvance=18 page=0 chnl=0
77 | char id=117 x=352 y=109 width=25 height=27 xoffset=-3 yoffset=10 xadvance=19 page=0 chnl=0
78 | char id=115 x=377 y=109 width=23 height=27 xoffset=-4 yoffset=10 xadvance=14 page=0 chnl=0
79 | char id=114 x=400 y=109 width=21 height=27 xoffset=-3 yoffset=10 xadvance=13 page=0 chnl=0
80 | char id=110 x=421 y=109 width=25 height=27 xoffset=-3 yoffset=10 xadvance=19 page=0 chnl=0
81 | char id=109 x=446 y=109 width=34 height=27 xoffset=-3 yoffset=10 xadvance=28 page=0 chnl=0
82 | char id=101 x=480 y=109 width=26 height=27 xoffset=-4 yoffset=10 xadvance=17 page=0 chnl=0
83 | char id=99 x=0 y=143 width=25 height=27 xoffset=-4 yoffset=10 xadvance=16 page=0 chnl=0
84 | char id=97 x=25 y=143 width=24 height=27 xoffset=-3 yoffset=10 xadvance=17 page=0 chnl=0
85 | char id=43 x=49 y=143 width=26 height=26 xoffset=-3 yoffset=8 xadvance=19 page=0 chnl=0
86 | char id=58 x=75 y=143 width=16 height=26 xoffset=-3 yoffset=11 xadvance=9 page=0 chnl=0
87 | char id=111 x=91 y=143 width=27 height=26 xoffset=-4 yoffset=11 xadvance=19 page=0 chnl=0
88 | char id=62 x=118 y=143 width=23 height=25 xoffset=-1 yoffset=9 xadvance=19 page=0 chnl=0
89 | char id=60 x=141 y=143 width=23 height=25 xoffset=-2 yoffset=9 xadvance=19 page=0 chnl=0
90 | char id=42 x=164 y=143 width=21 height=21 xoffset=-4 yoffset=3 xadvance=13 page=0 chnl=0
91 | char id=94 x=185 y=143 width=25 height=21 xoffset=-3 yoffset=3 xadvance=19 page=0 chnl=0
92 | char id=44 x=210 y=143 width=15 height=20 xoffset=-3 yoffset=22 xadvance=8 page=0 chnl=0
93 | char id=61 x=225 y=143 width=25 height=19 xoffset=-3 yoffset=12 xadvance=19 page=0 chnl=0
94 | char id=39 x=250 y=143 width=15 height=19 xoffset=-3 yoffset=3 xadvance=8 page=0 chnl=0
95 | char id=34 x=265 y=143 width=21 height=19 xoffset=-3 yoffset=3 xadvance=14 page=0 chnl=0
96 | char id=126 x=286 y=143 width=26 height=17 xoffset=-3 yoffset=14 xadvance=19 page=0 chnl=0
97 | char id=46 x=312 y=143 width=16 height=16 xoffset=-4 yoffset=21 xadvance=8 page=0 chnl=0
98 | char id=96 x=328 y=143 width=18 height=15 xoffset=-5 yoffset=3 xadvance=11 page=0 chnl=0
99 | char id=95 x=346 y=143 width=22 height=13 xoffset=-4 yoffset=29 xadvance=13 page=0 chnl=0
100 | char id=45 x=368 y=143 width=19 height=13 xoffset=-3 yoffset=16 xadvance=12 page=0 chnl=0
101 | kernings count=4455
102 | kerning first=40 second=64 amount=-1
103 | kerning first=40 second=67 amount=-1
104 | kerning first=40 second=71 amount=-1
105 | kerning first=40 second=79 amount=-1
106 | kerning first=40 second=81 amount=-1
107 | kerning first=40 second=99 amount=-1
108 | kerning first=40 second=100 amount=-1
109 | kerning first=40 second=101 amount=-1
110 | kerning first=40 second=111 amount=-1
111 | kerning first=40 second=113 amount=-1
112 | kerning first=123 second=64 amount=-1
113 | kerning first=123 second=67 amount=-1
114 | kerning first=123 second=71 amount=-1
115 | kerning first=123 second=79 amount=-1
116 | kerning first=123 second=81 amount=-1
117 | kerning first=123 second=99 amount=-1
118 | kerning first=123 second=100 amount=-1
119 | kerning first=123 second=101 amount=-1
120 | kerning first=123 second=111 amount=-1
121 | kerning first=123 second=113 amount=-1
122 | kerning first=91 second=64 amount=-1
123 | kerning first=91 second=67 amount=-1
124 | kerning first=91 second=71 amount=-1
125 | kerning first=91 second=79 amount=-1
126 | kerning first=91 second=81 amount=-1
127 | kerning first=91 second=99 amount=-1
128 | kerning first=91 second=100 amount=-1
129 | kerning first=91 second=101 amount=-1
130 | kerning first=91 second=111 amount=-1
131 | kerning first=91 second=113 amount=-1
132 | kerning first=81 second=34 amount=-1
133 | kerning first=81 second=38 amount=-1
134 | kerning first=81 second=39 amount=-1
135 | kerning first=81 second=41 amount=-1
136 | kerning first=81 second=42 amount=-1
137 | kerning first=81 second=44 amount=-1
138 | kerning first=81 second=46 amount=-1
139 | kerning first=81 second=47 amount=-1
140 | kerning first=81 second=65 amount=-1
141 | kerning first=81 second=84 amount=-1
142 | kerning first=81 second=86 amount=-1
143 | kerning first=81 second=89 amount=-1
144 | kerning first=81 second=90 amount=-1
145 | kerning first=81 second=92 amount=-1
146 | kerning first=81 second=93 amount=-1
147 | kerning first=81 second=125 amount=-1
148 | kerning first=92 second=34 amount=-3
149 | kerning first=92 second=39 amount=-3
150 | kerning first=92 second=42 amount=-3
151 | kerning first=92 second=45 amount=-1
152 | kerning first=92 second=63 amount=-1
153 | kerning first=92 second=64 amount=-1
154 | kerning first=92 second=67 amount=-1
155 | kerning first=92 second=71 amount=-1
156 | kerning first=92 second=74 amount=1
157 | kerning first=92 second=79 amount=-1
158 | kerning first=92 second=81 amount=-1
159 | kerning first=92 second=84 amount=-3
160 | kerning first=92 second=85 amount=-1
161 | kerning first=92 second=86 amount=-3
162 | kerning first=92 second=87 amount=-2
163 | kerning first=92 second=89 amount=-3
164 | kerning first=92 second=92 amount=-3
165 | kerning first=92 second=118 amount=-2
166 | kerning first=92 second=121 amount=-2
167 | kerning first=64 second=34 amount=-1
168 | kerning first=64 second=38 amount=-1
169 | kerning first=64 second=39 amount=-1
170 | kerning first=64 second=41 amount=-1
171 | kerning first=64 second=42 amount=-1
172 | kerning first=64 second=44 amount=-1
173 | kerning first=64 second=46 amount=-1
174 | kerning first=64 second=47 amount=-1
175 | kerning first=64 second=65 amount=-1
176 | kerning first=64 second=84 amount=-1
177 | kerning first=64 second=86 amount=-1
178 | kerning first=64 second=89 amount=-1
179 | kerning first=64 second=90 amount=-1
180 | kerning first=64 second=92 amount=-1
181 | kerning first=64 second=93 amount=-1
182 | kerning first=64 second=125 amount=-1
183 | kerning first=47 second=34 amount=1
184 | kerning first=47 second=38 amount=-3
185 | kerning first=47 second=39 amount=1
186 | kerning first=47 second=42 amount=1
187 | kerning first=47 second=44 amount=-3
188 | kerning first=47 second=45 amount=-2
189 | kerning first=47 second=46 amount=-3
190 | kerning first=47 second=47 amount=-3
191 | kerning first=47 second=58 amount=-2
192 | kerning first=47 second=59 amount=-2
193 | kerning first=47 second=64 amount=-1
194 | kerning first=47 second=65 amount=-3
195 | kerning first=47 second=67 amount=-1
196 | kerning first=47 second=71 amount=-1
197 | kerning first=47 second=74 amount=-3
198 | kerning first=47 second=79 amount=-1
199 | kerning first=47 second=81 amount=-1
200 | kerning first=47 second=97 amount=-2
201 | kerning first=47 second=99 amount=-2
202 | kerning first=47 second=100 amount=-2
203 | kerning first=47 second=101 amount=-2
204 | kerning first=47 second=103 amount=-2
205 | kerning first=47 second=109 amount=-2
206 | kerning first=47 second=110 amount=-2
207 | kerning first=47 second=111 amount=-2
208 | kerning first=47 second=112 amount=-2
209 | kerning first=47 second=113 amount=-2
210 | kerning first=47 second=114 amount=-2
211 | kerning first=47 second=115 amount=-2
212 | kerning first=47 second=116 amount=-1
213 | kerning first=47 second=117 amount=-2
214 | kerning first=47 second=118 amount=-1
215 | kerning first=47 second=120 amount=-1
216 | kerning first=47 second=121 amount=-1
217 | kerning first=47 second=122 amount=-2
218 | kerning first=107 second=99 amount=-1
219 | kerning first=107 second=100 amount=-1
220 | kerning first=107 second=101 amount=-1
221 | kerning first=107 second=111 amount=-1
222 | kerning first=107 second=113 amount=-1
223 | kerning first=104 second=34 amount=-1
224 | kerning first=104 second=39 amount=-1
225 | kerning first=104 second=42 amount=-1
226 | kerning first=104 second=118 amount=-1
227 | kerning first=104 second=121 amount=-1
228 | kerning first=98 second=34 amount=-2
229 | kerning first=98 second=39 amount=-2
230 | kerning first=98 second=41 amount=-1
231 | kerning first=98 second=42 amount=-2
232 | kerning first=98 second=86 amount=-2
233 | kerning first=98 second=87 amount=-1
234 | kerning first=98 second=92 amount=-2
235 | kerning first=98 second=93 amount=-1
236 | kerning first=98 second=118 amount=-1
237 | kerning first=98 second=120 amount=-1
238 | kerning first=98 second=121 amount=-1
239 | kerning first=98 second=125 amount=-1
240 | kerning first=90 second=45 amount=-1
241 | kerning first=90 second=64 amount=-1
242 | kerning first=90 second=67 amount=-1
243 | kerning first=90 second=71 amount=-1
244 | kerning first=90 second=79 amount=-1
245 | kerning first=90 second=81 amount=-1
246 | kerning first=89 second=34 amount=1
247 | kerning first=89 second=38 amount=-3
248 | kerning first=89 second=39 amount=1
249 | kerning first=89 second=42 amount=1
250 | kerning first=89 second=44 amount=-3
251 | kerning first=89 second=45 amount=-3
252 | kerning first=89 second=46 amount=-3
253 | kerning first=89 second=47 amount=-3
254 | kerning first=89 second=58 amount=-2
255 | kerning first=89 second=59 amount=-2
256 | kerning first=89 second=64 amount=-1
257 | kerning first=89 second=65 amount=-3
258 | kerning first=89 second=67 amount=-1
259 | kerning first=89 second=71 amount=-1
260 | kerning first=89 second=74 amount=-3
261 | kerning first=89 second=79 amount=-1
262 | kerning first=89 second=81 amount=-1
263 | kerning first=89 second=97 amount=-3
264 | kerning first=89 second=99 amount=-3
265 | kerning first=89 second=100 amount=-3
266 | kerning first=89 second=101 amount=-3
267 | kerning first=89 second=103 amount=-3
268 | kerning first=89 second=109 amount=-2
269 | kerning first=89 second=110 amount=-2
270 | kerning first=89 second=111 amount=-3
271 | kerning first=89 second=112 amount=-2
272 | kerning first=89 second=113 amount=-3
273 | kerning first=89 second=114 amount=-2
274 | kerning first=89 second=115 amount=-2
275 | kerning first=89 second=117 amount=-2
276 | kerning first=89 second=118 amount=-2
277 | kerning first=89 second=119 amount=-2
278 | kerning first=89 second=120 amount=-2
279 | kerning first=89 second=121 amount=-2
280 | kerning first=88 second=45 amount=-1
281 | kerning first=88 second=99 amount=-1
282 | kerning first=88 second=100 amount=-1
283 | kerning first=88 second=101 amount=-1
284 | kerning first=88 second=102 amount=-1
285 | kerning first=88 second=111 amount=-1
286 | kerning first=88 second=113 amount=-1
287 | kerning first=88 second=116 amount=-2
288 | kerning first=88 second=118 amount=-1
289 | kerning first=88 second=119 amount=-1
290 | kerning first=88 second=121 amount=-1
291 | kerning first=87 second=34 amount=1
292 | kerning first=87 second=38 amount=-2
293 | kerning first=87 second=39 amount=1
294 | kerning first=87 second=42 amount=1
295 | kerning first=87 second=44 amount=-2
296 | kerning first=87 second=45 amount=-1
297 | kerning first=87 second=46 amount=-2
298 | kerning first=87 second=47 amount=-2
299 | kerning first=87 second=65 amount=-2
300 | kerning first=87 second=74 amount=-2
301 | kerning first=87 second=97 amount=-2
302 | kerning first=87 second=99 amount=-1
303 | kerning first=87 second=100 amount=-1
304 | kerning first=87 second=101 amount=-1
305 | kerning first=87 second=103 amount=-2
306 | kerning first=87 second=111 amount=-1
307 | kerning first=87 second=113 amount=-1
308 | kerning first=87 second=115 amount=-1
309 | kerning first=86 second=34 amount=1
310 | kerning first=86 second=38 amount=-3
311 | kerning first=86 second=39 amount=1
312 | kerning first=86 second=42 amount=1
313 | kerning first=86 second=44 amount=-3
314 | kerning first=86 second=45 amount=-2
315 | kerning first=86 second=46 amount=-3
316 | kerning first=86 second=47 amount=-3
317 | kerning first=86 second=58 amount=-2
318 | kerning first=86 second=59 amount=-2
319 | kerning first=86 second=64 amount=-1
320 | kerning first=86 second=65 amount=-3
321 | kerning first=86 second=67 amount=-1
322 | kerning first=86 second=71 amount=-1
323 | kerning first=86 second=74 amount=-3
324 | kerning first=86 second=79 amount=-1
325 | kerning first=86 second=81 amount=-1
326 | kerning first=86 second=97 amount=-2
327 | kerning first=86 second=99 amount=-2
328 | kerning first=86 second=100 amount=-2
329 | kerning first=86 second=101 amount=-2
330 | kerning first=86 second=103 amount=-2
331 | kerning first=86 second=109 amount=-2
332 | kerning first=86 second=110 amount=-2
333 | kerning first=86 second=111 amount=-2
334 | kerning first=86 second=112 amount=-2
335 | kerning first=86 second=113 amount=-2
336 | kerning first=86 second=114 amount=-2
337 | kerning first=86 second=115 amount=-2
338 | kerning first=86 second=116 amount=-1
339 | kerning first=86 second=117 amount=-2
340 | kerning first=86 second=118 amount=-1
341 | kerning first=86 second=120 amount=-1
342 | kerning first=86 second=121 amount=-1
343 | kerning first=86 second=122 amount=-2
344 | kerning first=85 second=38 amount=-1
345 | kerning first=85 second=44 amount=-1
346 | kerning first=85 second=46 amount=-1
347 | kerning first=85 second=47 amount=-1
348 | kerning first=85 second=65 amount=-1
349 | kerning first=84 second=38 amount=-3
350 | kerning first=84 second=44 amount=-3
351 | kerning first=84 second=45 amount=-3
352 | kerning first=84 second=46 amount=-3
353 | kerning first=84 second=47 amount=-3
354 | kerning first=84 second=58 amount=-3
355 | kerning first=84 second=59 amount=-3
356 | kerning first=84 second=64 amount=-1
357 | kerning first=84 second=65 amount=-3
358 | kerning first=84 second=67 amount=-1
359 | kerning first=84 second=71 amount=-1
360 | kerning first=84 second=74 amount=-3
361 | kerning first=84 second=79 amount=-1
362 | kerning first=84 second=81 amount=-1
363 | kerning first=84 second=97 amount=-4
364 | kerning first=84 second=99 amount=-3
365 | kerning first=84 second=100 amount=-3
366 | kerning first=84 second=101 amount=-3
367 | kerning first=84 second=103 amount=-3
368 | kerning first=84 second=109 amount=-3
369 | kerning first=84 second=110 amount=-3
370 | kerning first=84 second=111 amount=-3
371 | kerning first=84 second=112 amount=-3
372 | kerning first=84 second=113 amount=-3
373 | kerning first=84 second=114 amount=-3
374 | kerning first=84 second=115 amount=-2
375 | kerning first=84 second=117 amount=-3
376 | kerning first=84 second=118 amount=-3
377 | kerning first=84 second=119 amount=-2
378 | kerning first=84 second=120 amount=-2
379 | kerning first=84 second=121 amount=-3
380 | kerning first=84 second=122 amount=-2
381 | kerning first=82 second=64 amount=-1
382 | kerning first=82 second=67 amount=-1
383 | kerning first=82 second=71 amount=-1
384 | kerning first=82 second=79 amount=-1
385 | kerning first=82 second=81 amount=-1
386 | kerning first=82 second=84 amount=-1
387 | kerning first=82 second=85 amount=-1
388 | kerning first=80 second=38 amount=-3
389 | kerning first=80 second=44 amount=-4
390 | kerning first=80 second=46 amount=-4
391 | kerning first=80 second=47 amount=-3
392 | kerning first=80 second=65 amount=-3
393 | kerning first=80 second=74 amount=-3
394 | kerning first=80 second=97 amount=-1
395 | kerning first=79 second=34 amount=-1
396 | kerning first=79 second=38 amount=-1
397 | kerning first=79 second=39 amount=-1
398 | kerning first=79 second=41 amount=-1
399 | kerning first=79 second=42 amount=-1
400 | kerning first=79 second=44 amount=-1
401 | kerning first=79 second=46 amount=-1
402 | kerning first=79 second=47 amount=-1
403 | kerning first=79 second=65 amount=-1
404 | kerning first=79 second=84 amount=-1
405 | kerning first=79 second=86 amount=-1
406 | kerning first=79 second=89 amount=-1
407 | kerning first=79 second=90 amount=-1
408 | kerning first=79 second=92 amount=-1
409 | kerning first=79 second=93 amount=-1
410 | kerning first=79 second=125 amount=-1
411 | kerning first=76 second=34 amount=-4
412 | kerning first=76 second=39 amount=-4
413 | kerning first=76 second=42 amount=-4
414 | kerning first=76 second=44 amount=1
415 | kerning first=76 second=45 amount=-3
416 | kerning first=76 second=46 amount=1
417 | kerning first=76 second=63 amount=-1
418 | kerning first=76 second=64 amount=-1
419 | kerning first=76 second=67 amount=-1
420 | kerning first=76 second=71 amount=-1
421 | kerning first=76 second=79 amount=-1
422 | kerning first=76 second=81 amount=-1
423 | kerning first=76 second=84 amount=-3
424 | kerning first=76 second=86 amount=-3
425 | kerning first=76 second=87 amount=-3
426 | kerning first=76 second=89 amount=-4
427 | kerning first=76 second=92 amount=-3
428 | kerning first=76 second=99 amount=-1
429 | kerning first=76 second=100 amount=-1
430 | kerning first=76 second=101 amount=-1
431 | kerning first=76 second=111 amount=-1
432 | kerning first=76 second=113 amount=-1
433 | kerning first=76 second=118 amount=-2
434 | kerning first=76 second=119 amount=-1
435 | kerning first=76 second=121 amount=-2
436 | kerning first=75 second=45 amount=-1
437 | kerning first=75 second=99 amount=-1
438 | kerning first=75 second=100 amount=-1
439 | kerning first=75 second=101 amount=-1
440 | kerning first=75 second=102 amount=-1
441 | kerning first=75 second=111 amount=-1
442 | kerning first=75 second=113 amount=-1
443 | kerning first=75 second=116 amount=-2
444 | kerning first=75 second=118 amount=-1
445 | kerning first=75 second=119 amount=-1
446 | kerning first=75 second=121 amount=-1
447 | kerning first=74 second=38 amount=-1
448 | kerning first=74 second=44 amount=-1
449 | kerning first=74 second=46 amount=-1
450 | kerning first=74 second=47 amount=-1
451 | kerning first=74 second=65 amount=-1
452 | kerning first=70 second=38 amount=-3
453 | kerning first=70 second=44 amount=-3
454 | kerning first=70 second=46 amount=-3
455 | kerning first=70 second=47 amount=-3
456 | kerning first=70 second=58 amount=-1
457 | kerning first=70 second=59 amount=-1
458 | kerning first=70 second=65 amount=-3
459 | kerning first=70 second=74 amount=-3
460 | kerning first=70 second=99 amount=-1
461 | kerning first=70 second=100 amount=-1
462 | kerning first=70 second=101 amount=-1
463 | kerning first=70 second=109 amount=-1
464 | kerning first=70 second=110 amount=-1
465 | kerning first=70 second=111 amount=-1
466 | kerning first=70 second=112 amount=-1
467 | kerning first=70 second=113 amount=-1
468 | kerning first=70 second=114 amount=-1
469 | kerning first=70 second=117 amount=-1
470 | kerning first=68 second=34 amount=-1
471 | kerning first=68 second=38 amount=-1
472 | kerning first=68 second=39 amount=-1
473 | kerning first=68 second=41 amount=-1
474 | kerning first=68 second=42 amount=-1
475 | kerning first=68 second=44 amount=-1
476 | kerning first=68 second=46 amount=-1
477 | kerning first=68 second=47 amount=-1
478 | kerning first=68 second=65 amount=-1
479 | kerning first=68 second=84 amount=-1
480 | kerning first=68 second=86 amount=-1
481 | kerning first=68 second=89 amount=-1
482 | kerning first=68 second=90 amount=-1
483 | kerning first=68 second=92 amount=-1
484 | kerning first=68 second=93 amount=-1
485 | kerning first=68 second=125 amount=-1
486 | kerning first=67 second=45 amount=-2
487 | kerning first=65 second=34 amount=-3
488 | kerning first=65 second=39 amount=-3
489 | kerning first=65 second=42 amount=-3
490 | kerning first=65 second=45 amount=-1
491 | kerning first=65 second=63 amount=-1
492 | kerning first=65 second=64 amount=-1
493 | kerning first=65 second=67 amount=-1
494 | kerning first=65 second=71 amount=-1
495 | kerning first=65 second=74 amount=1
496 | kerning first=65 second=79 amount=-1
497 | kerning first=65 second=81 amount=-1
498 | kerning first=65 second=84 amount=-3
499 | kerning first=65 second=85 amount=-1
500 | kerning first=65 second=86 amount=-3
501 | kerning first=65 second=87 amount=-2
502 | kerning first=65 second=89 amount=-3
503 | kerning first=65 second=92 amount=-3
504 | kerning first=65 second=118 amount=-2
505 | kerning first=65 second=121 amount=-2
506 | kerning first=102 second=34 amount=1
507 | kerning first=102 second=39 amount=1
508 | kerning first=102 second=42 amount=1
509 | kerning first=102 second=44 amount=-2
510 | kerning first=102 second=46 amount=-2
511 | kerning first=121 second=38 amount=-2
512 | kerning first=121 second=44 amount=-2
513 | kerning first=121 second=46 amount=-2
514 | kerning first=121 second=47 amount=-2
515 | kerning first=121 second=65 amount=-2
516 | kerning first=121 second=99 amount=-1
517 | kerning first=121 second=100 amount=-1
518 | kerning first=121 second=101 amount=-1
519 | kerning first=121 second=111 amount=-1
520 | kerning first=121 second=113 amount=-1
521 | kerning first=112 second=34 amount=-2
522 | kerning first=112 second=39 amount=-2
523 | kerning first=112 second=41 amount=-1
524 | kerning first=112 second=42 amount=-2
525 | kerning first=112 second=86 amount=-2
526 | kerning first=112 second=87 amount=-1
527 | kerning first=112 second=92 amount=-2
528 | kerning first=112 second=93 amount=-1
529 | kerning first=112 second=118 amount=-1
530 | kerning first=112 second=120 amount=-1
531 | kerning first=112 second=121 amount=-1
532 | kerning first=112 second=125 amount=-1
533 | kerning first=120 second=99 amount=-1
534 | kerning first=120 second=100 amount=-1
535 | kerning first=120 second=101 amount=-1
536 | kerning first=120 second=111 amount=-1
537 | kerning first=120 second=113 amount=-1
538 | kerning first=119 second=44 amount=-1
539 | kerning first=119 second=46 amount=-1
540 | kerning first=118 second=38 amount=-2
541 | kerning first=118 second=44 amount=-2
542 | kerning first=118 second=46 amount=-2
543 | kerning first=118 second=47 amount=-2
544 | kerning first=118 second=65 amount=-2
545 | kerning first=118 second=99 amount=-1
546 | kerning first=118 second=100 amount=-1
547 | kerning first=118 second=101 amount=-1
548 | kerning first=118 second=111 amount=-1
549 | kerning first=118 second=113 amount=-1
550 | kerning first=114 second=44 amount=-2
551 | kerning first=114 second=46 amount=-2
552 | kerning first=110 second=34 amount=-1
553 | kerning first=110 second=39 amount=-1
554 | kerning first=110 second=42 amount=-1
555 | kerning first=110 second=118 amount=-1
556 | kerning first=110 second=121 amount=-1
557 | kerning first=109 second=34 amount=-1
558 | kerning first=109 second=39 amount=-1
559 | kerning first=109 second=42 amount=-1
560 | kerning first=109 second=118 amount=-1
561 | kerning first=109 second=121 amount=-1
562 | kerning first=101 second=34 amount=-2
563 | kerning first=101 second=39 amount=-2
564 | kerning first=101 second=41 amount=-1
565 | kerning first=101 second=42 amount=-2
566 | kerning first=101 second=86 amount=-2
567 | kerning first=101 second=87 amount=-1
568 | kerning first=101 second=92 amount=-2
569 | kerning first=101 second=93 amount=-1
570 | kerning first=101 second=118 amount=-1
571 | kerning first=101 second=120 amount=-1
572 | kerning first=101 second=121 amount=-1
573 | kerning first=101 second=125 amount=-1
574 | kerning first=97 second=34 amount=-1
575 | kerning first=97 second=39 amount=-1
576 | kerning first=97 second=42 amount=-1
577 | kerning first=97 second=118 amount=-1
578 | kerning first=97 second=121 amount=-1
579 | kerning first=111 second=34 amount=-2
580 | kerning first=111 second=39 amount=-2
581 | kerning first=111 second=41 amount=-1
582 | kerning first=111 second=42 amount=-2
583 | kerning first=111 second=86 amount=-2
584 | kerning first=111 second=87 amount=-1
585 | kerning first=111 second=92 amount=-2
586 | kerning first=111 second=93 amount=-1
587 | kerning first=111 second=118 amount=-1
588 | kerning first=111 second=120 amount=-1
589 | kerning first=111 second=121 amount=-1
590 | kerning first=111 second=125 amount=-1
591 | kerning first=42 second=38 amount=-3
592 | kerning first=42 second=44 amount=-3
593 | kerning first=42 second=45 amount=-3
594 | kerning first=42 second=46 amount=-3
595 | kerning first=42 second=47 amount=-3
596 | kerning first=42 second=64 amount=-1
597 | kerning first=42 second=65 amount=-3
598 | kerning first=42 second=67 amount=-1
599 | kerning first=42 second=71 amount=-1
600 | kerning first=42 second=79 amount=-1
601 | kerning first=42 second=81 amount=-1
602 | kerning first=42 second=86 amount=1
603 | kerning first=42 second=87 amount=1
604 | kerning first=42 second=89 amount=1
605 | kerning first=42 second=92 amount=1
606 | kerning first=42 second=97 amount=-1
607 | kerning first=42 second=99 amount=-2
608 | kerning first=42 second=100 amount=-2
609 | kerning first=42 second=101 amount=-2
610 | kerning first=42 second=111 amount=-2
611 | kerning first=42 second=113 amount=-2
612 | kerning first=44 second=34 amount=-3
613 | kerning first=44 second=39 amount=-3
614 | kerning first=44 second=42 amount=-3
615 | kerning first=44 second=45 amount=-2
616 | kerning first=44 second=64 amount=-1
617 | kerning first=44 second=67 amount=-1
618 | kerning first=44 second=71 amount=-1
619 | kerning first=44 second=79 amount=-1
620 | kerning first=44 second=81 amount=-1
621 | kerning first=44 second=84 amount=-3
622 | kerning first=44 second=86 amount=-3
623 | kerning first=44 second=87 amount=-2
624 | kerning first=44 second=89 amount=-3
625 | kerning first=44 second=92 amount=-3
626 | kerning first=44 second=118 amount=-2
627 | kerning first=44 second=119 amount=-1
628 | kerning first=44 second=121 amount=-2
629 | kerning first=39 second=38 amount=-3
630 | kerning first=39 second=44 amount=-3
631 | kerning first=39 second=45 amount=-3
632 | kerning first=39 second=46 amount=-3
633 | kerning first=39 second=47 amount=-3
634 | kerning first=39 second=64 amount=-1
635 | kerning first=39 second=65 amount=-3
636 | kerning first=39 second=67 amount=-1
637 | kerning first=39 second=71 amount=-1
638 | kerning first=39 second=79 amount=-1
639 | kerning first=39 second=81 amount=-1
640 | kerning first=39 second=86 amount=1
641 | kerning first=39 second=87 amount=1
642 | kerning first=39 second=89 amount=1
643 | kerning first=39 second=92 amount=1
644 | kerning first=39 second=97 amount=-1
645 | kerning first=39 second=99 amount=-2
646 | kerning first=39 second=100 amount=-2
647 | kerning first=39 second=101 amount=-2
648 | kerning first=39 second=111 amount=-2
649 | kerning first=39 second=113 amount=-2
650 | kerning first=34 second=38 amount=-3
651 | kerning first=34 second=44 amount=-3
652 | kerning first=34 second=45 amount=-3
653 | kerning first=34 second=46 amount=-3
654 | kerning first=34 second=47 amount=-3
655 | kerning first=34 second=64 amount=-1
656 | kerning first=34 second=65 amount=-3
657 | kerning first=34 second=67 amount=-1
658 | kerning first=34 second=71 amount=-1
659 | kerning first=34 second=79 amount=-1
660 | kerning first=34 second=81 amount=-1
661 | kerning first=34 second=86 amount=1
662 | kerning first=34 second=87 amount=1
663 | kerning first=34 second=89 amount=1
664 | kerning first=34 second=92 amount=1
665 | kerning first=34 second=97 amount=-1
666 | kerning first=34 second=99 amount=-2
667 | kerning first=34 second=100 amount=-2
668 | kerning first=34 second=101 amount=-2
669 | kerning first=34 second=111 amount=-2
670 | kerning first=34 second=113 amount=-2
671 | kerning first=46 second=34 amount=-3
672 | kerning first=46 second=39 amount=-3
673 | kerning first=46 second=42 amount=-3
674 | kerning first=46 second=45 amount=-2
675 | kerning first=46 second=64 amount=-1
676 | kerning first=46 second=67 amount=-1
677 | kerning first=46 second=71 amount=-1
678 | kerning first=46 second=79 amount=-1
679 | kerning first=46 second=81 amount=-1
680 | kerning first=46 second=84 amount=-3
681 | kerning first=46 second=86 amount=-3
682 | kerning first=46 second=87 amount=-2
683 | kerning first=46 second=89 amount=-3
684 | kerning first=46 second=92 amount=-3
685 | kerning first=46 second=118 amount=-2
686 | kerning first=46 second=119 amount=-1
687 | kerning first=46 second=121 amount=-2
688 | kerning first=45 second=34 amount=-3
689 | kerning first=45 second=38 amount=-1
690 | kerning first=45 second=39 amount=-3
691 | kerning first=45 second=42 amount=-3
692 | kerning first=45 second=44 amount=-2
693 | kerning first=45 second=46 amount=-2
694 | kerning first=45 second=47 amount=-1
695 | kerning first=45 second=65 amount=-1
696 | kerning first=45 second=84 amount=-3
697 | kerning first=45 second=86 amount=-2
698 | kerning first=45 second=87 amount=-1
699 | kerning first=45 second=88 amount=-1
700 | kerning first=45 second=89 amount=-3
701 | kerning first=45 second=90 amount=-1
702 | kerning first=45 second=92 amount=-2
703 |
--------------------------------------------------------------------------------
/demo/sdf/LatoBlack-sdf.json:
--------------------------------------------------------------------------------
1 | {"pages":["LatoBlack-sdf.png"],"chars":[{"id":32,"x":0,"y":0,"width":0,"height":0,"xoffset":0,"yoffset":32,"xadvance":6,"page":0,"chnl":0},{"id":41,"x":0,"y":0,"width":17,"height":41,"xoffset":-3,"yoffset":2,"xadvance":10,"page":0,"chnl":0},{"id":40,"x":17,"y":0,"width":17,"height":41,"xoffset":-3,"yoffset":2,"xadvance":10,"page":0,"chnl":0},{"id":36,"x":34,"y":0,"width":27,"height":40,"xoffset":-4,"yoffset":0,"xadvance":19,"page":0,"chnl":0},{"id":124,"x":61,"y":0,"width":14,"height":40,"xoffset":-2,"yoffset":2,"xadvance":10,"page":0,"chnl":0},{"id":125,"x":75,"y":0,"width":19,"height":40,"xoffset":-4,"yoffset":2,"xadvance":10,"page":0,"chnl":0},{"id":123,"x":94,"y":0,"width":18,"height":40,"xoffset":-4,"yoffset":2,"xadvance":10,"page":0,"chnl":0},{"id":93,"x":112,"y":0,"width":18,"height":40,"xoffset":-4,"yoffset":2,"xadvance":10,"page":0,"chnl":0},{"id":91,"x":130,"y":0,"width":17,"height":40,"xoffset":-3,"yoffset":2,"xadvance":10,"page":0,"chnl":0},{"id":106,"x":147,"y":0,"width":18,"height":38,"xoffset":-5,"yoffset":4,"xadvance":9,"page":0,"chnl":0},{"id":81,"x":165,"y":0,"width":36,"height":38,"xoffset":-4,"yoffset":3,"xadvance":26,"page":0,"chnl":0},{"id":92,"x":201,"y":0,"width":24,"height":36,"xoffset":-5,"yoffset":3,"xadvance":13,"page":0,"chnl":0},{"id":64,"x":225,"y":0,"width":35,"height":36,"xoffset":-4,"yoffset":5,"xadvance":26,"page":0,"chnl":0},{"id":47,"x":260,"y":0,"width":24,"height":36,"xoffset":-5,"yoffset":3,"xadvance":13,"page":0,"chnl":0},{"id":127,"x":284,"y":0,"width":27,"height":34,"xoffset":-4,"yoffset":3,"xadvance":18,"page":0,"chnl":0},{"id":38,"x":311,"y":0,"width":33,"height":34,"xoffset":-4,"yoffset":3,"xadvance":23,"page":0,"chnl":0},{"id":35,"x":344,"y":0,"width":28,"height":34,"xoffset":-4,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":37,"x":372,"y":0,"width":35,"height":34,"xoffset":-4,"yoffset":3,"xadvance":26,"page":0,"chnl":0},{"id":63,"x":407,"y":0,"width":23,"height":34,"xoffset":-4,"yoffset":3,"xadvance":14,"page":0,"chnl":0},{"id":33,"x":430,"y":0,"width":15,"height":34,"xoffset":-1,"yoffset":3,"xadvance":12,"page":0,"chnl":0},{"id":48,"x":445,"y":0,"width":27,"height":34,"xoffset":-4,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":56,"x":472,"y":0,"width":27,"height":34,"xoffset":-4,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":55,"x":0,"y":41,"width":26,"height":34,"xoffset":-3,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":54,"x":26,"y":41,"width":26,"height":34,"xoffset":-3,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":53,"x":52,"y":41,"width":26,"height":34,"xoffset":-4,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":52,"x":78,"y":41,"width":28,"height":34,"xoffset":-4,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":51,"x":106,"y":41,"width":26,"height":34,"xoffset":-3,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":50,"x":132,"y":41,"width":26,"height":34,"xoffset":-3,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":49,"x":158,"y":41,"width":25,"height":34,"xoffset":-2,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":108,"x":183,"y":41,"width":15,"height":34,"xoffset":-2,"yoffset":3,"xadvance":9,"page":0,"chnl":0},{"id":107,"x":198,"y":41,"width":27,"height":34,"xoffset":-3,"yoffset":3,"xadvance":18,"page":0,"chnl":0},{"id":104,"x":225,"y":41,"width":25,"height":34,"xoffset":-3,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":100,"x":250,"y":41,"width":26,"height":34,"xoffset":-4,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":98,"x":276,"y":41,"width":26,"height":34,"xoffset":-3,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":90,"x":302,"y":41,"width":28,"height":34,"xoffset":-4,"yoffset":3,"xadvance":20,"page":0,"chnl":0},{"id":89,"x":330,"y":41,"width":32,"height":34,"xoffset":-5,"yoffset":3,"xadvance":22,"page":0,"chnl":0},{"id":88,"x":362,"y":41,"width":32,"height":34,"xoffset":-4,"yoffset":3,"xadvance":23,"page":0,"chnl":0},{"id":87,"x":394,"y":41,"width":44,"height":34,"xoffset":-4,"yoffset":3,"xadvance":34,"page":0,"chnl":0},{"id":86,"x":438,"y":41,"width":33,"height":34,"xoffset":-4,"yoffset":3,"xadvance":24,"page":0,"chnl":0},{"id":85,"x":471,"y":41,"width":30,"height":34,"xoffset":-3,"yoffset":3,"xadvance":23,"page":0,"chnl":0},{"id":84,"x":0,"y":75,"width":28,"height":34,"xoffset":-4,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":83,"x":28,"y":75,"width":26,"height":34,"xoffset":-4,"yoffset":3,"xadvance":17,"page":0,"chnl":0},{"id":82,"x":54,"y":75,"width":29,"height":34,"xoffset":-3,"yoffset":3,"xadvance":21,"page":0,"chnl":0},{"id":80,"x":83,"y":75,"width":28,"height":34,"xoffset":-3,"yoffset":3,"xadvance":20,"page":0,"chnl":0},{"id":79,"x":111,"y":75,"width":34,"height":34,"xoffset":-4,"yoffset":3,"xadvance":26,"page":0,"chnl":0},{"id":78,"x":145,"y":75,"width":31,"height":34,"xoffset":-3,"yoffset":3,"xadvance":24,"page":0,"chnl":0},{"id":77,"x":176,"y":75,"width":37,"height":34,"xoffset":-3,"yoffset":3,"xadvance":30,"page":0,"chnl":0},{"id":76,"x":213,"y":75,"width":24,"height":34,"xoffset":-3,"yoffset":3,"xadvance":17,"page":0,"chnl":0},{"id":75,"x":237,"y":75,"width":31,"height":34,"xoffset":-3,"yoffset":3,"xadvance":23,"page":0,"chnl":0},{"id":74,"x":268,"y":75,"width":21,"height":34,"xoffset":-4,"yoffset":3,"xadvance":14,"page":0,"chnl":0},{"id":73,"x":289,"y":75,"width":15,"height":34,"xoffset":-2,"yoffset":3,"xadvance":10,"page":0,"chnl":0},{"id":72,"x":304,"y":75,"width":31,"height":34,"xoffset":-3,"yoffset":3,"xadvance":24,"page":0,"chnl":0},{"id":71,"x":335,"y":75,"width":31,"height":34,"xoffset":-4,"yoffset":3,"xadvance":23,"page":0,"chnl":0},{"id":70,"x":366,"y":75,"width":25,"height":34,"xoffset":-3,"yoffset":3,"xadvance":18,"page":0,"chnl":0},{"id":69,"x":391,"y":75,"width":25,"height":34,"xoffset":-3,"yoffset":3,"xadvance":18,"page":0,"chnl":0},{"id":68,"x":416,"y":75,"width":32,"height":34,"xoffset":-3,"yoffset":3,"xadvance":24,"page":0,"chnl":0},{"id":67,"x":448,"y":75,"width":30,"height":34,"xoffset":-4,"yoffset":3,"xadvance":21,"page":0,"chnl":0},{"id":66,"x":478,"y":75,"width":28,"height":34,"xoffset":-3,"yoffset":3,"xadvance":21,"page":0,"chnl":0},{"id":65,"x":0,"y":109,"width":33,"height":34,"xoffset":-4,"yoffset":3,"xadvance":24,"page":0,"chnl":0},{"id":57,"x":33,"y":109,"width":27,"height":33,"xoffset":-3,"yoffset":4,"xadvance":19,"page":0,"chnl":0},{"id":105,"x":60,"y":109,"width":16,"height":33,"xoffset":-3,"yoffset":4,"xadvance":9,"page":0,"chnl":0},{"id":102,"x":76,"y":109,"width":21,"height":33,"xoffset":-4,"yoffset":4,"xadvance":12,"page":0,"chnl":0},{"id":121,"x":97,"y":109,"width":27,"height":32,"xoffset":-4,"yoffset":10,"xadvance":18,"page":0,"chnl":0},{"id":116,"x":124,"y":109,"width":22,"height":32,"xoffset":-4,"yoffset":5,"xadvance":13,"page":0,"chnl":0},{"id":113,"x":146,"y":109,"width":26,"height":32,"xoffset":-4,"yoffset":10,"xadvance":19,"page":0,"chnl":0},{"id":112,"x":172,"y":109,"width":26,"height":32,"xoffset":-3,"yoffset":10,"xadvance":19,"page":0,"chnl":0},{"id":103,"x":198,"y":109,"width":26,"height":32,"xoffset":-4,"yoffset":10,"xadvance":17,"page":0,"chnl":0},{"id":59,"x":224,"y":109,"width":16,"height":31,"xoffset":-3,"yoffset":11,"xadvance":9,"page":0,"chnl":0},{"id":122,"x":240,"y":109,"width":23,"height":27,"xoffset":-3,"yoffset":10,"xadvance":15,"page":0,"chnl":0},{"id":120,"x":263,"y":109,"width":27,"height":27,"xoffset":-4,"yoffset":10,"xadvance":18,"page":0,"chnl":0},{"id":119,"x":290,"y":109,"width":35,"height":27,"xoffset":-4,"yoffset":10,"xadvance":26,"page":0,"chnl":0},{"id":118,"x":325,"y":109,"width":27,"height":27,"xoffset":-4,"yoffset":10,"xadvance":18,"page":0,"chnl":0},{"id":117,"x":352,"y":109,"width":25,"height":27,"xoffset":-3,"yoffset":10,"xadvance":19,"page":0,"chnl":0},{"id":115,"x":377,"y":109,"width":23,"height":27,"xoffset":-4,"yoffset":10,"xadvance":14,"page":0,"chnl":0},{"id":114,"x":400,"y":109,"width":21,"height":27,"xoffset":-3,"yoffset":10,"xadvance":13,"page":0,"chnl":0},{"id":110,"x":421,"y":109,"width":25,"height":27,"xoffset":-3,"yoffset":10,"xadvance":19,"page":0,"chnl":0},{"id":109,"x":446,"y":109,"width":34,"height":27,"xoffset":-3,"yoffset":10,"xadvance":28,"page":0,"chnl":0},{"id":101,"x":480,"y":109,"width":26,"height":27,"xoffset":-4,"yoffset":10,"xadvance":17,"page":0,"chnl":0},{"id":99,"x":0,"y":143,"width":25,"height":27,"xoffset":-4,"yoffset":10,"xadvance":16,"page":0,"chnl":0},{"id":97,"x":25,"y":143,"width":24,"height":27,"xoffset":-3,"yoffset":10,"xadvance":17,"page":0,"chnl":0},{"id":43,"x":49,"y":143,"width":26,"height":26,"xoffset":-3,"yoffset":8,"xadvance":19,"page":0,"chnl":0},{"id":58,"x":75,"y":143,"width":16,"height":26,"xoffset":-3,"yoffset":11,"xadvance":9,"page":0,"chnl":0},{"id":111,"x":91,"y":143,"width":27,"height":26,"xoffset":-4,"yoffset":11,"xadvance":19,"page":0,"chnl":0},{"id":62,"x":118,"y":143,"width":23,"height":25,"xoffset":-1,"yoffset":9,"xadvance":19,"page":0,"chnl":0},{"id":60,"x":141,"y":143,"width":23,"height":25,"xoffset":-2,"yoffset":9,"xadvance":19,"page":0,"chnl":0},{"id":42,"x":164,"y":143,"width":21,"height":21,"xoffset":-4,"yoffset":3,"xadvance":13,"page":0,"chnl":0},{"id":94,"x":185,"y":143,"width":25,"height":21,"xoffset":-3,"yoffset":3,"xadvance":19,"page":0,"chnl":0},{"id":44,"x":210,"y":143,"width":15,"height":20,"xoffset":-3,"yoffset":22,"xadvance":8,"page":0,"chnl":0},{"id":61,"x":225,"y":143,"width":25,"height":19,"xoffset":-3,"yoffset":12,"xadvance":19,"page":0,"chnl":0},{"id":39,"x":250,"y":143,"width":15,"height":19,"xoffset":-3,"yoffset":3,"xadvance":8,"page":0,"chnl":0},{"id":34,"x":265,"y":143,"width":21,"height":19,"xoffset":-3,"yoffset":3,"xadvance":14,"page":0,"chnl":0},{"id":126,"x":286,"y":143,"width":26,"height":17,"xoffset":-3,"yoffset":14,"xadvance":19,"page":0,"chnl":0},{"id":46,"x":312,"y":143,"width":16,"height":16,"xoffset":-4,"yoffset":21,"xadvance":8,"page":0,"chnl":0},{"id":96,"x":328,"y":143,"width":18,"height":15,"xoffset":-5,"yoffset":3,"xadvance":11,"page":0,"chnl":0},{"id":95,"x":346,"y":143,"width":22,"height":13,"xoffset":-4,"yoffset":29,"xadvance":13,"page":0,"chnl":0},{"id":45,"x":368,"y":143,"width":19,"height":13,"xoffset":-3,"yoffset":16,"xadvance":12,"page":0,"chnl":0}],"kernings":[{"first":40,"second":64,"amount":-1},{"first":40,"second":67,"amount":-1},{"first":40,"second":71,"amount":-1},{"first":40,"second":79,"amount":-1},{"first":40,"second":81,"amount":-1},{"first":40,"second":99,"amount":-1},{"first":40,"second":100,"amount":-1},{"first":40,"second":101,"amount":-1},{"first":40,"second":111,"amount":-1},{"first":40,"second":113,"amount":-1},{"first":123,"second":64,"amount":-1},{"first":123,"second":67,"amount":-1},{"first":123,"second":71,"amount":-1},{"first":123,"second":79,"amount":-1},{"first":123,"second":81,"amount":-1},{"first":123,"second":99,"amount":-1},{"first":123,"second":100,"amount":-1},{"first":123,"second":101,"amount":-1},{"first":123,"second":111,"amount":-1},{"first":123,"second":113,"amount":-1},{"first":91,"second":64,"amount":-1},{"first":91,"second":67,"amount":-1},{"first":91,"second":71,"amount":-1},{"first":91,"second":79,"amount":-1},{"first":91,"second":81,"amount":-1},{"first":91,"second":99,"amount":-1},{"first":91,"second":100,"amount":-1},{"first":91,"second":101,"amount":-1},{"first":91,"second":111,"amount":-1},{"first":91,"second":113,"amount":-1},{"first":81,"second":34,"amount":-1},{"first":81,"second":38,"amount":-1},{"first":81,"second":39,"amount":-1},{"first":81,"second":41,"amount":-1},{"first":81,"second":42,"amount":-1},{"first":81,"second":44,"amount":-1},{"first":81,"second":46,"amount":-1},{"first":81,"second":47,"amount":-1},{"first":81,"second":65,"amount":-1},{"first":81,"second":84,"amount":-1},{"first":81,"second":86,"amount":-1},{"first":81,"second":89,"amount":-1},{"first":81,"second":90,"amount":-1},{"first":81,"second":92,"amount":-1},{"first":81,"second":93,"amount":-1},{"first":81,"second":125,"amount":-1},{"first":92,"second":34,"amount":-3},{"first":92,"second":39,"amount":-3},{"first":92,"second":42,"amount":-3},{"first":92,"second":45,"amount":-1},{"first":92,"second":63,"amount":-1},{"first":92,"second":64,"amount":-1},{"first":92,"second":67,"amount":-1},{"first":92,"second":71,"amount":-1},{"first":92,"second":74,"amount":1},{"first":92,"second":79,"amount":-1},{"first":92,"second":81,"amount":-1},{"first":92,"second":84,"amount":-3},{"first":92,"second":85,"amount":-1},{"first":92,"second":86,"amount":-3},{"first":92,"second":87,"amount":-2},{"first":92,"second":89,"amount":-3},{"first":92,"second":92,"amount":-3},{"first":92,"second":118,"amount":-2},{"first":92,"second":121,"amount":-2},{"first":64,"second":34,"amount":-1},{"first":64,"second":38,"amount":-1},{"first":64,"second":39,"amount":-1},{"first":64,"second":41,"amount":-1},{"first":64,"second":42,"amount":-1},{"first":64,"second":44,"amount":-1},{"first":64,"second":46,"amount":-1},{"first":64,"second":47,"amount":-1},{"first":64,"second":65,"amount":-1},{"first":64,"second":84,"amount":-1},{"first":64,"second":86,"amount":-1},{"first":64,"second":89,"amount":-1},{"first":64,"second":90,"amount":-1},{"first":64,"second":92,"amount":-1},{"first":64,"second":93,"amount":-1},{"first":64,"second":125,"amount":-1},{"first":47,"second":34,"amount":1},{"first":47,"second":38,"amount":-3},{"first":47,"second":39,"amount":1},{"first":47,"second":42,"amount":1},{"first":47,"second":44,"amount":-3},{"first":47,"second":45,"amount":-2},{"first":47,"second":46,"amount":-3},{"first":47,"second":47,"amount":-3},{"first":47,"second":58,"amount":-2},{"first":47,"second":59,"amount":-2},{"first":47,"second":64,"amount":-1},{"first":47,"second":65,"amount":-3},{"first":47,"second":67,"amount":-1},{"first":47,"second":71,"amount":-1},{"first":47,"second":74,"amount":-3},{"first":47,"second":79,"amount":-1},{"first":47,"second":81,"amount":-1},{"first":47,"second":97,"amount":-2},{"first":47,"second":99,"amount":-2},{"first":47,"second":100,"amount":-2},{"first":47,"second":101,"amount":-2},{"first":47,"second":103,"amount":-2},{"first":47,"second":109,"amount":-2},{"first":47,"second":110,"amount":-2},{"first":47,"second":111,"amount":-2},{"first":47,"second":112,"amount":-2},{"first":47,"second":113,"amount":-2},{"first":47,"second":114,"amount":-2},{"first":47,"second":115,"amount":-2},{"first":47,"second":116,"amount":-1},{"first":47,"second":117,"amount":-2},{"first":47,"second":118,"amount":-1},{"first":47,"second":120,"amount":-1},{"first":47,"second":121,"amount":-1},{"first":47,"second":122,"amount":-2},{"first":107,"second":99,"amount":-1},{"first":107,"second":100,"amount":-1},{"first":107,"second":101,"amount":-1},{"first":107,"second":111,"amount":-1},{"first":107,"second":113,"amount":-1},{"first":104,"second":34,"amount":-1},{"first":104,"second":39,"amount":-1},{"first":104,"second":42,"amount":-1},{"first":104,"second":118,"amount":-1},{"first":104,"second":121,"amount":-1},{"first":98,"second":34,"amount":-2},{"first":98,"second":39,"amount":-2},{"first":98,"second":41,"amount":-1},{"first":98,"second":42,"amount":-2},{"first":98,"second":86,"amount":-2},{"first":98,"second":87,"amount":-1},{"first":98,"second":92,"amount":-2},{"first":98,"second":93,"amount":-1},{"first":98,"second":118,"amount":-1},{"first":98,"second":120,"amount":-1},{"first":98,"second":121,"amount":-1},{"first":98,"second":125,"amount":-1},{"first":90,"second":45,"amount":-1},{"first":90,"second":64,"amount":-1},{"first":90,"second":67,"amount":-1},{"first":90,"second":71,"amount":-1},{"first":90,"second":79,"amount":-1},{"first":90,"second":81,"amount":-1},{"first":89,"second":34,"amount":1},{"first":89,"second":38,"amount":-3},{"first":89,"second":39,"amount":1},{"first":89,"second":42,"amount":1},{"first":89,"second":44,"amount":-3},{"first":89,"second":45,"amount":-3},{"first":89,"second":46,"amount":-3},{"first":89,"second":47,"amount":-3},{"first":89,"second":58,"amount":-2},{"first":89,"second":59,"amount":-2},{"first":89,"second":64,"amount":-1},{"first":89,"second":65,"amount":-3},{"first":89,"second":67,"amount":-1},{"first":89,"second":71,"amount":-1},{"first":89,"second":74,"amount":-3},{"first":89,"second":79,"amount":-1},{"first":89,"second":81,"amount":-1},{"first":89,"second":97,"amount":-3},{"first":89,"second":99,"amount":-3},{"first":89,"second":100,"amount":-3},{"first":89,"second":101,"amount":-3},{"first":89,"second":103,"amount":-3},{"first":89,"second":109,"amount":-2},{"first":89,"second":110,"amount":-2},{"first":89,"second":111,"amount":-3},{"first":89,"second":112,"amount":-2},{"first":89,"second":113,"amount":-3},{"first":89,"second":114,"amount":-2},{"first":89,"second":115,"amount":-2},{"first":89,"second":117,"amount":-2},{"first":89,"second":118,"amount":-2},{"first":89,"second":119,"amount":-2},{"first":89,"second":120,"amount":-2},{"first":89,"second":121,"amount":-2},{"first":88,"second":45,"amount":-1},{"first":88,"second":99,"amount":-1},{"first":88,"second":100,"amount":-1},{"first":88,"second":101,"amount":-1},{"first":88,"second":102,"amount":-1},{"first":88,"second":111,"amount":-1},{"first":88,"second":113,"amount":-1},{"first":88,"second":116,"amount":-2},{"first":88,"second":118,"amount":-1},{"first":88,"second":119,"amount":-1},{"first":88,"second":121,"amount":-1},{"first":87,"second":34,"amount":1},{"first":87,"second":38,"amount":-2},{"first":87,"second":39,"amount":1},{"first":87,"second":42,"amount":1},{"first":87,"second":44,"amount":-2},{"first":87,"second":45,"amount":-1},{"first":87,"second":46,"amount":-2},{"first":87,"second":47,"amount":-2},{"first":87,"second":65,"amount":-2},{"first":87,"second":74,"amount":-2},{"first":87,"second":97,"amount":-2},{"first":87,"second":99,"amount":-1},{"first":87,"second":100,"amount":-1},{"first":87,"second":101,"amount":-1},{"first":87,"second":103,"amount":-2},{"first":87,"second":111,"amount":-1},{"first":87,"second":113,"amount":-1},{"first":87,"second":115,"amount":-1},{"first":86,"second":34,"amount":1},{"first":86,"second":38,"amount":-3},{"first":86,"second":39,"amount":1},{"first":86,"second":42,"amount":1},{"first":86,"second":44,"amount":-3},{"first":86,"second":45,"amount":-2},{"first":86,"second":46,"amount":-3},{"first":86,"second":47,"amount":-3},{"first":86,"second":58,"amount":-2},{"first":86,"second":59,"amount":-2},{"first":86,"second":64,"amount":-1},{"first":86,"second":65,"amount":-3},{"first":86,"second":67,"amount":-1},{"first":86,"second":71,"amount":-1},{"first":86,"second":74,"amount":-3},{"first":86,"second":79,"amount":-1},{"first":86,"second":81,"amount":-1},{"first":86,"second":97,"amount":-2},{"first":86,"second":99,"amount":-2},{"first":86,"second":100,"amount":-2},{"first":86,"second":101,"amount":-2},{"first":86,"second":103,"amount":-2},{"first":86,"second":109,"amount":-2},{"first":86,"second":110,"amount":-2},{"first":86,"second":111,"amount":-2},{"first":86,"second":112,"amount":-2},{"first":86,"second":113,"amount":-2},{"first":86,"second":114,"amount":-2},{"first":86,"second":115,"amount":-2},{"first":86,"second":116,"amount":-1},{"first":86,"second":117,"amount":-2},{"first":86,"second":118,"amount":-1},{"first":86,"second":120,"amount":-1},{"first":86,"second":121,"amount":-1},{"first":86,"second":122,"amount":-2},{"first":85,"second":38,"amount":-1},{"first":85,"second":44,"amount":-1},{"first":85,"second":46,"amount":-1},{"first":85,"second":47,"amount":-1},{"first":85,"second":65,"amount":-1},{"first":84,"second":38,"amount":-3},{"first":84,"second":44,"amount":-3},{"first":84,"second":45,"amount":-3},{"first":84,"second":46,"amount":-3},{"first":84,"second":47,"amount":-3},{"first":84,"second":58,"amount":-3},{"first":84,"second":59,"amount":-3},{"first":84,"second":64,"amount":-1},{"first":84,"second":65,"amount":-3},{"first":84,"second":67,"amount":-1},{"first":84,"second":71,"amount":-1},{"first":84,"second":74,"amount":-3},{"first":84,"second":79,"amount":-1},{"first":84,"second":81,"amount":-1},{"first":84,"second":97,"amount":-4},{"first":84,"second":99,"amount":-3},{"first":84,"second":100,"amount":-3},{"first":84,"second":101,"amount":-3},{"first":84,"second":103,"amount":-3},{"first":84,"second":109,"amount":-3},{"first":84,"second":110,"amount":-3},{"first":84,"second":111,"amount":-3},{"first":84,"second":112,"amount":-3},{"first":84,"second":113,"amount":-3},{"first":84,"second":114,"amount":-3},{"first":84,"second":115,"amount":-2},{"first":84,"second":117,"amount":-3},{"first":84,"second":118,"amount":-3},{"first":84,"second":119,"amount":-2},{"first":84,"second":120,"amount":-2},{"first":84,"second":121,"amount":-3},{"first":84,"second":122,"amount":-2},{"first":82,"second":64,"amount":-1},{"first":82,"second":67,"amount":-1},{"first":82,"second":71,"amount":-1},{"first":82,"second":79,"amount":-1},{"first":82,"second":81,"amount":-1},{"first":82,"second":84,"amount":-1},{"first":82,"second":85,"amount":-1},{"first":80,"second":38,"amount":-3},{"first":80,"second":44,"amount":-4},{"first":80,"second":46,"amount":-4},{"first":80,"second":47,"amount":-3},{"first":80,"second":65,"amount":-3},{"first":80,"second":74,"amount":-3},{"first":80,"second":97,"amount":-1},{"first":79,"second":34,"amount":-1},{"first":79,"second":38,"amount":-1},{"first":79,"second":39,"amount":-1},{"first":79,"second":41,"amount":-1},{"first":79,"second":42,"amount":-1},{"first":79,"second":44,"amount":-1},{"first":79,"second":46,"amount":-1},{"first":79,"second":47,"amount":-1},{"first":79,"second":65,"amount":-1},{"first":79,"second":84,"amount":-1},{"first":79,"second":86,"amount":-1},{"first":79,"second":89,"amount":-1},{"first":79,"second":90,"amount":-1},{"first":79,"second":92,"amount":-1},{"first":79,"second":93,"amount":-1},{"first":79,"second":125,"amount":-1},{"first":76,"second":34,"amount":-4},{"first":76,"second":39,"amount":-4},{"first":76,"second":42,"amount":-4},{"first":76,"second":44,"amount":1},{"first":76,"second":45,"amount":-3},{"first":76,"second":46,"amount":1},{"first":76,"second":63,"amount":-1},{"first":76,"second":64,"amount":-1},{"first":76,"second":67,"amount":-1},{"first":76,"second":71,"amount":-1},{"first":76,"second":79,"amount":-1},{"first":76,"second":81,"amount":-1},{"first":76,"second":84,"amount":-3},{"first":76,"second":86,"amount":-3},{"first":76,"second":87,"amount":-3},{"first":76,"second":89,"amount":-4},{"first":76,"second":92,"amount":-3},{"first":76,"second":99,"amount":-1},{"first":76,"second":100,"amount":-1},{"first":76,"second":101,"amount":-1},{"first":76,"second":111,"amount":-1},{"first":76,"second":113,"amount":-1},{"first":76,"second":118,"amount":-2},{"first":76,"second":119,"amount":-1},{"first":76,"second":121,"amount":-2},{"first":75,"second":45,"amount":-1},{"first":75,"second":99,"amount":-1},{"first":75,"second":100,"amount":-1},{"first":75,"second":101,"amount":-1},{"first":75,"second":102,"amount":-1},{"first":75,"second":111,"amount":-1},{"first":75,"second":113,"amount":-1},{"first":75,"second":116,"amount":-2},{"first":75,"second":118,"amount":-1},{"first":75,"second":119,"amount":-1},{"first":75,"second":121,"amount":-1},{"first":74,"second":38,"amount":-1},{"first":74,"second":44,"amount":-1},{"first":74,"second":46,"amount":-1},{"first":74,"second":47,"amount":-1},{"first":74,"second":65,"amount":-1},{"first":70,"second":38,"amount":-3},{"first":70,"second":44,"amount":-3},{"first":70,"second":46,"amount":-3},{"first":70,"second":47,"amount":-3},{"first":70,"second":58,"amount":-1},{"first":70,"second":59,"amount":-1},{"first":70,"second":65,"amount":-3},{"first":70,"second":74,"amount":-3},{"first":70,"second":99,"amount":-1},{"first":70,"second":100,"amount":-1},{"first":70,"second":101,"amount":-1},{"first":70,"second":109,"amount":-1},{"first":70,"second":110,"amount":-1},{"first":70,"second":111,"amount":-1},{"first":70,"second":112,"amount":-1},{"first":70,"second":113,"amount":-1},{"first":70,"second":114,"amount":-1},{"first":70,"second":117,"amount":-1},{"first":68,"second":34,"amount":-1},{"first":68,"second":38,"amount":-1},{"first":68,"second":39,"amount":-1},{"first":68,"second":41,"amount":-1},{"first":68,"second":42,"amount":-1},{"first":68,"second":44,"amount":-1},{"first":68,"second":46,"amount":-1},{"first":68,"second":47,"amount":-1},{"first":68,"second":65,"amount":-1},{"first":68,"second":84,"amount":-1},{"first":68,"second":86,"amount":-1},{"first":68,"second":89,"amount":-1},{"first":68,"second":90,"amount":-1},{"first":68,"second":92,"amount":-1},{"first":68,"second":93,"amount":-1},{"first":68,"second":125,"amount":-1},{"first":67,"second":45,"amount":-2},{"first":65,"second":34,"amount":-3},{"first":65,"second":39,"amount":-3},{"first":65,"second":42,"amount":-3},{"first":65,"second":45,"amount":-1},{"first":65,"second":63,"amount":-1},{"first":65,"second":64,"amount":-1},{"first":65,"second":67,"amount":-1},{"first":65,"second":71,"amount":-1},{"first":65,"second":74,"amount":1},{"first":65,"second":79,"amount":-1},{"first":65,"second":81,"amount":-1},{"first":65,"second":84,"amount":-3},{"first":65,"second":85,"amount":-1},{"first":65,"second":86,"amount":-3},{"first":65,"second":87,"amount":-2},{"first":65,"second":89,"amount":-3},{"first":65,"second":92,"amount":-3},{"first":65,"second":118,"amount":-2},{"first":65,"second":121,"amount":-2},{"first":102,"second":34,"amount":1},{"first":102,"second":39,"amount":1},{"first":102,"second":42,"amount":1},{"first":102,"second":44,"amount":-2},{"first":102,"second":46,"amount":-2},{"first":121,"second":38,"amount":-2},{"first":121,"second":44,"amount":-2},{"first":121,"second":46,"amount":-2},{"first":121,"second":47,"amount":-2},{"first":121,"second":65,"amount":-2},{"first":121,"second":99,"amount":-1},{"first":121,"second":100,"amount":-1},{"first":121,"second":101,"amount":-1},{"first":121,"second":111,"amount":-1},{"first":121,"second":113,"amount":-1},{"first":112,"second":34,"amount":-2},{"first":112,"second":39,"amount":-2},{"first":112,"second":41,"amount":-1},{"first":112,"second":42,"amount":-2},{"first":112,"second":86,"amount":-2},{"first":112,"second":87,"amount":-1},{"first":112,"second":92,"amount":-2},{"first":112,"second":93,"amount":-1},{"first":112,"second":118,"amount":-1},{"first":112,"second":120,"amount":-1},{"first":112,"second":121,"amount":-1},{"first":112,"second":125,"amount":-1},{"first":120,"second":99,"amount":-1},{"first":120,"second":100,"amount":-1},{"first":120,"second":101,"amount":-1},{"first":120,"second":111,"amount":-1},{"first":120,"second":113,"amount":-1},{"first":119,"second":44,"amount":-1},{"first":119,"second":46,"amount":-1},{"first":118,"second":38,"amount":-2},{"first":118,"second":44,"amount":-2},{"first":118,"second":46,"amount":-2},{"first":118,"second":47,"amount":-2},{"first":118,"second":65,"amount":-2},{"first":118,"second":99,"amount":-1},{"first":118,"second":100,"amount":-1},{"first":118,"second":101,"amount":-1},{"first":118,"second":111,"amount":-1},{"first":118,"second":113,"amount":-1},{"first":114,"second":44,"amount":-2},{"first":114,"second":46,"amount":-2},{"first":110,"second":34,"amount":-1},{"first":110,"second":39,"amount":-1},{"first":110,"second":42,"amount":-1},{"first":110,"second":118,"amount":-1},{"first":110,"second":121,"amount":-1},{"first":109,"second":34,"amount":-1},{"first":109,"second":39,"amount":-1},{"first":109,"second":42,"amount":-1},{"first":109,"second":118,"amount":-1},{"first":109,"second":121,"amount":-1},{"first":101,"second":34,"amount":-2},{"first":101,"second":39,"amount":-2},{"first":101,"second":41,"amount":-1},{"first":101,"second":42,"amount":-2},{"first":101,"second":86,"amount":-2},{"first":101,"second":87,"amount":-1},{"first":101,"second":92,"amount":-2},{"first":101,"second":93,"amount":-1},{"first":101,"second":118,"amount":-1},{"first":101,"second":120,"amount":-1},{"first":101,"second":121,"amount":-1},{"first":101,"second":125,"amount":-1},{"first":97,"second":34,"amount":-1},{"first":97,"second":39,"amount":-1},{"first":97,"second":42,"amount":-1},{"first":97,"second":118,"amount":-1},{"first":97,"second":121,"amount":-1},{"first":111,"second":34,"amount":-2},{"first":111,"second":39,"amount":-2},{"first":111,"second":41,"amount":-1},{"first":111,"second":42,"amount":-2},{"first":111,"second":86,"amount":-2},{"first":111,"second":87,"amount":-1},{"first":111,"second":92,"amount":-2},{"first":111,"second":93,"amount":-1},{"first":111,"second":118,"amount":-1},{"first":111,"second":120,"amount":-1},{"first":111,"second":121,"amount":-1},{"first":111,"second":125,"amount":-1},{"first":42,"second":38,"amount":-3},{"first":42,"second":44,"amount":-3},{"first":42,"second":45,"amount":-3},{"first":42,"second":46,"amount":-3},{"first":42,"second":47,"amount":-3},{"first":42,"second":64,"amount":-1},{"first":42,"second":65,"amount":-3},{"first":42,"second":67,"amount":-1},{"first":42,"second":71,"amount":-1},{"first":42,"second":79,"amount":-1},{"first":42,"second":81,"amount":-1},{"first":42,"second":86,"amount":1},{"first":42,"second":87,"amount":1},{"first":42,"second":89,"amount":1},{"first":42,"second":92,"amount":1},{"first":42,"second":97,"amount":-1},{"first":42,"second":99,"amount":-2},{"first":42,"second":100,"amount":-2},{"first":42,"second":101,"amount":-2},{"first":42,"second":111,"amount":-2},{"first":42,"second":113,"amount":-2},{"first":44,"second":34,"amount":-3},{"first":44,"second":39,"amount":-3},{"first":44,"second":42,"amount":-3},{"first":44,"second":45,"amount":-2},{"first":44,"second":64,"amount":-1},{"first":44,"second":67,"amount":-1},{"first":44,"second":71,"amount":-1},{"first":44,"second":79,"amount":-1},{"first":44,"second":81,"amount":-1},{"first":44,"second":84,"amount":-3},{"first":44,"second":86,"amount":-3},{"first":44,"second":87,"amount":-2},{"first":44,"second":89,"amount":-3},{"first":44,"second":92,"amount":-3},{"first":44,"second":118,"amount":-2},{"first":44,"second":119,"amount":-1},{"first":44,"second":121,"amount":-2},{"first":39,"second":38,"amount":-3},{"first":39,"second":44,"amount":-3},{"first":39,"second":45,"amount":-3},{"first":39,"second":46,"amount":-3},{"first":39,"second":47,"amount":-3},{"first":39,"second":64,"amount":-1},{"first":39,"second":65,"amount":-3},{"first":39,"second":67,"amount":-1},{"first":39,"second":71,"amount":-1},{"first":39,"second":79,"amount":-1},{"first":39,"second":81,"amount":-1},{"first":39,"second":86,"amount":1},{"first":39,"second":87,"amount":1},{"first":39,"second":89,"amount":1},{"first":39,"second":92,"amount":1},{"first":39,"second":97,"amount":-1},{"first":39,"second":99,"amount":-2},{"first":39,"second":100,"amount":-2},{"first":39,"second":101,"amount":-2},{"first":39,"second":111,"amount":-2},{"first":39,"second":113,"amount":-2},{"first":34,"second":38,"amount":-3},{"first":34,"second":44,"amount":-3},{"first":34,"second":45,"amount":-3},{"first":34,"second":46,"amount":-3},{"first":34,"second":47,"amount":-3},{"first":34,"second":64,"amount":-1},{"first":34,"second":65,"amount":-3},{"first":34,"second":67,"amount":-1},{"first":34,"second":71,"amount":-1},{"first":34,"second":79,"amount":-1},{"first":34,"second":81,"amount":-1},{"first":34,"second":86,"amount":1},{"first":34,"second":87,"amount":1},{"first":34,"second":89,"amount":1},{"first":34,"second":92,"amount":1},{"first":34,"second":97,"amount":-1},{"first":34,"second":99,"amount":-2},{"first":34,"second":100,"amount":-2},{"first":34,"second":101,"amount":-2},{"first":34,"second":111,"amount":-2},{"first":34,"second":113,"amount":-2},{"first":46,"second":34,"amount":-3},{"first":46,"second":39,"amount":-3},{"first":46,"second":42,"amount":-3},{"first":46,"second":45,"amount":-2},{"first":46,"second":64,"amount":-1},{"first":46,"second":67,"amount":-1},{"first":46,"second":71,"amount":-1},{"first":46,"second":79,"amount":-1},{"first":46,"second":81,"amount":-1},{"first":46,"second":84,"amount":-3},{"first":46,"second":86,"amount":-3},{"first":46,"second":87,"amount":-2},{"first":46,"second":89,"amount":-3},{"first":46,"second":92,"amount":-3},{"first":46,"second":118,"amount":-2},{"first":46,"second":119,"amount":-1},{"first":46,"second":121,"amount":-2},{"first":45,"second":34,"amount":-3},{"first":45,"second":38,"amount":-1},{"first":45,"second":39,"amount":-3},{"first":45,"second":42,"amount":-3},{"first":45,"second":44,"amount":-2},{"first":45,"second":46,"amount":-2},{"first":45,"second":47,"amount":-1},{"first":45,"second":65,"amount":-1},{"first":45,"second":84,"amount":-3},{"first":45,"second":86,"amount":-2},{"first":45,"second":87,"amount":-1},{"first":45,"second":88,"amount":-1},{"first":45,"second":89,"amount":-3},{"first":45,"second":90,"amount":-1},{"first":45,"second":92,"amount":-2}],"info":{"face":"Lato Black","size":32,"bold":0,"italic":0,"charset":"","unicode":0,"stretchH":100,"smooth":1,"aa":1,"padding":[4,4,4,4],"spacing":[-8,-8]},"common":{"lineHeight":39,"base":32,"scaleW":512,"scaleH":512,"pages":1,"packed":0}}
--------------------------------------------------------------------------------
/demo/sdf/LatoBlack-sdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattdesl/gl-sprite-text/d9cac3c5413e591d54115e8b4f4a31ed5cd32bdf/demo/sdf/LatoBlack-sdf.png
--------------------------------------------------------------------------------
/demo/sdf/dummy.txt:
--------------------------------------------------------------------------------
1 | One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. "What's happened to me?" he thought. It wasn't a dream. His room, a proper human room although a little too small, lay peacefully between its four familiar walls. A collection of textile samples lay spread out on the table - Samsa was a travelling salesman - and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame.
--------------------------------------------------------------------------------
/demo/sdf/frag.glsl:
--------------------------------------------------------------------------------
1 | #ifdef GL_ES
2 | precision mediump float;
3 | #endif
4 |
5 | varying vec4 v_col;
6 | varying vec2 v_tex0;
7 | uniform sampler2D texture0;
8 | uniform vec4 tint;
9 |
10 | const float smoothing = 1.0/16.0;
11 | const vec2 shadowOffset = vec2(-1.0/512.0);
12 | const vec4 glowColor = vec4(vec3(0.1), 1.0);
13 | const float glowMin = 0.2;
14 | const float glowMax = 0.8;
15 |
16 | // drop shadow computed in fragment shader
17 | void main() {
18 | vec4 texColor = texture2D(texture0, v_tex0);
19 | float dst = texColor.a;
20 | float alpha = smoothstep(0.5 - smoothing, 0.5 + smoothing, dst);
21 |
22 | float glowDst = texture2D(texture0, v_tex0 + shadowOffset).a;
23 | vec4 glow = glowColor * smoothstep(glowMin, glowMax, glowDst);
24 |
25 | float mask = 1.0-alpha;
26 |
27 | vec4 base = v_col * vec4(vec3(1.0), alpha) * tint;
28 | gl_FragColor = mix(base, glow, mask);
29 | }
--------------------------------------------------------------------------------
/demo/sdf/vert.glsl:
--------------------------------------------------------------------------------
1 | attribute vec4 position;
2 | attribute vec4 color;
3 | attribute vec2 texcoord0;
4 | uniform mat4 projection;
5 | uniform mat4 view;
6 | varying vec4 v_col;
7 | varying vec2 v_tex0;
8 |
9 | void main() {
10 | gl_Position = projection * view * position;
11 | v_col = color;
12 | v_tex0 = texcoord0;
13 | gl_PointSize = 1.0;
14 | }
--------------------------------------------------------------------------------
/demo/simple.js:
--------------------------------------------------------------------------------
1 | require('canvas-testbed')(render, start, { context: 'webgl' })
2 |
3 | var createText = require('../')
4 | var createShader = require('gl-basic-shader')
5 |
6 | var clear = require('gl-clear')({ color: [0,0,0,1] })
7 |
8 | var Lato = require('bmfont-lato/32')
9 | var mat4 = require('gl-mat4')
10 |
11 | var text,
12 | ortho = mat4.create(),
13 | translate = mat4.create(),
14 | shader,
15 | time = 0
16 |
17 | function render(gl, width, height, dt) {
18 | time += dt/1000
19 | clear(gl)
20 |
21 | //this is necessary since our image is semi-transparent!
22 | gl.enable(gl.BLEND)
23 | gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
24 |
25 | mat4.ortho(ortho, 0, width, height, 0, 0, 1)
26 |
27 | //gl-basic-shader gives us some matrices we can use
28 | shader.bind()
29 | shader.uniforms.projection = ortho
30 |
31 | //We aren't handling retina here, so it will look pretty
32 | //bad on high density screens.
33 | text.letterSpacing = (Math.sin(time)/2+0.5)*20
34 | text.lineHeight = (Math.sin(time)/2+0.5)*text.fontSize
35 |
36 | //get bounds of text after we've adjusted all its params
37 | var bounds = text.getBounds()
38 |
39 | //here we're translating the text in a shader
40 | mat4.identity(translate)
41 | mat4.translate(translate, translate, [10, 10-bounds.y, 0])
42 | shader.uniforms.model = translate
43 |
44 | //Draws from upper-left corner of text box.
45 | text.draw(shader)
46 | }
47 |
48 | function start(gl, width, height) {
49 | //build our text
50 | text = createText(gl, {
51 | font: Lato,
52 | text: 'Hello, World! Some\nmulti-line text for you.',
53 | //we can word-wrap like so:
54 | // wrapWidth: 140
55 | })
56 |
57 | //a shader with vertex colors and uv coords
58 | shader = createShader(gl, {
59 | color: true,
60 | texcoord: true
61 | })
62 | }
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var Base = require('fontpath-simple-renderer')
2 | var inherits = require('inherits')
3 | var bmfont2fontpath = require('fontpath-bmfont')
4 | var texcoord = require('texcoord')
5 | var xtend = require('xtend')
6 | var createTexture = require('gl-texture2d')
7 |
8 | var Batch = require('gl-sprite-batch')
9 |
10 | var tmpPos = [0, 0],
11 | tmpShape = [0, 0],
12 | tmp1 = [0, 0],
13 | tmp2 = [0, 0]
14 | var DEFAULT_TEXCOORD = [0, 0, 1, 1]
15 | var maxInitialCapacity = 500
16 |
17 | function texcoordGlyph(glyph, atlas, out) {
18 | tmp1[0] = glyph.x
19 | tmp1[1] = glyph.y
20 | tmp2[0] = glyph.width
21 | tmp2[1] = glyph.height
22 | return texcoord(tmp1, tmp2, atlas, out)
23 | }
24 |
25 | function TextRenderer(gl, opt) {
26 | if (!(this instanceof TextRenderer))
27 | return new TextRenderer(gl, opt)
28 | opt = opt||{}
29 |
30 | if (!opt.font)
31 | throw new Error('must specify bmfont at creation time')
32 |
33 | //if the font has Image/ndarray array
34 | if (!opt.textures && Array.isArray(opt.font.images)) {
35 | opt.textures = opt.font.images.map(function(img) {
36 | return createTexture(gl, img)
37 | })
38 | }
39 |
40 | opt.font = bmfont2fontpath(opt.font)
41 |
42 | Base.call(this, opt)
43 |
44 | this.textures = opt.textures || []
45 | this.gl = gl
46 | if (!gl)
47 | throw new Error("must specify gl context")
48 |
49 | //assume text will be used dynamically
50 | if (typeof opt.dynamic !== 'boolean')
51 | opt.dynamic = true
52 |
53 | var batch = opt.batch
54 | if (!batch)
55 | this.defaultBatch = Batch(gl, opt)
56 | this.batch = batch || this.defaultBatch
57 |
58 | if (typeof opt.wrapWidth !== 'number')
59 | this.layout()
60 | }
61 |
62 | inherits(TextRenderer, Base)
63 |
64 | TextRenderer.prototype.dispose = function(textures) {
65 | if (this.defaultBatch)
66 | this.defaultBatch.dispose()
67 | if (textures) {
68 | this.textures.forEach(function(t) {
69 | if (typeof t.dispose === 'function')
70 | t.dispose()
71 | })
72 | }
73 | return this
74 | }
75 |
76 | TextRenderer.prototype.uncache = function() {
77 | this._cache = false
78 | this.batch.clear()
79 | return this
80 | }
81 |
82 | TextRenderer.prototype.cache = function(x, y, start, end) {
83 | // if (this.underline || this.font.pages.length > 1)
84 | // throw new Error('currently cached text does not support underlines or multiple texture pages')
85 |
86 | this._cache = true
87 | this.batch.ensureCapacity(this.text.length)
88 | this.batch.clear()
89 | this._build(x, y, start, end)
90 | return this
91 | }
92 |
93 | TextRenderer.prototype.draw = function(shader, x, y, start, end) {
94 | var batch = this.batch
95 | batch.bind(shader)
96 |
97 | //if we're drawing dynamically
98 | if (!this._cache) {
99 | batch.clear()
100 | this._build(x, y, start, end)
101 | }
102 |
103 | batch.draw()
104 | batch.unbind()
105 | return this
106 | }
107 |
108 | TextRenderer.prototype._build = function(x, y, start, end) {
109 | var result = this.render(x, y, start, end)
110 |
111 | var batch = this.batch
112 | var i = 0
113 |
114 | //underlines currently not supported with cache()
115 | if (!this._cache) {
116 | batch.texcoord = DEFAULT_TEXCOORD
117 | batch.texture = null
118 |
119 | for (i = 0; i < result.underlines.length; i++) {
120 | var underline = result.underlines[i]
121 | batch.position = underline.position
122 | batch.shape = underline.size
123 | batch.push()
124 | }
125 | }
126 |
127 | //now draw our glyphs into the batch...
128 | for (i = 0; i < result.glyphs.length; i++) {
129 | var g = result.glyphs[i]
130 | this._drawGlyph(batch, g)
131 | }
132 | }
133 |
134 | TextRenderer.prototype._drawGlyph = function(batch, data) {
135 | //... we could sort these by texture page to reduce draws
136 | var glyph = data.glyph
137 | var img = this.textures[glyph.page]
138 | tmpPos[0] = data.position[0]+glyph.hbx
139 | tmpPos[1] = data.position[1]+glyph.hby - this.font.descender
140 | tmpShape[0] = glyph.width * data.scale[0]
141 | tmpShape[1] = glyph.height * data.scale[1]
142 |
143 | batch.texture = img
144 | texcoordGlyph(glyph, img && img.shape, batch.texcoord)
145 | batch.position = tmpPos
146 | batch.shape = tmpShape
147 | batch.push()
148 | }
149 |
150 | module.exports = TextRenderer
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gl-sprite-text",
3 | "version": "2.3.1",
4 | "description": "fontpath renderer for bitmap fonts in webgl",
5 | "main": "index.js",
6 | "license": "MIT",
7 | "author": {
8 | "name": "Matt DesLauriers",
9 | "email": "dave.des@gmail.com",
10 | "url": "https://github.com/mattdesl"
11 | },
12 | "dependencies": {
13 | "fontpath-bmfont": "^1.0.0",
14 | "fontpath-simple-renderer": "^4.0.0",
15 | "gl-sprite-batch": "^3.1.0",
16 | "gl-texture2d": "^2.0.8",
17 | "inherits": "^2.0.1",
18 | "texcoord": "^1.0.2",
19 | "xtend": "^4.0.0"
20 | },
21 | "devDependencies": {
22 | "as-number": "^1.0.0",
23 | "beefy": "^2.1.1",
24 | "bluebird": "^2.3.5",
25 | "bmfont-lato": "^2.0.0",
26 | "brfs": "^1.2.0",
27 | "browserify": "^8.1.0",
28 | "canvas-testbed": "^1.0.2",
29 | "eases": "^1.0.2",
30 | "gl-basic-shader": "^1.2.2",
31 | "gl-checker-background": "^1.0.0",
32 | "gl-clear": "0.0.1",
33 | "gl-mat4": "^1.0.0",
34 | "gl-texture2d": "^2.0.7",
35 | "gl-textured-quad": "^1.0.4",
36 | "img": "0.0.1",
37 | "lerp": "^1.0.0",
38 | "ndarray": "^1.0.15",
39 | "smoothstep": "^1.0.1",
40 | "uglify-js": "^2.4.16",
41 | "xtend": "^4.0.0"
42 | },
43 | "scripts": {
44 | "test": "node test.js",
45 | "demo": "beefy demo/index.js --open --cwd demo",
46 | "demo-sdf": "beefy demo/sdf.js --cwd demo --open -- -t brfs -t glslify",
47 | "demo-simple": "beefy demo/simple.js --open --cwd demo",
48 | "build": "browserify demo/index.js | uglifyjs -cm > demo/js/bundle.js",
49 | "build-sdf": "browserify demo/sdf.js -t brfs -t glslify | uglifyjs -cm > demo/js/sdf-bundle.js"
50 | },
51 | "keywords": [
52 | "fontpath",
53 | "font",
54 | "text",
55 | "sprite",
56 | "bmfont",
57 | "bitmap",
58 | "bitmapfont"
59 | ],
60 | "repository": {
61 | "type": "git",
62 | "url": "git://github.com/mattdesl/gl-sprite-text.git"
63 | },
64 | "homepage": "https://github.com/mattdesl/gl-sprite-text",
65 | "bugs": {
66 | "url": "https://github.com/mattdesl/gl-sprite-text/issues"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------