├── .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 | [![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges) 4 | 5 | ![text](http://i.imgur.com/P5zUbNo.png) 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 | [![NPM](https://nodei.co/npm/gl-sprite-text.png)](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 | --------------------------------------------------------------------------------