Repository: cmiscm/leonsans Branch: master Commit: f8c03c92d805 Files: 48 Total size: 309.1 KB Directory structure: gitextract_04kbmd_5/ ├── .gitignore ├── LICENSE ├── README.md ├── dist/ │ └── leon.js ├── examples/ │ ├── all.html │ ├── canvas-basic.html │ ├── color-pattern.html │ ├── colorful.html │ ├── gradient.html │ ├── grid.html │ ├── index.html │ ├── js/ │ │ └── util.js │ ├── mask-tiling-pixi.html │ ├── metaball-pixi.html │ ├── morphing-pixi.html │ ├── pattern.html │ ├── plants-pixi.html │ ├── wave.html │ └── webgl-basic-pixi.html └── src/ ├── core/ │ ├── align.js │ ├── dispatcher.js │ ├── group.js │ ├── guide.js │ ├── length.js │ ├── model.js │ ├── paths.js │ ├── point.js │ ├── util.js │ └── vector.js ├── draw/ │ ├── canvas/ │ │ ├── color.js │ │ ├── colorful.js │ │ ├── grids.js │ │ ├── lines.js │ │ ├── pattern.js │ │ ├── points.js │ │ └── wave.js │ └── pixi/ │ ├── color.js │ └── lines.js ├── font/ │ ├── index.js │ ├── latin.js │ ├── latinutil.js │ ├── lower.js │ ├── number.js │ ├── special.js │ ├── upper.js │ └── util.js ├── index.js └── leonsans.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ examples/.DS_Store examples/data/.DS_Store ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019 Jongmin Kim Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Leon Sans Leon Sans is a geometric sans-serif typeface made with code in 2019 by Jongmin Kim. It allows to change font weight dynamically and to create custom animations, effects or shapes in the Canvas element of HTML5. He designed the font to celebrate his newborn baby Leon. There are live examples at https://leon-kim.com/examples/ And website at https://leon-kim.com/ [![Video Label](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/leon-youtube.jpg)](https://youtu.be/sb7v-d-R11E?hl=en&fs=1&cc_load_policy=1) ![uppercase](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/upper.gif) ![lowercase](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/lower.gif) ![number](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/number-special.gif) ![latin upper](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/latin-upper.gif) ![latin lower](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/latin-lower.gif) ## What is special? The font is made with code, it has coordinate values of the drawing points for each glyph. With the coordinate values, you can create custom shapes, effects or animations. ![Drawing animation](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/drawing.gif) - [Drawing animation](https://leon-kim.com/examples/#canvas-basic) ![Weight change](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/weight.gif) - [Weight change](https://leon-kim.com/examples/#canvas-basic) ![Wave](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/wave.gif) - [Wave](https://leon-kim.com/examples/#wave) ![Metaball](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/metaball.gif) - [Metaball](https://leon-kim.com/examples/#metaball-pixi) ![Plant](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/plant.gif) - [Plant](https://leon-kim.com/examples/#plants-pixi) ![Colorful](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/colorful.gif) - [Colorful](https://leon-kim.com/examples/#colorful) ![Color pattern](https://raw.githubusercontent.com/cmiscm/leonsans/gh-pages/screenshot/colorpattern.gif) - [Color pattern](https://leon-kim.com/examples/#color-pattern) ## Usage Download the minified js file in dist folder and include it in your html. ```html ``` Generate LeonSans and draw it in the Canvas element of HTML5. ```javascript let leon, canvas, ctx; const sw = 800; const sh = 600; const pixelRatio = 2; function init() { canvas = document.createElement('canvas'); document.body.appendChild(canvas); ctx = canvas.getContext("2d"); canvas.width = sw * pixelRatio; canvas.height = sh * pixelRatio; canvas.style.width = sw + 'px'; canvas.style.height = sh + 'px'; ctx.scale(pixelRatio, pixelRatio); leon = new LeonSans({ text: 'The quick brown\nfox jumps over\nthe lazy dog', color: ['#000000'], size: 80, weight: 200 }); requestAnimationFrame(animate); } function animate(t) { requestAnimationFrame(animate); ctx.clearRect(0, 0, sw, sh); const x = (sw - leon.rect.w) / 2; const y = (sh - leon.rect.h) / 2; leon.position(x, y); leon.draw(ctx); } window.onload = () => { init(); }; ``` For the drawing animation, include TweenMax (JS animation library) in your html. ```html ``` And update all the drawing values from 0 to 1 ```javascript let i, total = leon.drawing.length; for (i = 0; i < total; i++) { TweenMax.fromTo(leon.drawing[i], 1.6, { value: 0 }, { delay: i * 0.05, value: 1, ease: Power4.easeOut }); } ``` ### Option list | Name | Type | Description | | -------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | string | The text that needs to be shown. | | `size` | integer | The size of the text. | | `weight` | number | The weight of the font: `1 - 900`. [Default: `1`] | | `color` | array | The colors of each characters. [Default: `['#000000']`] | | `colorful` | array | The colors for colorful effect. [Default: `['#c5d73f', '#9d529c', '#49a9db', '#fec330', '#5eb96e', '#fc5356', '#f38f31']`] | | `tracking` | integer | The spacing between the characters of a block of text. [Default: `0`] | | `leading` | integer | The distance between each line of text. [Default: `0`] | | `align` | string | How the text content of the element is horizontally aligned: `left, center, right`. [Default: `left`] | | `pathGap` | number | The gap between each coordinate of the points on a line of each character: `0 - 1`. [Default: `0.5`] | | `amplitude` | number | The amplitude of the wave effect: `0 - 1`. [Default: `0.5`] | | `maxWidth` | number | The width of the text sentence. | | `breakWord` | boolean | Words break when reaching the end of a line. [Default: `false`] | | `fps` | number | The FPS for the wave effect. [Default: `30`] | | `isPath` | boolean | `true` to get the coordinate values of the points on a line of each character. [Default: `false`] | | `isWave` | boolean | `true` for the wave effect. [Default: `false`] | ### Properties | Name | Type | Description | | -------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `lineWidth` | number | The thickness of lines of the character. | | `scale` | number | The scale of the character. `scale` is `1` when the font size is `500`. | | `drawing` | array | The drawing object values for each character. `0` is the beginning of the animation, `1` is the end of the animation state. | | `data` | array | An object of the raw data for the text. | | `paths` | array | The coordinate values of the points on a line of each character. | | `drawingPaths` | array | The coordinate values of the points on a line of each character to draw the drawing animation in WebGL. It has 1px distance of each path. | | `wavePaths` | array | The coordinate values of the points on a line for the wave effect. | | `rect` | Object | The size of the text and its position: `{x: x position, y: y position, w: width, h: height}`.| ### Methods | Name | Description | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `on()` | Add `update` event. | | `off()` | Remove `update` event. | | `position(x, y)` | Set the position of the text. | | `updateDrawingPaths()` | Update paths for drawing in WebGL (PIXI.js). It's very expensive, only call when it needs. | | `drawPixi(graphics)` | Draw text in WebGL with PIXI.js. | | `draw(ctx)` | Draw text in the Canvas element. | | `drawColorful(ctx)` | Draw the colorful effect. | | `wave(ctx, t)` | Draw the wave effect. | | `pattern(ctx, w, h)` | Draw rectangle shapes at each path point | | `grid(ctx)` | Draw grid for each type. | | `point(ctx)` | Draw circles at each drawing point and lines for each type. | | `box(ctx)` | Draw outline box for the text. | | `reset()` | Reset all the values. | | `dispose()` | Dispose. | ================================================ FILE: dist/leon.js ================================================ /*! * VERSION: 1.6.5 * DATE: 2020-09-20 * https://leon-sans.com * * @license Copyright (c) 2019-2020, Jongmin Kim. All rights reserved. **/ var LeonSans=function(t){var r={};function i(e){if(r[e])return r[e].exports;var a=r[e]={i:e,l:!1,exports:{}};return t[e].call(a.exports,a,a.exports,i),a.l=!0,a.exports}return i.m=t,i.c=r,i.d=function(t,r,e){i.o(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:e})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,r){if(1&r&&(t=i(t)),8&r)return t;if(4&r&&"object"==typeof t&&t&&t.__esModule)return t;var e=Object.create(null);if(i.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:t}),2&r&&"string"!=typeof t)for(var a in t)i.d(e,a,function(r){return t[r]}.bind(null,a));return e},i.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(r,"a",r),r},i.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},i.p="",i(i.s=0)}([function(t,r,i){var e=i(1).default;t.exports=e},function(t,r,i){"use strict";i.r(r),i.d(r,"default",(function(){return Zt}));var e=1,a=2*Math.PI;function s(t,r){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,e=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,a=.49*t.rect.w*r,s=.49*(t.rect.h+220)*r;return{x:i,y:e,w:a,h:s}}function n(t,r,i){return{x:t/2,y:(r-130*.49*i)/2}}function l(t,r,i){return{r:r,cr:i,fr1:1,fr2:.78,gx1:t.ratio.x1,gx2:t.ratio.x2,gy1:t.ratio.y1,gy2:t.ratio.y2}}function f(t,r,i,e,a){var s=(e-a)/(r-i)*(t-i)+a;return se&&(s=e),s}function o(t){var r,i,e,a,s,n,l,o,h,y,d,c=t.typo.p.length,p=[];for(r=0;r0)for(e=0;e{var i=f(r.drawing.value,r.maxDrawing,r.minDrawing,1,0);if(i>0&&"a"!=r.pos.type){var e=r.lengths*i;t.setLineDash([r.lengths]),t.lineDashOffset=r.direction*(e+r.lengths),t.stroke()}}})}return p}function h(t,r){var i,e,a=t.length,s=[];for(i=0;i0){var o=i*l;t.setLineDash([i]),t.lineDashOffset=r.direction*(o+i),t.stroke()}return n}function T(t,r,i,e){var a,s;if(1==r.drawing.value)for(a=r.lines.length,s=0;s0&&(p[0].start=1,Array.prototype.push.apply(c,p))}return c}function X(t,r,i){var e,a,s,n,l,o,h,y=t.length,d=[],c=1,p=1;for(r>-1&&(p=f(r,1,0,80,10)*i),e=0;e0&&null!=(h=E(l,A,n,o))&&(c&&(h.type="m",c=0),d.push(h)),A=new z(l);return d}function E(t,r,i,e){if(t.type=i.type,t.distance=i.distance,t.num=e,r&&null==t.rotation){var a=t.x-r.x,s=t.y-r.y,n=Math.atan2(a,s);t.rotation=-n}else t.rotation=t.rotation;return t.rotation==V?null:t}function B(t,r){var i=H(t.x1,t.x2,t.x3,t.x4,r),e=H(t.y1,t.y2,t.y3,t.y4,r),a=K(t.x1,t.x2,t.x3,t.x4,r),s=K(t.y1,t.y2,t.y3,t.y4,r);return new z({x:i,y:e,rotation:-Math.atan2(a,s)})}function H(t,r,i,e,a){var s=a*a;return t+(3*-t+a*(3*t-t*a))*a+(3*r+a*(-6*r+3*r*a))*a+(3*i-3*i*a)*s+e*(s*a)}function K(t,r,i,e,a){return 3*a*a*(3*r-t-3*i+e)+6*a*(t-2*r+i)+3*(-t+r)}var Q=Math.PI/180*180,U=Math.PI/180*90,V=-100;function Y(t,r,i,e,a,s,n,l){var f,o=[],h=l.length;for(f=0;f{for(var l=[],f=0;f":Y(423,90,352,0,0,0,0,[{d:-1,v:[["m",0,0,{x:-1,y:.3,r:$(0,0,90,176)}],["l",90,176,{r:Q,f:1}],["l",0,352,{x:-1,y:.3,f:1}]]}]),"/":Y(433,130,352,0,0,0,0,[{d:1,v:[["m",0,352,{r:$(0,352,130,0),f:1,y:0}],["l",130,0,{y:0}]]}]),"þ":Y(600,232,338,-10,-2,-117,-117,[{d:-1,v:[["m",0,-106,{y:0}],["l",0,116,{r:V}],["b",0,180.1,51.9,232,116,232,{r:U}],["b",180.1,232,232,180.1,232,116,{r:Q}],["b",232,51.9,180.1,0,116,0,{r:U}],["b",51.9,0,0,51.9,0,116,{r:Q}],["l",0,338,{y:0,f:1}]]}]),"Þ":Y(520,162,352,-5,-70,0,0,[{d:-1,v:[["m",0,0,{x:0,y:0,r:Q}],["l",0,352,{x:0,y:0,r:Q,f:1}]]},{d:1,v:[["m",0,281.6,{x:0,r:U,f:1,p:1}],["l",57,281.6,{x:-.5,r:U,f:1}],["b",115,281.6,162,233.4,162,175.4,{x:-.5,r:Q}],["b",162,117.4,115,70.4,57,70.4,{x:-.5,r:U}],["l",0,70.4,{x:0,r:U,f:1,p:1}]]}]),"ß":Y(596,209,352,-10,-10,0,0,[{d:1,v:[["m",0,348.3,{r:Q,f:1,x:0,y:0}],["l",0,104.3,{x:0}],["b",0,46,36,0,98.9,0,{x:0}],["b",145.2,0,191,27.9,191,81,{x:1}],["b",191,110.7,165.6,131.8,151.8,140.9],["l",140,148.8],["b",120.6,161.7,110.8,172.8,110.8,185.5],["b",110.8,206.7,131.6,213.8,140,217.5],["b",190.6,241.1,211,262.7,211,289.6],["b",211,329.5,174.8,352,142.5,352],["b",97.3,352,75.2,319.7,72.3,289.3]]}])};function kt(t,r){var i=t,e=-60+r;return[{d:-1,v:[["m",-40+i,e,{x:0,y:0,r:$(-40+i,e,0+i,60+e)}],["l",0+i,60+e,{x:0,y:0,f:1}]]}]}function Dt(t,r){var i=t,e=-60+r;return[{d:-1,v:[["m",40+i,e,{x:0,y:0,r:$(40+i,e,0+i,60+e)}],["l",0+i,60+e,{x:0,y:0,f:1}]]}]}function Tt(t,r){var i=-68+t,e=0+r;return[{d:-1,v:[["m",0+i,50+e,{r:$(0+i,50+e,66.5+i,0+e),y:0,x:0}],["l",66.5+i,0+e,{r:$(0+i,50+e,66.5+i,0+e),y:0,x:0,f:1}],["l",69.5+i,0+e,{r:$(69.5+i,0+e,136+i,50+e),y:0,x:0,f:1,v:1}],["l",136+i,50+e,{y:0,x:0,f:1}]]}]}function It(t,r){var i=t-76.24,e=r;return[{d:1,v:[["m",159.52+i,16.56+e,{x:-1,y:-.2,r:tt(159.52+i,16.56+e,150.08+i,29.28+e,134.56+i,37.68+e,118.56+i,37.68+e,0),f:1}],["b",150.08+i,29.28+e,134.56+i,37.68+e,118.56+i,37.68+e,{x:-1,y:-.2,r:U}],["b",103.28+i,37.68+e,89.68+i,29.28+e,76.24+i,20.4+e,{x:-1,y:-.2}],["b",61.44+i,10.56+e,47.28+i,0+e,31.68+i,0+e,{x:-1,y:-.2,r:U}],["b",17.84+i,0+e,8.72+i,7.12+e,0+i,16+e,{x:-1,y:-.2}]]}]}function Rt(t,r){return[{d:1,v:[["a",-50+t,r,{x:0,y:0}]]},{d:1,v:[["a",50+t,r,{x:0,y:0}]]}]}function Ft(t,r){var i=t-57,e=r;return[{d:1,v:[["m",112.7+i,0+e,{r:tt(112.7+i,0+e+i,10.1+e,110.1+i,19.3+e,105+i,27.7+e,0),x:0,y:0,f:1}],["b",112.7+i,10.1+e,110.1+i,19.3+e,105+i,27.7+e,{x:0,y:0}],["b",99.8+i,36.1+e,92.9+i,42.8+e,84.3+i,47.7+e,{x:0,y:0}],["b",75.7+i,52.6+e,66.7+i,55+e,57.3+i,55+e,{x:0,y:0}],["b",47.5+i,55+e,38.3+i,52.6+e,29.6+i,47.7+e,{x:0,y:0}],["b",20.8+i,42.8+e,13.8+i,36.1+e,8.5+i,27.7+e,{x:0,y:0}],["b",3.2+i,19.3+e,.5+i,10.1+e,.5+i,0+e,{x:0,y:0}]]}]}function Mt(t,r){var i=88+t,e=-116+r;return[{d:1,v:[["m",116+i,58+e,{r:Q,p:1,f:1}],["b",116+i,90.05+e,90.05+i,116+e,58+i,116+e,{r:U}],["b",25.95+i,116+e,0+i,90.05+e,0+i,58+e,{r:Q}],["b",0+i,25.95+e,25.95+i,0+e,58+i,0+e,{r:U}],["b",90.05+i,0+e,116+i,25.95+e,116+i,58+e,{r:Q,c:1}]]}]}function Gt(t,r){return[{d:1,v:[["m",t-40,r,{x:0,y:1,r:U}],["l",100+t,r,{x:0,y:1,f:1}]]}]}function zt(t,r){return[{d:-1,v:[["m",t,r,{p:1}],["b",9.3+t,11.6+r,15.6+t,27.1+r,15.6+t,40.9+r],["b",15.6+t,83.3+r,-18.2+t,107.8+r,-59.5+t,107.8+r],["b",-70.9+t,107.8+r,-82.9+t,106.2+r,-93.7+t,102.7+r,{x:.5,f:1}]]}]}function Lt(t,r){return[{d:-1,v:[["m",t,r,{p:1}],["b",-19.6+t,14.8+r,-42.2+t,37.9+r,-42.2+t,64.1+r],["b",-42.2+t,100.3+r,30.2-42.2+t,118.8+r,21.4+t,118.8+r],["b",68.3-42.2+t,118.8+r,72.9-42.2+t,118.4+r,35.2+t,117.6+r,{x:.5,f:1}]]}]}function jt(t,r){return[{d:1,v:[["a",t,r,{x:0,y:0}]]}]}function Ct(t,r){var i=-68+t,e=r;return[{d:-1,v:[["m",0+i,e,{r:$(0+i,e,66.5+i,50+e),y:0,x:0}],["l",66.5+i,50+e,{r:$(0+i,e,66.5+i,50+e),y:0,x:0,f:1}],["l",69.5+i,50+e,{r:$(69.5+i,50+e,136+i,e),y:0,x:0,f:1,v:1}],["l",136+i,e,{y:0,x:0,f:1}]]}]}function At(t,r){return[{d:1,v:[["m",t-50,r,{x:0,y:0}],["l",t+50,r,{x:0,y:0,f:1}]]}]}var qt,Xt,Et=[{d:1,v:[["m",0,352,{y:0,f:1}],["l",0,130,{y:-3}]]}],Bt=[{d:1,v:[["m",-115.9,444,{x:.4,y:.63,r:tt(-115.9,444,12.6-115.9,454.4,29.6-115.9,460.2,-70,461.2,0),f:1}],["b",12.6-115.9,454.4,29.6-115.9,460.2,-70,461.2,{x:.4,y:.63,r:U}],["b",84.5-115.9,463.5,0,435.1,0,396.4,{x:.4,y:.63,r:Q}],["l",0,130,{y:-3}]]}],Ht={"Æ":Y(996,426,352,0,0,0,0,[{d:-1,v:[["m",426,0,{x:0,r:U}],["l",234,0,{x:.5,f:1,r:$(234,0,0,352)}],["l",0,352,{x:.5,y:.5,f:1}]]},{d:-1,v:[["m",234,0,{x:.5,p:1}],["l",234,352,{f:1,x:.5}],["l",426,352,{f:1,x:0}]]},{d:-1,v:[["m",76.4,237,{r:U,p:1}],["l",234,237,{f:1,r:U,p:1}]]},{d:-1,v:[["m",234,164,{r:U,p:1,x:.5}],["l",414,164,{f:1,x:0}]]}]),"æ":Y(1e3,457.5,232,0,0,-64,-64,[{d:-1,v:[["m",232,8,{y:-3.4,r:Q}],["l",232,116,{r:V}],["b",232,180.1,180.1,232,116,232,{r:U}],["b",51.9,232,0,180.1,0,116,{r:Q}],["b",0,51.9,51.9,0,116,0,{r:U}],["b",180.1,0,232,51.9,232,116,{r:Q}],["l",232,224,{y:-.1,r:Q,f:1}]]},{d:1,v:[["m",443.6,182.9,{r:tt(443.6,182.9,423.1,213.2,388.1,233.1,348.5,233.1,0),f:1}],["b",423.1,213.2,388.1,233.1,348.5,233.1,{r:U}],["b",284.4,233.1,232.5,181.2,232.5,117.1,{r:Q}],["b",232.5,53,284.4,1.1,348.5,1.1,{r:U}],["b",408.4,1.1,456.9,47.2,457.5,106.1,{r:Q}],["l",232.5,106.1,{r:Q,p:1}]]}]),"À":Y(620,290,352,0,0,0,0,JSON.parse(JSON.stringify(rt)).concat(kt(145,-50))),"Á":Y(620,290,352,0,0,0,0,JSON.parse(JSON.stringify(rt)).concat(Dt(145,-50))),"Â":Y(620,290,352,0,0,0,0,JSON.parse(JSON.stringify(rt)).concat(Tt(145,-100))),"Ã":Y(620,290,352,0,0,0,0,JSON.parse(JSON.stringify(rt)).concat(It(145,-90))),"Ä":Y(620,290,352,0,0,0,0,JSON.parse(JSON.stringify(rt)).concat(Rt(145,-70))),"Å":Y(620,290,352,0,0,0,0,JSON.parse(JSON.stringify(rt)).concat(Mt(0,0))),"Ă":Y(620,290,352,0,0,0,0,JSON.parse(JSON.stringify(rt)).concat(Ft(145,-110))),"Ą":Y(620,290,352,0,0,0,0,JSON.parse(JSON.stringify(rt)).concat(Lt(290,352))),"à":Y(600,232,232,10,2,-64,-64,JSON.parse(JSON.stringify(vt)).concat(kt(116,-60))),"á":Y(600,232,232,10,2,-64,-64,JSON.parse(JSON.stringify(vt)).concat(Dt(116,-60))),"â":Y(600,232,232,10,2,-64,-64,JSON.parse(JSON.stringify(vt)).concat(Tt(116,-110))),"ã":Y(600,232,232,10,2,-64,-64,JSON.parse(JSON.stringify(vt)).concat(It(116,-100))),"ä":Y(600,232,232,10,2,-64,-64,JSON.parse(JSON.stringify(vt)).concat(Rt(116,-80))),"å":Y(600,232,232,10,2,-64,-64,JSON.parse(JSON.stringify(vt)).concat(Mt(-30,0))),"ă":Y(600,232,232,10,2,-64,-64,JSON.parse(JSON.stringify(vt)).concat(Ft(116,-120))),"ą":Y(600,232,232,10,2,-64,-64,JSON.parse(JSON.stringify(vt)).concat(Lt(232,224))),"Ć":Y(700,293.1,360,0,0,0,0,JSON.parse(JSON.stringify(it)).concat(kt(180,-60))),"Ĉ":Y(700,293.1,360,0,0,0,0,JSON.parse(JSON.stringify(it)).concat(Tt(180,-110))),"Ċ":Y(700,293.1,360,0,0,0,0,JSON.parse(JSON.stringify(it)).concat(jt(180,-80))),"Č":Y(700,293.1,360,0,0,0,0,JSON.parse(JSON.stringify(it)).concat(Ct(180,-110))),"Ç":Y(700,293.1,360,0,0,0,0,JSON.parse(JSON.stringify(it)).concat(zt(180,360))),"ć":Y(520,212.1,233.1,2,-10,-64,-64,JSON.parse(JSON.stringify(xt)).concat(kt(116.5,-68.9))),"ĉ":Y(520,212.1,233.1,2,-10,-64,-64,JSON.parse(JSON.stringify(xt)).concat(Tt(116.5,-118.9))),"ċ":Y(520,212.1,233.1,2,-10,-64,-64,JSON.parse(JSON.stringify(xt)).concat(jt(116.5,-88.9))),"č":Y(520,212.1,233.1,2,-10,-64,-64,JSON.parse(JSON.stringify(xt)).concat(Ct(116.5,-118.9))),"ç":Y(520,212.1,233.1,2,-10,-64,-64,JSON.parse(JSON.stringify(xt)).concat(zt(116.5,233.1))),"Đ":Y(721,270,352,-10,-10,0,0,JSON.parse(JSON.stringify(et)).concat(Gt(0,176))),"Ď":Y(721,270,352,-10,-10,0,0,JSON.parse(JSON.stringify(et)).concat(Ct(100,-110))),"ď":Y(600,232,352,10,2,0,0,JSON.parse(JSON.stringify(ut)).concat((qt=300,Xt=0,[{d:-1,v:[["m",qt,Xt,{x:0,y:0}],["l",qt,80+Xt,{x:0,y:0,f:1}]]}]))),"đ":Y(600,232,352,10,2,0,0,JSON.parse(JSON.stringify(ut)).concat(Gt(180,40))),"È":Y(520,192,352,-5,-80,0,0,JSON.parse(JSON.stringify(at)).concat(kt(96,-60))),"É":Y(520,192,352,-5,-80,0,0,JSON.parse(JSON.stringify(at)).concat(Dt(96,-60))),"Ê":Y(520,192,352,-5,-80,0,0,JSON.parse(JSON.stringify(at)).concat(Tt(96,-110))),"Ë":Y(520,192,352,-5,-80,0,0,JSON.parse(JSON.stringify(at)).concat(Rt(96,-80))),"Ē":Y(520,192,352,-5,-80,0,0,JSON.parse(JSON.stringify(at)).concat(At(96,-80))),"Ĕ":Y(520,192,352,-5,-80,0,0,JSON.parse(JSON.stringify(at)).concat(Ft(96,-120))),"Ė":Y(520,192,352,-5,-80,0,0,JSON.parse(JSON.stringify(at)).concat(jt(96,-80))),"Ě":Y(520,192,352,-5,-80,0,0,JSON.parse(JSON.stringify(at)).concat(Ct(96,-110))),"è":Y(570,225.5,233.1,0,0,-64,-64,JSON.parse(JSON.stringify(gt)).concat(kt(112,-60))),"é":Y(570,225.5,233.1,0,0,-64,-64,JSON.parse(JSON.stringify(gt)).concat(Dt(112,-60))),"ê":Y(570,225.5,233.1,0,0,-64,-64,JSON.parse(JSON.stringify(gt)).concat(Tt(112,-110))),"ë":Y(570,225.5,233.1,0,0,-64,-64,JSON.parse(JSON.stringify(gt)).concat(Rt(112,-80))),"ē":Y(570,225.5,233.1,0,0,-64,-64,JSON.parse(JSON.stringify(gt)).concat(At(112,-80))),"ĕ":Y(570,225.5,233.1,0,0,-64,-64,JSON.parse(JSON.stringify(gt)).concat(Ft(112,-120))),"ė":Y(570,225.5,233.1,0,0,-64,-64,JSON.parse(JSON.stringify(gt)).concat(jt(112,-90))),"ě":Y(570,225.5,233.1,0,0,-64,-64,JSON.parse(JSON.stringify(gt)).concat(Ct(112,-120))),"Ĝ":Y(840,352,360,0,0,0,0,JSON.parse(JSON.stringify(st)).concat(Tt(180,-110))),"Ğ":Y(840,352,360,0,0,0,0,JSON.parse(JSON.stringify(st)).concat(Ft(180,-120))),"Ġ":Y(840,352,360,0,0,0,0,JSON.parse(JSON.stringify(st)).concat(jt(180,-80))),"Ģ":Y(840,352,360,0,0,0,0,JSON.parse(JSON.stringify(st)).concat(zt(180,360))),"ĝ":Y(600,232,338,10,2,-117,-117,JSON.parse(JSON.stringify(bt)).concat(Tt(116,-118.9))),"ğ":Y(600,232,338,10,2,-117,-117,JSON.parse(JSON.stringify(bt)).concat(Ft(116,-120))),"ġ":Y(600,232,338,10,2,-117,-117,JSON.parse(JSON.stringify(bt)).concat(jt(116,-90))),"ģ":Y(600,232,338,10,2,-117,-117,JSON.parse(JSON.stringify(bt)).concat(Dt(116,-70))),"Ĥ":Y(684,232,352,0,0,0,0,JSON.parse(JSON.stringify(nt)).concat(Tt(116,-110))),"ĥ":Y(520,182,352,0,0,0,0,JSON.parse(JSON.stringify(St)).concat(Tt(91,-110))),"Ì":Y(249,0,352,0,0,0,0,JSON.parse(JSON.stringify(lt)).concat(kt(0,-60))),"Í":Y(249,0,352,0,0,0,0,JSON.parse(JSON.stringify(lt)).concat(Dt(0,-60))),"Î":Y(249,0,352,0,0,0,0,JSON.parse(JSON.stringify(lt)).concat(Tt(0,-110))),"Ï":Y(249,0,352,0,0,0,0,JSON.parse(JSON.stringify(lt)).concat(Rt(0,-80))),"ì":Y(200,0,352,0,0,0,0,JSON.parse(JSON.stringify(Et)).concat(kt(0,70))),"í":Y(200,0,352,0,0,0,0,JSON.parse(JSON.stringify(Et)).concat(Dt(0,70))),"î":Y(200,0,352,0,0,0,0,JSON.parse(JSON.stringify(Et)).concat(Tt(0,10))),"ï":Y(200,0,352,0,0,0,0,JSON.parse(JSON.stringify(Et)).concat(Rt(0,50))),"Ĵ":Y(472,172.5,355.5,10,20,-2,-2,JSON.parse(JSON.stringify(ft)).concat(Tt(172.5,-110))),"ĵ":Y(220,115.9,352,-60,-60,0,0,JSON.parse(JSON.stringify(Bt)).concat(Tt(0,20))),"Ñ":Y(721,250,352,0,0,0,0,JSON.parse(JSON.stringify(ot)).concat(It(125,-100))),"ñ":Y(520,182,352,0,0,0,0,JSON.parse(JSON.stringify(mt)).concat(It(91,30))),"Ò":Y(850,360,360,0,0,0,0,JSON.parse(JSON.stringify(ht)).concat(kt(180,-60))),"Ó":Y(850,360,360,0,0,0,0,JSON.parse(JSON.stringify(ht)).concat(Dt(180,-60))),"Ô":Y(850,360,360,0,0,0,0,JSON.parse(JSON.stringify(ht)).concat(Tt(180,-110))),"Õ":Y(850,360,360,0,0,0,0,JSON.parse(JSON.stringify(ht)).concat(It(180,-100))),"Ö":Y(850,360,360,0,0,0,0,JSON.parse(JSON.stringify(ht)).concat(Rt(180,-80))),"Ø":Y(850,360,360,0,0,0,0,JSON.parse(JSON.stringify(ht)).concat([{d:1,v:[["m",0,360,{r:$(0,360,360,0),f:1,x:0,y:1}],["l",360,0,{x:0,y:1}]]}])),"ò":Y(580,232,232,0,0,-64,-64,JSON.parse(JSON.stringify(Ot)).concat(kt(116,-60))),"ó":Y(580,232,232,0,0,-64,-64,JSON.parse(JSON.stringify(Ot)).concat(Dt(116,-60))),"ô":Y(580,232,232,0,0,-64,-64,JSON.parse(JSON.stringify(Ot)).concat(Tt(116,-110))),"õ":Y(580,232,232,0,0,-64,-64,JSON.parse(JSON.stringify(Ot)).concat(It(116,-100))),"ö":Y(580,232,232,0,0,-64,-64,JSON.parse(JSON.stringify(Ot)).concat(Rt(116,-80))),"ø":Y(580,232,232,0,0,-64,-64,JSON.parse(JSON.stringify(Ot)).concat([{d:1,v:[["m",0,232,{r:$(0,232,232,0),f:1,x:0,y:1}],["l",232,0,{x:0,y:1}]]}])),"Ŝ":Y(560,224,360,0,0,0,0,JSON.parse(JSON.stringify(yt)).concat(Tt(112.4,-110))),"ŝ":Y(400,143.808,231.12,0,0,-64,-64,JSON.parse(JSON.stringify(Jt)).concat(Tt(112.4*.642,-110))),"Ş":Y(560,224,360,0,0,0,0,JSON.parse(JSON.stringify(yt)).concat(zt(110.3,360))),"ş":Y(400,143.808,231.12,0,0,-64,-64,JSON.parse(JSON.stringify(Jt)).concat(zt(70.8126,231.12))),"Ù":Y(712,250,355,0,0,-.5,-.5,JSON.parse(JSON.stringify(dt)).concat(kt(125,-50))),"Ú":Y(712,250,355,0,0,-.5,-.5,JSON.parse(JSON.stringify(dt)).concat(Dt(125,-50))),"Û":Y(712,250,355,0,0,-.5,-.5,JSON.parse(JSON.stringify(dt)).concat(Tt(125,-100))),"Ŭ":Y(712,250,355,0,0,-.5,-.5,JSON.parse(JSON.stringify(dt)).concat(Ft(125,-110))),"Ü":Y(712,250,355,0,0,-.5,-.5,JSON.parse(JSON.stringify(dt)).concat(Rt(125,-70))),"ù":Y(520,182,352,0,0,0,0,JSON.parse(JSON.stringify(Nt)).concat(kt(91,70))),"ú":Y(520,182,352,0,0,0,0,JSON.parse(JSON.stringify(Nt)).concat(Dt(91,70))),"û":Y(520,182,352,0,0,0,0,JSON.parse(JSON.stringify(Nt)).concat(Tt(91,20))),"ŭ":Y(520,182,352,0,0,0,0,JSON.parse(JSON.stringify(Nt)).concat(Ft(91,10))),"ü":Y(520,182,352,0,0,0,0,JSON.parse(JSON.stringify(Nt)).concat(Rt(91,50))),"Ý":Y(673,270,352,0,0,0,0,JSON.parse(JSON.stringify(ct)).concat(Dt(135,-60))),"ý":Y(500,225.5,331.5,10,10,-119,-119,JSON.parse(JSON.stringify(_t)).concat(Dt(116.3,-60))),"ÿ":Y(500,225.5,331.5,10,10,-119,-119,JSON.parse(JSON.stringify(_t)).concat(Rt(116.3,-90)))},Kt=Object.assign({},pt,wt,Pt,Wt,Ht);function Qt(t){var r=(Kt[t]||Kt.tofu).clone();return r.v=t,r}function Ut(t,r,i,e){var a;return a=t.indexOf("\n")>0?t.split("\n"):t.indexOf("\\n")>0?t.split("\\n"):[t],0==i?function(t){var r,i=[],e=t.length;for(r=0;r=i&&(c+=1,d=o.w,p[c]=[]);c+=1}var v=[];for(n=p.length,a=0;a0&&(" "==e[0]&&e.shift()," "==e[e.length-1]&&e.pop(),e.length>0&&v.push(e));return v}(a,r,i):function(t,r,i){var e,a,n,l,f,o,h,y,d,c,p=0,v=0,x=0,u=[];for(y=t.length,f=0;fi&&(p=v,u[x+=1]=[]),u[x].push(a)}x+=1,p=0}y=u.length;var g=[];for(f=0;f0&&g.push(n);return g}(a,r,i)}function Vt(t,r){return{c:(t-r)/2,r:t-r,l:0}}class Yt{constructor(){this.lineWidth_=1,this.drawing_=[],this.data_=null,this.paths_=null,this.lines_=null,this.rect_={x:0,y:0,w:0,h:0},this.align_="left",this.scale_=1,this.fontRatio_=1}get data(){return this.data_}get paths(){return this.paths_}get lines(){return this.lines_}set lines(t){this.lines_=t}get lineWidth(){return this.lineWidth_}get fontRatio(){return this.fontRatio_}get scale(){return this.scale_}get rect(){return this.rect_}get drawing(){return this.drawing_}set align(t){this.align_!=t&&(this.align_=t,this.setPosition())}get align(){return this.align_}position(t,r){return(this.rect_.x!=t||this.rect_.y!=r)&&(this.rect_.x=t,this.rect_.y=r,this.setPosition(),!0)}setPosition(){var t,r,i,e,a=this.data_.length;for(t=0;tt.toString()!==r.toString())}dispatch(t,r){this.handlers_[t].listeners.forEach(t=>{t(r)})}}{constructor(){var{text:t="",size:r=500,weight:i=e,color:a=["#000000"],colorful:s=["#c5d73f","#9d529c","#49a9db","#fec330","#5eb96e","#fc5356","#f38f31"],tracking:n=0,leading:l=0,align:f="left",pathGap:o=.5,amplitude:h=.5,width:y=0,breakWord:d=!1,fps:c=30,isPath:p=!1,isWave:v=!1}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};super(),this.size_=r,this.weight_=i,this.color_=a,this.colorful_=function(t){for(var r,i,e=t.slice(),a=e.length,s=a;s--;)r=Math.random()*a|0,i=e[s],e[s]=e[r],e[r]=i;return e}(s),this.tracking_=n,this.leading_=l,this.pathGap_=o,this.amplitude_=h,this.width_=y,this.breakWord_=d,this.fps_=c,this.fpsTime_=1e3/this.fps_,this.isPath_=p,this.isWave_=v,this.model=new Yt,this.str_=null,this.time_=null,this.isFps_=!1,this.isForceRander_=!1,this.updateID_=0,this.dPathsID_=null,this.pPathsID_=null,this.wPathsID_=null,this.guideID_=null,this.text=t,this.model.align=f}on(t,r){super.on(t,r),this.update()}off(t,r){super.off(t,r)}get text(){return this.str_}set text(t){this.str_!=t&&(this.str_=t,this.update())}get size(){return this.size_}set size(t){this.size_!=t&&(this.size_=t,this.update(),this.isForceRander_=!0)}get weight(){return this.weight_}set weight(t){t900&&(t=900),this.weight_!=t&&(this.weight_=t,this.update(),this.isForceRander_=!0)}get color(){return this.color_}set color(t){this.color_!=t&&(this.color_=t)}get tracking(){return this.tracking_}set tracking(t){this.tracking_!=t&&(this.tracking_=t,this.update(),this.isForceRander_=!0)}get leading(){return this.leading_}set leading(t){this.leading_!=t&&(this.leading_=t,this.update(),this.isForceRander_=!0)}get align(){return this.model.align}set align(t){this.model.align!=t&&(this.model.align=t,this.updateID_++,this.updateSignal())}get pathGap(){return this.pathGap_}set pathGap(t){this.pathGap_!=t&&(this.pathGap_=t,this.updatePatternPaths(!0),this.updateWavePaths(!0),this.isForceRander_=!0)}get amplitude(){return this.amplitude_}set amplitude(t){this.amplitude_=t}get rect(){return this.model.rect}set maxWidth(t){this.width_!=t&&(this.width_=t,this.update())}get maxWidth(){return this.width_}set breakWord(t){this.breakWord_!=t&&(this.breakWord_=t,this.update())}get breakWord(){return this.breakWord_}get isPath(){return this.isPath_}set isPath(t){this.isPath_=t,this.updatePatternPaths(!0)}get isWave(){return this.isWave_}set isWave(t){this.isWave_=t,this.updateWavePaths(!0)}get fps(){return this.fps_}set fps(t){this.fps_=t,this.fpsTime_=1e3/this.fps_}get lineWidth(){return this.model.lineWidth}get scale(){return this.model.scale}get drawing(){return this.model.drawing}get data(){return this.model.data}get paths(){return this.model.paths}get drawingPaths(){return this.model.drawingPaths}get wavePaths(){return this.model.wavePaths}position(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;this.model.position(t,r)&&(this.updateID_++,this.updateSignal())}update(){this.updateID_++,this.model.update(this.str_,this.width_,this.breakWord_,this.weight_,this.size_,this.tracking_,this.leading_),this.isPath_||this.isWave_?(this.updatePatternPaths(),this.updateWavePaths()):this.updateSignal()}updateGuide(){this.guideID_!=this.updateID_&&(this.guideID_=this.updateID_,this.model.updateGuide())}updateDrawingPaths(){this.dPathsID_!=this.updateID_&&(this.dPathsID_=this.updateID_,this.model.updateDrawingPaths())}updatePatternPaths(t){this.isPath_&&(t||this.pPathsID_!=this.updateID_)&&(this.pPathsID_=this.updateID_,this.model.updatePatternPaths(this.pathGap_),this.isForceRander_=!0,this.updateSignal())}updateWavePaths(t){this.isWave_&&(t||this.wPathsID_!=this.updateID_)&&(this.wPathsID_=this.updateID_,this.model.updateWavePaths(this.pathGap_),this.isForceRander_=!0,this.updateSignal())}updateSignal(){this.model.updateLinesForRect(),this.model.updatePathsForRect(),this.dispatch("update",this.model)}reset(){this.size_=500,this.weight_=e,this.color_=["#000000"],this.tracking_=0,this.leading_=0,this.pathGap_=.5,this.amplitude_=.5,this.width_=0,this.breakWord_=!1,this.fps_=30,this.fpsTime_=1e3/this.fps_,this.isPath_=!1,this.isWave_=!1,this.str_=null,this.time_=null,this.isFps_=!1,this.isForceRander_=!1,this.updateID_=0,this.dPathsID_=null,this.pPathsID_=null,this.wPathsID_=null,this.guideID_=null,this.model.reset()}dispose(){this.reset(),this.model=null}drawPixi(t){var r,i,e,a=this.model.data.length;for(r=0;r10&&(k(t),t.beginPath(),h&&t.moveTo(h.x,h.y),t.lineTo(o.x,o.y),c+=D(t,f,d,y,s,c)),h=o):"b"==o.type&&((d=N(h.x,h.y,o.x,o.y,o.x2,o.y2,o.x3,o.y3))/r.scale>10&&(k(t),t.beginPath(),h&&t.moveTo(h.x,h.y),t.bezierCurveTo(o.x,o.y,o.x2,o.y2,o.x3,o.y3),c+=D(t,f,d,y,s,c)),h={x:o.x3,y:o.y3})}(t,this.model,this.colorful_)}wave(t,r){(t.lineWidth=this.lineWidth,r)&&(this.time_||(this.time_=r),r-this.time_>this.fpsTime_||this.isForceRander_?(this.time_=r,this.isFps_=!0):this.isFps_=!1);this.isForceRander_=!1;var i,e,a=this.model.data.length;for(i=0;i Leon Sans - All ================================================ FILE: examples/canvas-basic.html ================================================ Leon Sans - Canvas Basic ================================================ FILE: examples/color-pattern.html ================================================ LeonSans - Color Pattern ================================================ FILE: examples/colorful.html ================================================ Leon Sans - Colorful ================================================ FILE: examples/gradient.html ================================================ Leon Sans - Gradient ================================================ FILE: examples/grid.html ================================================ Leon Sans - Grids ================================================ FILE: examples/index.html ================================================ Leon Sans examples ================================================ FILE: examples/js/util.js ================================================ const pixelRatio = 2; let isDown = false, moveX = 0, moveY = 0, offsetX = 0, offsetY = 0; let canvas, ctx; let renderer, stage; let sw = document.body.clientWidth; let sh = document.body.clientHeight; function generateCanvas() { canvas = document.createElement('canvas'); document.body.appendChild(canvas); ctx = canvas.getContext("2d"); window.addEventListener('resize', canvasResize, false); canvasResize(); moveEvent(canvas); } function canvasResize() { sw = document.body.clientWidth; sh = document.body.clientHeight; canvas.width = sw * pixelRatio; canvas.height = sh * pixelRatio; canvas.style.width = sw + 'px'; canvas.style.height = sh + 'px'; ctx.scale(pixelRatio, pixelRatio); } function generatePixi(bgcolor) { renderer = new PIXI.Renderer({ width: sw, height: sh, antialias: true, transparent: false, autoDensity: true, resolution: pixelRatio,//window.devicePixelRatio > 1 ? 2 : 1, powerPreference: "high-performance", backgroundColor: bgcolor }); document.body.appendChild(renderer.view); stage = new PIXI.Container(); window.addEventListener('resize', pixiResize, false); pixiResize(); moveEvent(renderer.view); } function pixiResize() { sw = document.body.clientWidth; sh = document.body.clientHeight; renderer.resize(sw, sh); } function moveEvent(canvas) { const hammer = new Hammer(canvas); hammer.add(new Hammer.Pan({direction: Hammer.DIRECTION_ALL, threshold: 0})); hammer.on("pan", (e) => { moveX = e.deltaX + offsetX; moveY = e.deltaY + offsetY; if (e.isFinal) { offsetX = moveX; offsetY = moveY; } }); } function getSize(size) { let ratio = Math.sqrt(sw * sw + sh * sh) / 1800; if (ratio > 1) ratio = 1; else if (ratio < 0.5) ratio = 0.5; return size * ratio; } ================================================ FILE: examples/mask-tiling-pixi.html ================================================ Leon Sans - MASK + Tiling PIXI ================================================ FILE: examples/metaball-pixi.html ================================================ Leon Sans - Metaball PIXI ================================================ FILE: examples/morphing-pixi.html ================================================ Leon Sans - Morphing PIXI ================================================ FILE: examples/pattern.html ================================================ Leon Sans - Pattern ================================================ FILE: examples/plants-pixi.html ================================================ Leon Sans - Plants PIXI ================================================ FILE: examples/wave.html ================================================ Leon Sans - Wave ================================================ FILE: examples/webgl-basic-pixi.html ================================================ Leon Sans - WebGL Basic PIXI ================================================ FILE: src/core/align.js ================================================ export function setAlignGapX(sw, tw) { return { c: (sw - tw) / 2, r: sw - tw, l: 0 }; } export function getAlignGapX(align, alignGapX) { if (align == 'center') { return alignGapX.c; } else if (align == 'right') { return alignGapX.r; } else { return alignGapX.l; } } ================================================ FILE: src/core/dispatcher.js ================================================ export class Dispatcher { constructor() { this.handlers_ = { update: { listeners: [] } }; } on(event, callback) { if (typeof callback !== 'function') { console.error(`The listener callback must be a function, the given type is ${typeof callback}`); return false; } if (typeof event !== 'string') { console.error(`The event name must be a string, the given type is ${typeof event}`); return false; } if (this.handlers_[event] === undefined) { this.handlers_[event] = { listeners: [] }; } this.handlers_[event].listeners.push(callback); } off(event, callback) { if (this.handlers_[event] === undefined) { console.error(`This event: ${event} does not exist`); return false; } this.handlers_[event].listeners = this.handlers_[event].listeners.filter(listener => { return listener.toString() !== callback.toString(); }); } dispatch(event, data) { this.handlers_[event].listeners.forEach((listener) => { listener(data); }); } } ================================================ FILE: src/core/group.js ================================================ import { getRect } from './util.js'; import { typo } from '../font/index.js'; export function getTextGroup(text, scale, width, isBreakAll) { let group; if (text.indexOf('\n') > 0) { group = text.split('\n'); } else if (text.indexOf('\\n') > 0) { group = text.split('\\n'); } else { group = [text]; } if (width == 0) return keepAll(group); else if (isBreakAll) return breakAll(group, scale, width); else return breakWord(group, scale, width); } function keepAll(group) { const textGroup = []; const total = group.length; let i; for (i = 0; i < total; i++) { textGroup[i] = group[i].split(''); } return textGroup; } function breakWord(group, scale, width) { let g2, g3, t, m_rect, tw = 0, tw2 = 0, i, j, k, total, j_total, k_total, index = 0; const tg = []; total = group.length; for (i = 0; i < total; i++) { g2 = group[i].split(' '); tg[index] = []; j_total = g2.length; for (j = 0; j < j_total; j++) { tw2 = 0; g3 = g2[j]; k_total = g3.length; for (k = 0; k < k_total; k++) { t = typo(g3[k]); m_rect = getRect(t, scale); tw2 += m_rect.w; } t = typo(' '); m_rect = getRect(t, scale); tw2 += m_rect.w; tw += tw2; if (tw > width) { index += 1; tw = tw2; tg[index] = []; } tg[index].push(g3); } index += 1; tw = 0; } total = tg.length; const textGroup = []; for (i = 0; i < total; i++) { t = tg[i].join(' ').split(''); if (t.length > 0) { textGroup.push(t); } } return textGroup; } function breakAll(group, scale, width) { let t, i, total, j, j_total, m_rect, g2, g3, tw = 0, index = 0, tx = 0; const tg = []; total = group.length; for (i = 0; i < total; i++) { g2 = group[i]; tw = 0; tx = 0; tg[index] = []; j_total = g2.length; for (j = 0; j < j_total; j++) { g3 = g2[j]; t = typo(g3); m_rect = getRect(t, scale); tw += m_rect.w; tg[index].push(g3); if (tw >= width) { index += 1; tw = m_rect.w; tg[index] = []; } } index += 1; } const textGroup = []; total = tg.length; for (i = 0; i < total; i++) { t = tg[i]; if (t.length > 0) { if (t[0] == ' ') t.shift(); if (t[t.length - 1] == ' ') t.pop(); if (t.length > 0) textGroup.push(t); } } return textGroup; } ================================================ FILE: src/core/guide.js ================================================ import { RECT_RATIO } from './util.js'; /** * @name getGuide * @property {Object} - typo data object from 'font/index.js' * @property {Number} - scale * @returns {Object} the guide pos array * @description get a guide pos */ export function getGuide(d, scale) { let guide = [], ggap = 10, i, gvx, gvy; for (i = 0; i < 6; i++) { gvx = (ggap * i) + 20; gvy = (ggap * i) + 90; guide[i] = { x1: (gvx * RECT_RATIO) * scale, x2: ((d.rect.w - (gvx * 2)) * RECT_RATIO) * scale, y1: (gvy * RECT_RATIO) * scale, y2: (((d.rect.h - gvy) * RECT_RATIO) * scale) - ((i * ggap * RECT_RATIO) * scale), }; } return guide; } /** * @name getGuide * @property {Object} - typo data object from 'font/index.js' * @property {Number} - scale * @returns {Object} the guide pos array * @description get a guide pos */ export function getGrid(d, scale) { let grid = [], i, gvy = [98, 340, 815]; for (i = 0; i < 3; i++) { grid[i] = (gvy[i] * RECT_RATIO) * scale; } return grid; } ================================================ FILE: src/core/length.js ================================================ export function getLengths(item, model) { const total = item.typo.p.length; let c, p, arr = [], lt = [], max = 0, i; for (i = 0; i < total; i++) { p = item.typo.p[i]; c = getEachPath(item, p.v, model); max += c.l; arr.push(c.v); lt.push(c.l); } return { max: max, lines: arr, lengths: lt }; } function getEachPath(item, points, model) { const total = points.length; let i, p, line, cp1, cp2, prev, lines = [], length = 0; for (i = 0; i < total; i++) { p = points[i]; line = {}; cp2 = p.convert(item, model); if (i == 0 || p.type == 'a') { line.x1 = cp2.x; line.y1 = cp2.y; line.distance = 0; line.radius = cp2.radius; } else { cp1 = prev.convert(item, model); if (prev.type == 'b') { line.x1 = cp1.x3; line.y1 = cp1.y3; } else { line.x1 = cp1.x; line.y1 = cp1.y; } line.x2 = cp2.x; line.y2 = cp2.y; if (p.type == 'b') { line.x3 = cp2.x2; line.y3 = cp2.y2; line.x4 = cp2.x3; line.y4 = cp2.y3; line.distance = cubicBezierLength(line.x1, line.y1, line.x2, line.y2, line.x3, line.y3, line.x4, line.y4); } else { line.distance = distance(line.x1, line.y1, line.x2, line.y2); } } line.type = p.type; line.rotation = p.ratio.r; line.pat = p.ratio.p; line.fix = p.ratio.f; line.vt = p.ratio.v; lines.push(line); length += line.distance; prev = p; } return { v: lines, l: length }; } export function cubicBezierLength(x1, y1, x2, y2, x3, y3, x4, y4, sampleCount) { const ptCount = sampleCount || 40; let totDist = 0; let lastX = x1; let lastY = y1; let dx, dy, i, pt; for (i = 1; i < ptCount; i++) { pt = cubicQxy(i / ptCount, x1, y1, x2, y2, x3, y3, x4, y4); dx = pt.x - lastX; dy = pt.y - lastY; totDist += Math.sqrt(dx * dx + dy * dy); lastX = pt.x; lastY = pt.y; } dx = x4 - lastX; dy = y4 - lastY; totDist += Math.sqrt(dx * dx + dy * dy); return totDist; } function cubicQxy(t, x1, y1, x2, y2, x3, y3, x4, y4) { x1 += (x2 - x1) * t; x2 += (x3 - x2) * t; x3 += (x4 - x3) * t; x1 += (x2 - x1) * t; x2 += (x3 - x2) * t; y1 += (y2 - y1) * t; y2 += (y3 - y2) * t; y3 += (y4 - y3) * t; y1 += (y2 - y1) * t; y2 += (y3 - y2) * t; return { x: x1 + (x2 - x1) * t, y: y1 + (y2 - y1) * t }; } export function distance(x1, y1, x2, y2) { const a = (x2 - x1), b = (y2 - y1); return Math.sqrt(a * a + b * b); } ================================================ FILE: src/core/model.js ================================================ import { getFontW, getWeightRatio, getCircleRound, getScale, getTracking, getLeading, getFontRatio, getLineW, getRect, getCenter, getRange, getLines, addRectToPaths, } from './util.js'; import { getGuide, getGrid } from './guide.js'; import { getTextGroup } from './group.js'; import { setAlignGapX, getAlignGapX } from './align.js'; import { typo } from '../font/index.js'; import { getLengths } from './length.js'; import { getPaths } from './paths.js'; export class Model { constructor() { this.lineWidth_ = 1; this.drawing_ = []; this.data_ = null; this.paths_ = null; this.lines_ = null; this.rect_ = { x: 0, y: 0, w: 0, h: 0 }; this.align_ = 'left'; this.scale_ = 1; this.fontRatio_ = 1; } get data() { return this.data_; } get paths() { return this.paths_; } get lines() { return this.lines_; } set lines(v) { this.lines_ = v; } get lineWidth() { return this.lineWidth_; } get fontRatio() { return this.fontRatio_; } get scale() { return this.scale_; } get rect() { return this.rect_; } get drawing() { return this.drawing_; } set align(v) { if (this.align_ != v) { this.align_ = v; this.setPosition(); } } get align() { return this.align_; } position(x, y) { if (this.rect_.x != x || this.rect_.y != y) { this.rect_.x = x; this.rect_.y = y; this.setPosition(); return true; } else { return false; } } setPosition() { const total = this.data_.length; let i, d; for (i = 0; i < total; i++) { d = this.data_[i]; d.rect.x = d.originPos.x + this.rect_.x + getAlignGapX(this.align_, d.alignGapX); d.rect.y = d.originPos.y + this.rect_.y; } } updateDrawingPaths() { const total = this.data_.length; let i, d; for (i = 0; i < total; i++) { d = this.data_[i]; d.drawingPaths = addRectToPaths(getPaths(this, d, -1, false), d); } } updatePatternPaths(pathGap) { const total = this.data_.length; let i, d; for (i = 0; i < total; i++) { d = this.data_[i]; d.rawPaths = getPaths(this, d, pathGap, true); } } updateWavePaths(pathGap) { const total = this.data_.length; let i, d; for (i = 0; i < total; i++) { d = this.data_[i]; d.rawWavePaths = getPaths(this, d, pathGap, false); } } updateGuide() { const total = this.data_.length; let i, d; for (i = 0; i < total; i++) { d = this.data_[i]; d.guide = getGuide(d.typo, this.scale); d.grid = getGrid(d.typo, this.scale); } } update(text, width, breakWord, weight, size, tracking, leading) { const fontW = getFontW(weight); const weightRatio = getWeightRatio(fontW); const circleRound = getCircleRound(fontW); const scale = getScale(size); const m_tracking = getTracking(tracking, scale); const m_leading = getLeading(leading, scale); const fontRatio = getFontRatio(weightRatio); this.fontRatio_ = fontRatio; this.scale_ = scale; this.lineWidth_ = getLineW(fontW, scale); const textGroup = getTextGroup(text, scale, width, breakWord); let total = textGroup.length; const total2 = total - 1; let i, j, j_total, j_total2, gt, t, str, m_rect, s_pos, tw = 0, th = 0, tx = 0, ty = 0, maxW = 0, maxH = 0, tmp = []; for (i = 0; i < total; i++) { gt = textGroup[i]; j_total = gt.length; j_total2 = j_total - 1; tw = 0; tx = 0; tmp[i] = { tw: 0, arr: [] }; for (j = 0; j < j_total; j++) { str = gt[j]; t = typo(str); m_rect = getRect(t, scale); tw += m_rect.w; th = m_rect.h; if (j < j_total2) { tw += m_tracking; } if (i < total2) { th += m_leading; } m_rect.x = tx; m_rect.y = ty; s_pos = { x: tx, y: ty }; tmp[i].arr[j] = { str: str, typo: t, rect: m_rect, originPos: s_pos, center: getCenter(m_rect.w, m_rect.h, scale), range: getRange(t, weightRatio, circleRound) }; tx = tw; } ty += th; tmp[i].tw = tw; maxW = Math.max(maxW, tw); maxH += th; } this.rect_.w = maxW; this.rect_.h = maxH; this.drawing_ = []; const arr = []; let aGapX, drawing; for (const a of tmp) { aGapX = setAlignGapX(maxW, a.tw); for (const b of a.arr) { b.alignGapX = aGapX; b.pointsLength = getLengths(b, this); arr.push(b); drawing = { value: 1 }; this.drawing_.push(drawing); b.drawing = drawing; // add converted Vector for (const c of b.typo.p) { c.cv = []; for (const d of c.v) { c.cv.push(d.convert(b, this)); } } } } this.data_ = arr; this.setPosition(); } updatePathsForRect() { const total = this.data_.length; const paths = []; let i, d; for (i = 0; i < total; i++) { d = this.data_[i]; if (d.rawWavePaths) { d.wavePaths = addRectToPaths(d.rawWavePaths, d); } if (d.rawPaths) { d.paths = addRectToPaths(d.rawPaths, d); Array.prototype.push.apply(paths, d.paths); } } this.paths_ = paths; } updateLinesForRect() { const total = this.data_.length; let i, d; for (i = 0; i < total; i++) { d = this.data_[i]; d.lines = getLines(d); } } reset() { this.lineWidth_ = 1; this.drawing_ = []; this.data_ = null; this.paths_ = null; this.lines_ = null; this.rect_ = { x: 0, y: 0, w: 0, h: 0 }; this.align_ = 'left'; this.scale_ = 1; this.fontRatio_ = 1; } } ================================================ FILE: src/core/paths.js ================================================ import { getCurrent } from './util.js'; import { ROTATE_NONE } from '../font/util.js'; import { Point } from './point.js'; let prevPoint = null; /** * @name getPaths * @property {Model} model - mode.js * @property {Object} data - data object * @property {Number} pathGap * @returns {Array} Returns paths array * @description get a guide pos */ export function getPaths(model, data, pathGap, isPattern) { const lines = data.pointsLength.lines; const scale = model.scale; let total = lines.length, i, j_total, j, line, lg, direction, arr = [], paths = [], paths2 = []; for (i = 0; i < total; i++) { line = lines[i]; prevPoint = null; arr.push(getDotPos(line, pathGap, scale)); } total = arr.length; for (i = 0; i < total; i++) { lg = arr[i]; j_total = lg.length; paths2 = []; for (j = 0; j < j_total; j++) { line = lg[j]; if (line.rotation != ROTATE_NONE) { if (isPattern) { // If the 'p' value of the font data is 1, it's not included in the pattern paths. if (!line.pat) { paths2.push(line); } } else { paths2.push(line); } } } direction = data.typo.p[i].d; if (direction == 1) { paths2.reverse(); } if (paths2.length > 0) { paths2[0].start = 1; Array.prototype.push.apply(paths, paths2); } } return paths; } function getDotPos(lines, pathGap, scale) { const total = lines.length; let i, j, j_total; let line; let curPoint; let num, pp; let arr = []; let isFirst = 1; let pgap = 1; if (pathGap > -1) pgap = getCurrent(pathGap, 1, 0, 80, 10) * scale; for (i = 0; i < total; i++) { line = lines[i]; if (line.type == 'a') { arr.push(new Point({ x: line.x1, y: line.y1, rotation: 0, type: 'a', pat: line.pat, fix: line.fix, radius: line.radius })); } else if (line.distance == 0) { // it should be type m curPoint = new Point({ x: line.x1, y: line.y1, rotation: line.rotation, type: line.type, pat: line.pat, fix: line.fix }); pp = setPointValues(curPoint, prevPoint, line, 1); if (pp != null) { if (isFirst) { pp.type = 'm'; isFirst = 0; } arr.push(pp); } prevPoint = new Point(curPoint); //Object.assign({}, curPoint) } else { j_total = Math.ceil(line.distance / pgap); if (j_total < 3) j_total = 3; if (line.vt) j_total = 2; for (j = 1; j < j_total; j++) { num = j / (j_total - 1); if (line.type == 'b') { curPoint = getCubicBezierXYatT(line, num); } else { curPoint = new Point({ x: line.x1 + ((line.x2 - line.x1) * num), y: line.y1 + ((line.y2 - line.y1) * num), type: line.type }); } if (line.rotation != 0 && num == 1) curPoint.rotation = line.rotation; if (line.pat && num == 1) curPoint.pat = line.pat; if (line.fix && num == 1) curPoint.fix = line.fix; if (j_total > 0) { pp = setPointValues(curPoint, prevPoint, line, num); if (pp != null) { if (isFirst) { pp.type = 'm'; isFirst = 0; } arr.push(pp); } } prevPoint = new Point(curPoint); //Object.assign({}, curPoint) } } } return arr; } function setPointValues(cur, prev, line, num) { cur.type = line.type; cur.distance = line.distance; cur.num = num; if (!prev || cur.rotation != null) { cur.rotation = cur.rotation; } else { const dx = cur.x - prev.x; const dy = cur.y - prev.y; const rad = Math.atan2(dx, dy); cur.rotation = -rad; } if (cur.rotation == ROTATE_NONE) { return null; } else { return cur; } } function getCubicBezierXYatT(line, t) { const x = CubicN(line.x1, line.x2, line.x3, line.x4, t); const y = CubicN(line.y1, line.y2, line.y3, line.y4, t); const tx = bezierTangent(line.x1, line.x2, line.x3, line.x4, t); const ty = bezierTangent(line.y1, line.y2, line.y3, line.y4, t); const rotation = -Math.atan2(tx, ty); return new Point({ x: x, y: y, rotation: rotation }); } function CubicN(a, b, c, d, t) { const t2 = t * t; const t3 = t2 * t; return a + (-a * 3 + t * (3 * a - a * t)) * t + (3 * b + t * (-6 * b + b * 3 * t)) * t + (c * 3 - c * 3 * t) * t2 + d * t3; } //http://qaru.site/questions/10657973/quadratic-curve-with-rope-pattern //https://stackoverflow.com/questions/32322966/quadratic-curve-with-rope-pattern export function bezierTangent(a, b, c, d, t) { return (3 * t * t * (-a + 3 * b - 3 * c + d) + 6 * t * (a - 2 * b + c) + 3 * (-a + b)); } ================================================ FILE: src/core/point.js ================================================ export function Point(mp) { Object.assign(this, mp); } Object.assign(Point.prototype, { addRect: function (rect) { const vv = new Point(this); vv.x = this.x + rect.x; vv.y = this.y + rect.y; vv.x2 = this.x2 + rect.x; vv.y2 = this.y2 + rect.y; vv.x3 = this.x3 + rect.x; vv.y3 = this.y3 + rect.y; vv.rx = this.rx + rect.x; vv.ry = this.ry + rect.y; vv.sx = this.sx + rect.x; vv.sy = this.sy + rect.y; if (vv.radius < 0.5) vv.radius = 0.5; return vv; } }); ================================================ FILE: src/core/util.js ================================================ const DEFAULT_FONT_SIZE = 500; export const MIN_FONT_WEIGHT = 1; export const MAX_FONT_WEIGHT = 900; const MAX_LINE_WIDTH = 70; const FONT_WEIGHT_LIMIT = 80; const FR_1 = 1; const FR_2 = 0.78; export const RECT_RATIO = 0.49; const MAX_SHAKE = 120; export const PI2 = 2 * Math.PI; export function getAmplitude(amplitude, scale) { return (MAX_SHAKE * amplitude) * scale; } export function getFontW(weight) { return (MAX_LINE_WIDTH - MIN_FONT_WEIGHT) / (MAX_FONT_WEIGHT - MIN_FONT_WEIGHT) * (weight - MIN_FONT_WEIGHT) + MIN_FONT_WEIGHT; } export function getWeightRatio(fontW) { return (1) / (FONT_WEIGHT_LIMIT - MIN_FONT_WEIGHT) * (fontW - MIN_FONT_WEIGHT); } export function getCircleRound(fontW) { return (58 - 4) / (FONT_WEIGHT_LIMIT - MIN_FONT_WEIGHT) * (fontW - MIN_FONT_WEIGHT) + 4; } export function getScale(size) { return size / DEFAULT_FONT_SIZE; } export function getLineW(fontW, scale) { let lw = fontW * scale; if (lw < 1) lw = 1; //if (weight == 1) lw = 1 return lw; } export function getTracking(tracking, scale) { return tracking * 50 * scale; } export function getLeading(leading, scale) { return leading * 50 * scale; } export function getFontRatio(weightRatio) { return (FR_2 - FR_1) * weightRatio + FR_1; } export function getRect(d, scale, x = 0, y = 0) { const w = (d.rect.w * RECT_RATIO) * scale; const h = ((d.rect.h + 220) * RECT_RATIO) * scale; return { x: x, y: y, w: w, h: h }; } /** * @name getGap * @property {Object} - typo data object from 'font/index.js' * @property {Number} - weightRatio * @returns {Object} the gap x and y * @description get a typo gap from thin to bold weight */ /* export function getGap(d, weightRatio) { const gx1 = d.ratio.x1 const gx2 = d.ratio.x2 const gy1 = d.ratio.y1 const gy2 = d.ratio.y2 const x = (gx2 - gx1) * weightRatio + gx1 const y = (gy2 - gy1) * weightRatio + gy1 return { x: x, y: y } } */ /** * @name getCenter * @property {Number} - typo rect width * @property {Number} - typo rect height * @property {Number} - typo scale * @returns {Object} center position x and y * @description get a center position of a typo */ export function getCenter(w, h, scale) { const x = w / 2; const y = (h - ((220 - 90) * RECT_RATIO * scale)) / 2; return { x: x, y: y }; } /** * @name getRange * @property {Object} - typo data object from 'font/index.js' * @property {Number} - weightRatio * @property {Number} - circleRound * @returns {Object} ratio range * @description save ratio range to control each line's coordinate */ export function getRange(d, weightRatio, circleRound) { const gx1 = d.ratio.x1; const gx2 = d.ratio.x2; const gy1 = d.ratio.y1; const gy2 = d.ratio.y2; return { r: weightRatio, cr: circleRound, fr1: FR_1, fr2: FR_2, gx1: gx1, gx2: gx2, gy1: gy1, gy2: gy2, }; } export function getCurrent(v, vmax, vmin, max, min) { let value = (max - min) / (vmax - vmin) * (v - vmin) + min; if (value < min) value = min; else if (value > max) value = max; return value; } export function getLines(data) { const total = data.typo.p.length; const lines = []; let i, j, k, j_total; let d2, d3, cp, dir, lt, ltRatio, prevRatio; for (i = 0; i < total; i++) { d2 = data.typo.p[i]; j_total = d2.cv.length; for (j = 0; j < j_total; j++) { d3 = d2.cv[j]; // add current position to all points cp = d3.addRect(data.rect); dir = d2.d; lt = data.pointsLength.lengths[i]; ltRatio = lt / data.pointsLength.max; prevRatio = 0; if (i > 0) { for (k = 0; k < i; k++) { prevRatio += (data.pointsLength.lengths[k] / data.pointsLength.max); } } ltRatio += prevRatio; lines.push({ pos: cp, drawing: data.drawing, direction: dir, lengths: lt, maxDrawing: ltRatio, minDrawing: prevRatio, closePath: d3.ratio.c, stroke: (ctx, d) => { let dv = getCurrent(d.drawing.value, d.maxDrawing, d.minDrawing, 1, 0); //if (d.direction == 1) { // dv = getCurrent(1 - d.drawing.value, d.minDrawing, d.maxDrawing, 1, 0); //} if (dv > 0 && d.pos.type != 'a') { const frac = d.lengths * dv; ctx.setLineDash([d.lengths]); ctx.lineDashOffset = d.direction * (frac + d.lengths); ctx.stroke(); } }, }); } } return lines; } export function addRectToPaths(path, data) { const total = path.length; const arr = []; let i, cp, p; for (i = 0; i < total; i++) { p = path[i]; cp = p.addRect(data.rect); arr.push(cp); } return arr; } export function randomBrightColor() { return "hsl(" + 360 * Math.random() + ',' + '100%,' + '50%)'; } export function shuffle(oldArray) { let newArray = oldArray.slice(), len = newArray.length, i = len, p, t; while (i--) { p = (Math.random() * len) | 0; t = newArray[i]; newArray[i] = newArray[p]; newArray[p] = t; } return newArray; } ================================================ FILE: src/core/vector.js ================================================ import { Point } from './point.js'; export function Vector(mp) { this.type = mp[0]; this.x = mp[1] || 0; this.y = mp[2] || 0; if (this.type == 'b') { this.x2 = mp[3] || 0; this.y2 = mp[4] || 0; this.x3 = mp[5] || 0; this.y3 = mp[6] || 0; if (mp[7] == null) { this.ratio = { x: 1, y: 1, r: 0, // rotation : if the rotation is ROTATE_NONE, it will hide in the 'pattern' and 'paths' p: 0, // 1 is hide the point in the pattern paths f: 0, // 1 is fixed position for wave paths c: 0, // 1 is close path for PIXI bug - graphics.closePath() v: 0 // 1 is vertex, it's only for the vertex shape like V, W, A }; } else { this.ratio = {}; this.ratio.x = (mp[7].x == null) ? 1 : mp[7].x; this.ratio.y = (mp[7].y == null) ? 1 : mp[7].y; this.ratio.r = mp[7].r || 0; this.ratio.p = mp[7].p || 0; this.ratio.f = mp[7].f || 0; this.ratio.c = mp[7].c || 0; this.ratio.v = mp[7].v || 0; } } else { if (mp[3] == null) { this.ratio = { x: 1, y: 1, r: 0, p: 0, f: 0, c: 0, v: 0 }; } else { this.ratio = {}; this.ratio.x = (mp[3].x == null) ? 1 : mp[3].x; this.ratio.y = (mp[3].y == null) ? 1 : mp[3].y; this.ratio.r = mp[3].r || 0; this.ratio.p = mp[3].p || 0; this.ratio.f = mp[3].f || 0; this.ratio.c = mp[3].c || 0; this.ratio.v = mp[3].v || 0; } } } Object.assign(Vector.prototype, { convert: function (pos, model) { const x = convertX(this.x, pos, this.ratio, model); const y = convertY(this.y, pos, this.ratio, model); const x2 = convertX(this.x2, pos, this.ratio, model); const y2 = convertY(this.y2, pos, this.ratio, model); const x3 = convertX(this.x3, pos, this.ratio, model); const y3 = convertY(this.y3, pos, this.ratio, model); const rd = convertR(this.type, pos, model); const vv = new Point(this); vv.x = x; vv.y = y; vv.x2 = x2; vv.y2 = y2; vv.x3 = x3; vv.y3 = y3; vv.radius = rd; return vv; } }); function convertR(type, pos, model) { let rd = 0; if (type == 'a') rd = pos.range.cr * model.scale * model.fontRatio; return rd; } function convertX(x, pos, ratio, model) { const rr = pos.range.r * ratio.x; const gx = (pos.range.gx2 - pos.range.gx1) * rr + pos.range.gx1; const fr = (pos.range.fr2 - pos.range.fr1) * rr + pos.range.fr1; return pos.center.x + (((x - gx)) * model.scale * fr); // + pos.rect.x } function convertY(y, pos, ratio, model) { const rr = pos.range.r * ratio.y; const gy = (pos.range.gy2 - pos.range.gy1) * rr + pos.range.gy1; const fr = (pos.range.fr2 - pos.range.fr1) * rr + pos.range.fr1; return pos.center.y + (((y - gy)) * model.scale * fr); // + pos.rect.y } ================================================ FILE: src/draw/canvas/color.js ================================================ export function Color(ctx, no, data, color) { let c_total = color.length; const cur = (no + (c_total * (Math.abs((no / 10) | 0) + 1))) % c_total; if (Array.isArray(color[cur])) { c_total = color[cur].length; const vv = 1 / (c_total + 1); const g = ctx.createLinearGradient(data.rect.x, data.rect.y, data.rect.x, data.rect.y + data.rect.h); let i; g.addColorStop(vv, color[cur][0]); for (i = 0; i < c_total; i++) { g.addColorStop(vv * (i + 1), color[cur][i]); } g.addColorStop(vv * (c_total + 1), color[cur][c_total - 1]); ctx.strokeStyle = g; ctx.fillStyle = g; } else { ctx.strokeStyle = color[cur]; ctx.fillStyle = color[cur]; } } ================================================ FILE: src/draw/canvas/colorful.js ================================================ import { PI2, getCurrent } from '../../core/util.js'; import { cubicBezierLength, distance } from '../../core/length.js'; let colorArr; let curColor = -1; let colorTotal; const MIN_DISTANCE = 10; export function Colorful(ctx, model, colors) { curColor = -1; colorArr = colors; colorTotal = colorArr.length; const total = model.data.length; let i, d, j, j_total, line, pos, prev; let max, length, prevRatio; for (i = 0; i < total; i++) { d = model.data[i]; max = d.pointsLength.max; prevRatio = 0; j_total = d.lines.length; prev = null; for (j = 0; j < j_total; j++) { line = d.lines[j]; pos = line.pos; if (pos.type == 'a') { setColor(ctx); ctx.beginPath(); ctx.arc(pos.x, pos.y, pos.radius * d.drawing.value, 0, PI2); ctx.fill(); ctx.closePath(); } else if (pos.type == 'm') { prev = pos; } else if (pos.type == 'l') { length = distance(prev.x, prev.y, pos.x, pos.y); if (length / model.scale > MIN_DISTANCE) { // ignore short distance paths setColor(ctx); ctx.beginPath(); if (prev) ctx.moveTo(prev.x, prev.y); ctx.lineTo(pos.x, pos.y); prevRatio += draw(ctx, line, length, max, d, prevRatio); } prev = pos; } else if (pos.type == 'b') { length = cubicBezierLength(prev.x, prev.y, pos.x, pos.y, pos.x2, pos.y2, pos.x3, pos.y3); if (length / model.scale > MIN_DISTANCE) { setColor(ctx); ctx.beginPath(); if (prev) ctx.moveTo(prev.x, prev.y); ctx.bezierCurveTo(pos.x, pos.y, pos.x2, pos.y2, pos.x3, pos.y3); prevRatio += draw(ctx, line, length, max, d, prevRatio); } prev = { x: pos.x3, y: pos.y3 }; } } } } function setColor(ctx) { const color = getColor(); ctx.fillStyle = color; ctx.strokeStyle = color; } function getColor() { curColor++; if (curColor == colorTotal) curColor = 0; return colorArr[curColor]; } function draw(ctx, line, length, max, d, prevRatio) { const ltRatio = length / max; let dv = getCurrent(d.drawing.value, prevRatio + ltRatio, prevRatio, 1, 0); if (line.direction == 1) { dv = getCurrent(1 - d.drawing.value, prevRatio, prevRatio + ltRatio, 1, 0); } if (dv > 0) { const frac = length * dv; ctx.setLineDash([length]); ctx.lineDashOffset = line.direction * (frac + length); ctx.stroke(); } return ltRatio; } ================================================ FILE: src/draw/canvas/grids.js ================================================ export function Grids(ctx, data) { ctx.save(); ctx.beginPath(); ctx.lineWidth = 1; ctx.strokeStyle = "#aaaaaa"; let i, total = data.guide.length, grid; for (i = 0; i < total; i++) { grid = data.rect.y + data.grid[i]; ctx.moveTo(data.rect.x, grid); ctx.lineTo(data.rect.x + data.rect.w, grid); } ctx.stroke(); ctx.lineWidth = 1; ctx.beginPath(); ctx.strokeStyle = "#aaaaaa"; ctx.rect(data.rect.x, data.rect.y, data.rect.w, data.rect.h); ctx.stroke(); ctx.restore(); } ================================================ FILE: src/draw/canvas/lines.js ================================================ import { PI2 } from '../../core/util.js'; export function Lines(ctx, data) { const total = data.lines.length; let i, d, pos; for (i = 0; i < total; i++) { d = data.lines[i]; pos = d.pos; if (pos.type == 'a') { ctx.beginPath(); ctx.arc(pos.x, pos.y, pos.radius * d.drawing.value, 0, PI2); ctx.fill(); ctx.closePath(); } else if (pos.type == 'm') { ctx.beginPath(); ctx.moveTo(pos.x, pos.y); } else if (pos.type == 'l') { ctx.lineTo(pos.x, pos.y); d.stroke(ctx, d); } else if (pos.type == 'b') { ctx.bezierCurveTo(pos.x, pos.y, pos.x2, pos.y2, pos.x3, pos.y3); d.stroke(ctx, d); } } } ================================================ FILE: src/draw/canvas/pattern.js ================================================ import { PI2 } from '../../core/util.js'; export function Pattern(ctx, data, w, h) { const total = Math.round(data.paths.length * data.drawing.value); const w2 = w / 2; const w3 = w / 3; const h2 = h / 2; let i, p; for (i = 0; i < total; i++) { p = data.paths[i]; if (p.num == 1) { ctx.fillStyle = "#ff00c5"; } else { ctx.fillStyle = "#ff95f8"; } if (p.type == 'a') { ctx.beginPath(); ctx.arc(p.x, p.y, w3, 0, PI2); ctx.fill(); } else { ctx.beginPath(); ctx.save(); ctx.translate(p.x, p.y); ctx.rotate(p.rotation); ctx.fillRect(-w2, -h2, w, h); ctx.restore(); } } } ================================================ FILE: src/draw/canvas/points.js ================================================ import { PI2 } from '../../core/util.js'; export function Points(ctx, data) { ctx.save(); ctx.lineWidth = 1; let total = data.lines.length; let i; for (i = 0; i < total; i++) { eachLine_(ctx, data.lines[i]); } ctx.restore(); ctx.save(); ctx.lineWidth = 1; total = data.typo.p.length; for (i = 0; i < total; i++) { eachPoint_(ctx, data.typo.p[i], data); } ctx.restore(); } function eachPoint_(ctx, p, data) { const total = p.v.length; let i, mp, cp; for (i = 0; i < total; i++) { mp = p.cv[i]; cp = mp.addRect(data.rect); if (mp.type == 'b') { ctx.fillStyle = "#ff2a00"; ctx.beginPath(); ctx.arc(cp.x3 + (cp.x3 - cp.x2), cp.y3 + (cp.y3 - cp.y2), 1.5, 0, PI2); ctx.fill(); ctx.beginPath(); ctx.arc(cp.x2, cp.y2, 1.5, 0, PI2); ctx.fill(); ctx.beginPath(); ctx.moveTo(cp.x2, cp.y2); ctx.lineTo(cp.x3, cp.y3); ctx.lineTo(cp.x3 + (cp.x3 - cp.x2), cp.y3 + (cp.y3 - cp.y2)); ctx.stroke(); ctx.beginPath(); ctx.fillStyle = "#ffffff"; ctx.arc(cp.x3, cp.y3, 2.5, 0, PI2); ctx.fill(); ctx.stroke(); } else { ctx.beginPath(); ctx.fillStyle = "#ffffff"; ctx.strokeStyle = "#ff2a00"; ctx.arc(cp.x, cp.y, 2.5, 0, PI2); ctx.fill(); ctx.stroke(); } } } function eachLine_(ctx, d) { const pos = d.pos; if (pos.type != 'a') { if (pos.type == 'm') { ctx.strokeStyle = "#ff2a00"; ctx.beginPath(); ctx.moveTo(pos.x, pos.y); } else if (pos.type == 'l') { ctx.lineTo(pos.x, pos.y); } else if (pos.type == 'b') { ctx.bezierCurveTo(pos.x, pos.y, pos.x2, pos.y2, pos.x3, pos.y3); } ctx.stroke(); } } ================================================ FILE: src/draw/canvas/wave.js ================================================ import { PI2, getAmplitude } from '../../core/util.js'; const THIN_LIMIT = 110; const COS = Math.cos; const SIN = Math.sin; export function Wave(ctx, data, scale, amplitude, weight, fps) { const total = data.wavePaths.length; const m_amplitude = getAmplitude(amplitude, scale); let i, p, prev, qx, qy, saveDot = []; ctx.beginPath(); for (i = 0; i < total; i++) { p = data.wavePaths[i]; if (fps) { const ranx = (Math.random() * m_amplitude) - (m_amplitude / 2); const rany = (Math.random() * m_amplitude) - (m_amplitude / 2); p.rx = p.x + ranx * COS(p.rotation); p.ry = p.y + ranx * SIN(p.rotation); p.sx = p.x + ranx; p.sy = p.y + rany; } if (p.type == 'a') { saveDot.push(p); } else if (p.start == 1) { ctx.moveTo(p.x, p.y); } else if (p.fix) { ctx.lineTo(p.x, p.y); } else { if (weight < THIN_LIMIT) { prev = data.wavePaths[i - 1]; if (prev) { qx = prev.x + ((p.x - prev.x) * 0.5); qy = prev.y + ((p.y - prev.y) * 0.5); ctx.quadraticCurveTo(qx, qy, p.rx, p.ry); } } else { ctx.lineTo(p.rx, p.ry); } } } ctx.stroke(); for (i = 0; i < saveDot.length; i++) { p = saveDot[i]; ctx.beginPath(); ctx.arc(p.x, p.y, p.radius, 0, PI2); ctx.fill(); } } ================================================ FILE: src/draw/pixi/color.js ================================================ export function PixiColor(no, data, color) { let c_total = color.length; const cur = (no + (c_total * (Math.abs((no / 10) | 0) + 1))) % c_total; if (Array.isArray(color[cur])) { /* c_total = color[cur].length; const vv = 1 / (c_total - 1); const g = ctx.createLinearGradient(data.rect.x, data.rect.y, data.rect.x, data.rect.y + data.rect.h); let i; for (i = 0; i < c_total; i++) { g.addColorStop(vv * i, color[cur][i]); } ctx.strokeStyle = g; ctx.fillStyle = g; */ /* c_total = color[cur].length; const vv = 1 / (c_total - 1); const c = document.createElement("canvas"); const ctx = c.getContext("2d"); const g = ctx.createLinearGradient(0, 0, data.rect.w, data.rect.h); let i; for (i = 0; i < c_total; i++) { g.addColorStop(vv * i, color[cur][i]); } ctx.fillStyle = g; ctx.fillRect(0, 0, data.rect.w, data.rect.h); return new PIXI.Texture.from(c); */ } else { return color[cur]; } } ================================================ FILE: src/draw/pixi/lines.js ================================================ export function PixiLines(graphics, data, lineW, color) { let total, i; if (data.drawing.value == 1) { total = data.lines.length; for (i = 0; i < total; i++) { eachLine_(graphics, data.lines[i], lineW, color); } } else { total = data.drawingPaths.length * data.drawing.value; for (i = 0; i < total; i++) { eachPath_(graphics, data.drawingPaths[i], lineW, color, data.drawing.value); } } } function eachLine_(graphics, data, lineW, color) { const pos = data.pos; if (pos.type == 'a') { graphics.lineStyle(0, color, 0); graphics.beginFill(color); graphics.drawCircle(pos.x, pos.y, pos.radius); graphics.endFill(); } else if (pos.type == 'm') { graphics.lineStyle(lineW, color, 1); graphics.moveTo(pos.x, pos.y); } else if (pos.type == 'l') { graphics.lineTo(pos.x, pos.y); } else if (pos.type == 'b') { graphics.bezierCurveTo(pos.x, pos.y, pos.x2, pos.y2, pos.x3, pos.y3); } if (data.closePath) { graphics.closePath(); } } function eachPath_(graphics, pos, lineW, color, dValue) { if (pos.type == 'a') { graphics.lineStyle(0, color, 0); graphics.beginFill(color); graphics.drawCircle(pos.x, pos.y, pos.radius * dValue); graphics.endFill(); } else { if (pos.start == 1) { graphics.lineStyle(lineW, color, 1); graphics.moveTo(pos.x, pos.y); } else { graphics.lineTo(pos.x, pos.y, 1); } } } ================================================ FILE: src/font/index.js ================================================ import { UPPER } from './upper.js'; import { LOWER } from './lower.js'; import { NUMBER } from './number.js'; import { SPECIAL } from './special.js'; import { LATIN } from './latin.js'; import { TOFU } from './util.js'; const DATA = Object.assign({}, UPPER, LOWER, NUMBER, SPECIAL, LATIN); export function typo(v) { const t = DATA[v] || DATA[TOFU]; const clone = t.clone(); clone.v = v; return clone; } ================================================ FILE: src/font/latin.js ================================================ import { generateFontData, ROTATE_HORIZONTAL, ROTATE_VERTICAL, ROTATE_NONE, getR, getCurveR } from './util.js'; import { getLatin1, getLatin2, getLatin3, getLatin4, getLatin5, getLatin6, getLatin7, getLatin8, getLatin9, getLatin10, getLatin11, getLatin12, getLatin13, getLatin14 } from './latinutil.js'; import { DATA_UA, DATA_UC, DATA_UD, DATA_UE, DATA_UG, DATA_UH, DATA_UI, DATA_UJ, DATA_UN, DATA_UO, DATA_US, DATA_UU, DATA_UY } from './upper.js'; import { DATA_LA, DATA_LC, DATA_LD, DATA_LE, DATA_LG, DATA_LH, DATA_LN, DATA_LO, DATA_LS, DATA_LU, DATA_LY } from './lower.js'; const DATA_LI = [{ d: 1, v: [ ['m', 0, 352, { y: 0, f: 1 }], ['l', 0, 130, { y: -3 }], ] }]; const DATA_LJ = [{ d: 1, v: [ ['m', 0 - 115.9, 317 + 127, { x: 0.4, y: 0.63, r: getCurveR(0 - 115.9, 317 + 127, 12.6 - 115.9, 327.4 + 127, 29.6 - 115.9, 333.2 + 127, 45.9 - 115.9, 334.2 + 127, 0), f: 1 }], ['b', 12.6 - 115.9, 327.4 + 127, 29.6 - 115.9, 333.2 + 127, 45.9 - 115.9, 334.2 + 127, { x: 0.4, y: 0.63, r: ROTATE_VERTICAL }], ['b', 84.5 - 115.9, 336.5 + 127, 0, 308.1 + 127, 0, 269.4 + 127, { x: 0.4, y: 0.63, r: ROTATE_HORIZONTAL }], ['l', 0, 0 + 127 + 3, { y: -3 }], ] }]; export const LATIN = { 'Æ': generateFontData( 996, 426, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 426.0, 0.0, { x: 0, r: ROTATE_VERTICAL }], ['l', 234.0, 0.0, { x: 0.5, f: 1, r: getR(234.0, 0.0, .0, 352.0), }], ['l', 0.0, 352.0, { x: 0.5, y: 0.5, f: 1 }], ] }, { d: -1, v: [ ['m', 234.0, 0.0, { x: 0.5, p: 1, }], ['l', 234.0, 352.0, { f: 1, x: 0.5 }], ['l', 426.0, 352.0, { f: 1, x: 0 }] ] }, { d: -1, v: [ ['m', 76.4, 237.0, { r: ROTATE_VERTICAL, p: 1, }], ['l', 234.0, 237.0, { f: 1, r: ROTATE_VERTICAL, p: 1, }] ] }, { d: -1, v: [ ['m', 234.0, 164.0, { r: ROTATE_VERTICAL, p: 1, x: 0.5 }], ['l', 414.0, 164.0, { f: 1, x: 0 }] ] }] ), 'æ': generateFontData( 1000, 232 + 225.5, 232, 0, 0, -64, -64, [{ d: -1, v: [ ['m', 232, 8, { y: -3.4, r: ROTATE_HORIZONTAL }], ['l', 232, 116, { r: ROTATE_NONE }], ['b', 232, 180.1, 180.1, 232, 116, 232, { r: ROTATE_VERTICAL }], ['b', 51.9, 232, 0, 180.1, 0, 116, { r: ROTATE_HORIZONTAL }], ['b', 0, 51.9, 51.9, 0, 116, 0, { r: ROTATE_VERTICAL }], ['b', 180.1, 0, 232, 51.9, 232, 116, { r: ROTATE_HORIZONTAL }], ['l', 232, 224, { y: -0.1, r: ROTATE_HORIZONTAL, f: 1 }] ] }, { d: 1, v: [ ['m', 211.6 + 232, 182.9, { r: getCurveR(211.6 + 232, 182.9, 191.1 + 232, 213.2, 156.1 + 232, 233.1, 116.5 + 232, 233.1, 0), f: 1 }], ['b', 191.1 + 232, 213.2, 156.1 + 232, 233.1, 116.5 + 232, 233.1, { r: ROTATE_VERTICAL }], ['b', 52.4 + 232, 233.1, 0.5 + 232, 181.2, 0.5 + 232, 117.1, { r: ROTATE_HORIZONTAL }], ['b', 0.5 + 232, 53, 52.4 + 232, 1.1, 116.5 + 232, 1.1, { r: ROTATE_VERTICAL }], ['b', 176.4 + 232, 1.1, 224.9 + 232, 47.2, 225.5 + 232, 106.1, { r: ROTATE_HORIZONTAL }], ['l', 0.5 + 232, 106.1, { r: ROTATE_HORIZONTAL, p: 1 }], ] }] ), 'À': generateFontData( 620, 290, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UA)).concat(getLatin1(145, -50)) ), 'Á': generateFontData( 620, 290, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UA)).concat(getLatin2(145, -50)) ), 'Â': generateFontData( 620, 290, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UA)).concat(getLatin3(145, -100)) ), 'Ã': generateFontData( 620, 290, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UA)).concat(getLatin4(145, -90)) ), 'Ä': generateFontData( 620, 290, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UA)).concat(getLatin5(145, -70)) ), 'Å': generateFontData( 620, 290, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UA)).concat(getLatin7(0, 0)) ), 'Ă': generateFontData( 620, 290, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UA)).concat(getLatin6(145, -110)) ), 'Ą': generateFontData( 620, 290, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UA)).concat(getLatin10(290, 352)) ), 'à': generateFontData( 600, 232, 232, 10, 2, -64, -64, JSON.parse(JSON.stringify(DATA_LA)).concat(getLatin1(116, -60)) ), 'á': generateFontData( 600, 232, 232, 10, 2, -64, -64, JSON.parse(JSON.stringify(DATA_LA)).concat(getLatin2(116, -60)) ), 'â': generateFontData( 600, 232, 232, 10, 2, -64, -64, JSON.parse(JSON.stringify(DATA_LA)).concat(getLatin3(116, -110)) ), 'ã': generateFontData( 600, 232, 232, 10, 2, -64, -64, JSON.parse(JSON.stringify(DATA_LA)).concat(getLatin4(116, -100)) ), 'ä': generateFontData( 600, 232, 232, 10, 2, -64, -64, JSON.parse(JSON.stringify(DATA_LA)).concat(getLatin5(116, -80)) ), 'å': generateFontData( 600, 232, 232, 10, 2, -64, -64, JSON.parse(JSON.stringify(DATA_LA)).concat(getLatin7(-30, 0)) ), 'ă': generateFontData( 600, 232, 232, 10, 2, -64, -64, JSON.parse(JSON.stringify(DATA_LA)).concat(getLatin6(116, -120)) ), 'ą': generateFontData( 600, 232, 232, 10, 2, -64, -64, JSON.parse(JSON.stringify(DATA_LA)).concat(getLatin10(232, 224)) ), 'Ć': generateFontData( 700, 293.1, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UC)).concat(getLatin1(180, -60)) ), 'Ĉ': generateFontData( 700, 293.1, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UC)).concat(getLatin3(180, -110)) ), 'Ċ': generateFontData( 700, 293.1, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UC)).concat(getLatin11(180, -80)) ), 'Č': generateFontData( 700, 293.1, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UC)).concat(getLatin12(180, -110)) ), 'Ç': generateFontData( 700, 293.1, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UC)).concat(getLatin9(180, 360)) ), 'ć': generateFontData( 520, 212.1, 233.1, 2, -10, -64, -64, JSON.parse(JSON.stringify(DATA_LC)).concat(getLatin1(116.5, 1.1 - 70)) ), 'ĉ': generateFontData( 520, 212.1, 233.1, 2, -10, -64, -64, JSON.parse(JSON.stringify(DATA_LC)).concat(getLatin3(116.5, 1.1 - 120)) ), 'ċ': generateFontData( 520, 212.1, 233.1, 2, -10, -64, -64, JSON.parse(JSON.stringify(DATA_LC)).concat(getLatin11(116.5, 1.1 - 90)) ), 'č': generateFontData( 520, 212.1, 233.1, 2, -10, -64, -64, JSON.parse(JSON.stringify(DATA_LC)).concat(getLatin12(116.5, 1.1 - 120)) ), 'ç': generateFontData( 520, 212.1, 233.1, 2, -10, -64, -64, JSON.parse(JSON.stringify(DATA_LC)).concat(getLatin9(116.5, 233.1)) ), 'Đ': generateFontData( 721, 270, 352, -10, -10, 0, 0, JSON.parse(JSON.stringify(DATA_UD)).concat(getLatin8(0, 352 / 2)) ), 'Ď': generateFontData( 721, 270, 352, -10, -10, 0, 0, JSON.parse(JSON.stringify(DATA_UD)).concat(getLatin12(100, -110)) ), 'ď': generateFontData( 600, 232, 352, 10, 2, 0, 0, JSON.parse(JSON.stringify(DATA_LD)).concat(getLatin13(300, 0)) ), 'đ': generateFontData( 600, 232, 352, 10, 2, 0, 0, JSON.parse(JSON.stringify(DATA_LD)).concat(getLatin8(180, 40)) ), 'È': generateFontData( 520, 192, 352, -5, -80, 0, 0, JSON.parse(JSON.stringify(DATA_UE)).concat(getLatin1(96, -60)) ), 'É': generateFontData( 520, 192, 352, -5, -80, 0, 0, JSON.parse(JSON.stringify(DATA_UE)).concat(getLatin2(96, -60)) ), 'Ê': generateFontData( 520, 192, 352, -5, -80, 0, 0, JSON.parse(JSON.stringify(DATA_UE)).concat(getLatin3(96, -110)) ), 'Ë': generateFontData( 520, 192, 352, -5, -80, 0, 0, JSON.parse(JSON.stringify(DATA_UE)).concat(getLatin5(96, -80)) ), 'Ē': generateFontData( 520, 192, 352, -5, -80, 0, 0, JSON.parse(JSON.stringify(DATA_UE)).concat(getLatin14(96, -80)) ), 'Ĕ': generateFontData( 520, 192, 352, -5, -80, 0, 0, JSON.parse(JSON.stringify(DATA_UE)).concat(getLatin6(96, -120)) ), 'Ė': generateFontData( 520, 192, 352, -5, -80, 0, 0, JSON.parse(JSON.stringify(DATA_UE)).concat(getLatin11(96, -80)) ), 'Ě': generateFontData( 520, 192, 352, -5, -80, 0, 0, JSON.parse(JSON.stringify(DATA_UE)).concat(getLatin12(96, -110)) ), 'è': generateFontData( 570, 225.5, 233.1, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LE)).concat(getLatin1(112, -60)) ), 'é': generateFontData( 570, 225.5, 233.1, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LE)).concat(getLatin2(112, -60)) ), 'ê': generateFontData( 570, 225.5, 233.1, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LE)).concat(getLatin3(112, -110)) ), 'ë': generateFontData( 570, 225.5, 233.1, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LE)).concat(getLatin5(112, -80)) ), 'ē': generateFontData( 570, 225.5, 233.1, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LE)).concat(getLatin14(112, -80)) ), 'ĕ': generateFontData( 570, 225.5, 233.1, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LE)).concat(getLatin6(112, -120)) ), 'ė': generateFontData( 570, 225.5, 233.1, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LE)).concat(getLatin11(112, -90)) ), 'ě': generateFontData( 570, 225.5, 233.1, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LE)).concat(getLatin12(112, -120)) ), 'Ĝ': generateFontData( 840, 352, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UG)).concat(getLatin3(180, -110)) ), 'Ğ': generateFontData( 840, 352, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UG)).concat(getLatin6(180, -120)) ), 'Ġ': generateFontData( 840, 352, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UG)).concat(getLatin11(180, -80)) ), 'Ģ': generateFontData( 840, 352, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UG)).concat(getLatin9(180, 360)) ), 'ĝ': generateFontData( 600, 232, 338, 10, 2, -117, -117, JSON.parse(JSON.stringify(DATA_LG)).concat(getLatin3(116, 1.1 - 120)) ), 'ğ': generateFontData( 600, 232, 338, 10, 2, -117, -117, JSON.parse(JSON.stringify(DATA_LG)).concat(getLatin6(116, -120)) ), 'ġ': generateFontData( 600, 232, 338, 10, 2, -117, -117, JSON.parse(JSON.stringify(DATA_LG)).concat(getLatin11(116, -90)) ), 'ģ': generateFontData( 600, 232, 338, 10, 2, -117, -117, JSON.parse(JSON.stringify(DATA_LG)).concat(getLatin2(116, -70)) ), 'Ĥ': generateFontData( 684, 232, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UH)).concat(getLatin3(232 / 2, -110)) ), 'ĥ': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LH)).concat(getLatin3(182 / 2, -110)) ), 'Ì': generateFontData( 249, 0, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UI)).concat(getLatin1(0, -60)) ), 'Í': generateFontData( 249, 0, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UI)).concat(getLatin2(0, -60)) ), 'Î': generateFontData( 249, 0, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UI)).concat(getLatin3(0, -110)) ), 'Ï': generateFontData( 249, 0, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UI)).concat(getLatin5(0, -80)) ), 'ì': generateFontData( 200, 0, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LI)).concat(getLatin1(0, -60 + 130)) ), 'í': generateFontData( 200, 0, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LI)).concat(getLatin2(0, -60 + 130)) ), 'î': generateFontData( 200, 0, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LI)).concat(getLatin3(0, -120 + 130)) ), 'ï': generateFontData( 200, 0, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LI)).concat(getLatin5(0, -80 + 130)) ), 'Ĵ': generateFontData( 472, 172.5, 355.5, 10, 20, -2, -2, JSON.parse(JSON.stringify(DATA_UJ)).concat(getLatin3(172.5, -110)) ), 'ĵ': generateFontData( 220, 115.9, 352, -60, -60, 0, 0, JSON.parse(JSON.stringify(DATA_LJ)).concat(getLatin3(0, -110 + 130)) ), 'Ñ': generateFontData( 721, 250, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UN)).concat(getLatin4(250 / 2, -100)) ), 'ñ': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LN)).concat(getLatin4(182 / 2, -100 + 130)) ), 'Ò': generateFontData( 850, 360, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UO)).concat(getLatin1(180, -60)) ), 'Ó': generateFontData( 850, 360, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UO)).concat(getLatin2(180, -60)) ), 'Ô': generateFontData( 850, 360, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UO)).concat(getLatin3(180, -110)) ), 'Õ': generateFontData( 850, 360, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UO)).concat(getLatin4(180, -100)) ), 'Ö': generateFontData( 850, 360, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UO)).concat(getLatin5(180, -80)) ), 'Ø': generateFontData( 850, 360, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UO)).concat([{ d: 1, v: [ ['m', 0, 360, { r: getR(0, 360, 360, 0), f: 1, x: 0, y: 1 }], ['l', 360, 0, { x: 0, y: 1 }] ] }]) ), 'ò': generateFontData( 580, 232, 232, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LO)).concat(getLatin1(116, -60)) ), 'ó': generateFontData( 580, 232, 232, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LO)).concat(getLatin2(116, -60)) ), 'ô': generateFontData( 580, 232, 232, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LO)).concat(getLatin3(116, -110)) ), 'õ': generateFontData( 580, 232, 232, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LO)).concat(getLatin4(116, -100)) ), 'ö': generateFontData( 580, 232, 232, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LO)).concat(getLatin5(116, -80)) ), 'ø': generateFontData( 580, 232, 232, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LO)).concat([{ d: 1, v: [ ['m', 0, 232, { r: getR(0, 232, 232, 0), f: 1, x: 0, y: 1 }], ['l', 232, 0, { x: 0, y: 1 }] ] }]) ), 'Ŝ': generateFontData( 560, 224, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_US)).concat(getLatin3(112.4, -110)) ), 'ŝ': generateFontData( 400, 224 * 0.642, 360 * 0.642, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LS)).concat(getLatin3(112.4 * 0.642, -110)) ), 'Ş': generateFontData( 560, 224, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_US)).concat(getLatin9(110.3, 360)) ), 'ş': generateFontData( 400, 224 * 0.642, 360 * 0.642, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LS)).concat(getLatin9(110.3 * 0.642, 360 * 0.642)) ), 'Ù': generateFontData( 712, 250, 355, 0, 0, -0.5, -0.5, JSON.parse(JSON.stringify(DATA_UU)).concat(getLatin1(125, -50)) ), 'Ú': generateFontData( 712, 250, 355, 0, 0, -0.5, -0.5, JSON.parse(JSON.stringify(DATA_UU)).concat(getLatin2(125, -50)) ), 'Û': generateFontData( 712, 250, 355, 0, 0, -0.5, -0.5, JSON.parse(JSON.stringify(DATA_UU)).concat(getLatin3(125, -100)) ), 'Ŭ': generateFontData( 712, 250, 355, 0, 0, -0.5, -0.5, JSON.parse(JSON.stringify(DATA_UU)).concat(getLatin6(125, -110)) ), 'Ü': generateFontData( 712, 250, 355, 0, 0, -0.5, -0.5, JSON.parse(JSON.stringify(DATA_UU)).concat(getLatin5(125, -70)) ), 'ù': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LU)).concat(getLatin1(91, -60 + 130)) ), 'ú': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LU)).concat(getLatin2(91, -60 + 130)) ), 'û': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LU)).concat(getLatin3(91, -110 + 130)) ), 'ŭ': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LU)).concat(getLatin6(91, -120 + 130)) ), 'ü': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LU)).concat(getLatin5(91, -80 + 130)) ), 'Ý': generateFontData( 673, 270, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UY)).concat(getLatin2(135, -60)) ), 'ý': generateFontData( 500, 225.5, 331.5, 10, 10, -119, -119, JSON.parse(JSON.stringify(DATA_LY)).concat(getLatin2(116.3, -60)) ), 'ÿ': generateFontData( 500, 225.5, 331.5, 10, 10, -119, -119, JSON.parse(JSON.stringify(DATA_LY)).concat(getLatin5(116.3, -90)) ), }; ================================================ FILE: src/font/latinutil.js ================================================ import { ROTATE_HORIZONTAL, ROTATE_VERTICAL, VERTEX_GAP2, getR, getCurveR } from './util.js'; //À export function getLatin1(x, y) { const tx = x; const ty = -60 + y; return [{ d: -1, v: [ ['m', -40 + tx, ty, { x: 0, y: 0, r: getR(-40 + tx, ty, 0 + tx, 60 + ty) }], ['l', 0 + tx, 60 + ty, { x: 0, y: 0, f: 1 }], ] }]; } //Á export function getLatin2(x, y) { const tx = x; const ty = -60 + y; return [{ d: -1, v: [ ['m', 40 + tx, ty, { x: 0, y: 0, r: getR(40 + tx, ty, 0 + tx, 60 + ty) }], ['l', 0 + tx, 60 + ty, { x: 0, y: 0, f: 1 }], ] }]; } //Â export function getLatin3(x, y) { const tx = -68 + x; const ty = 0 + y; return [{ d: -1, v: [ ['m', 0 + tx, 50 + ty, { r: getR(0 + tx, 50 + ty, 68 - VERTEX_GAP2 + tx, 0 + ty), y: 0, x: 0 }], ['l', 68 - VERTEX_GAP2 + tx, 0 + ty, { r: getR(0 + tx, 50 + ty, 68 - VERTEX_GAP2 + tx, 0 + ty), y: 0, x: 0, f: 1, }], ['l', 68 + VERTEX_GAP2 + tx, 0 + ty, { r: getR(68 + VERTEX_GAP2 + tx, 0 + ty, 68 + 68 + tx, 50 + ty), y: 0, x: 0, f: 1, v: 1 }], ['l', 68 + 68 + tx, 50 + ty, { y: 0, x: 0, f: 1 }] ] }]; } //Ã export function getLatin4(x, y) { const tx = x - 76.24; const ty = y; return [{ d: 1, v: [ ['m', 159.52 + tx, 16.56 + ty, { x: -1, y: -0.2, r: getCurveR(159.52 + tx, 16.56 + ty, 150.08 + tx, 29.28 + ty, 134.56 + tx, 37.68 + ty, 118.56 + tx, 37.68 + ty, 0), f: 1 }], ['b', 150.08 + tx, 29.28 + ty, 134.56 + tx, 37.68 + ty, 118.56 + tx, 37.68 + ty, { x: -1, y: -0.2, r: ROTATE_VERTICAL }], ['b', 103.28 + tx, 37.68 + ty, 89.68 + tx, 29.28 + ty, 76.24 + tx, 20.4 + ty, { x: -1, y: -0.2 }], ['b', 61.44 + tx, 10.56 + ty, 47.28 + tx, 0 + ty, 31.68 + tx, 0 + ty, { x: -1, y: -0.2, r: ROTATE_VERTICAL }], ['b', 17.84 + tx, 0 + ty, 8.72 + tx, 7.12 + ty, 0 + tx, 16 + ty, { x: -1, y: -0.2 }], ] }]; } //Ä export function getLatin5(x, y) { return [{ d: 1, v: [ ['a', -50 + x, y, { x: 0, y: 0 }], ] }, { d: 1, v: [ ['a', 50 + x, y, { x: 0, y: 0 }], ] }]; } //Ŭ export function getLatin6(x, y) { const tx = x - 57; const ty = y; return [{ d: 1, v: [ ['m', 112.7 + tx, 0.0 + ty, { r: getCurveR(112.7 + tx, 0.0 + ty + tx, 10.1 + ty, 110.1 + tx, 19.3 + ty, 105.0 + tx, 27.7 + ty, 0), x: 0, y: 0, f: 1 }], ['b', 112.7 + tx, 10.1 + ty, 110.1 + tx, 19.3 + ty, 105.0 + tx, 27.7 + ty, { x: 0, y: 0, }], ['b', 99.8 + tx, 36.1 + ty, 92.9 + tx, 42.8 + ty, 84.3 + tx, 47.7 + ty, { x: 0, y: 0, }], ['b', 75.7 + tx, 52.6 + ty, 66.7 + tx, 55.0 + ty, 57.3 + tx, 55.0 + ty, { x: 0, y: 0, }], ['b', 47.5 + tx, 55.0 + ty, 38.3 + tx, 52.6 + ty, 29.6 + tx, 47.7 + ty, { x: 0, y: 0, }], ['b', 20.8 + tx, 42.8 + ty, 13.8 + tx, 36.1 + ty, 8.5 + tx, 27.7 + ty, { x: 0, y: 0, }], ['b', 3.2 + tx, 19.3 + ty, 0.5 + tx, 10.1 + ty, 0.5 + tx, 0.0 + ty, { x: 0, y: 0, }], ] }]; } //Å export function getLatin7(x, y) { const tx = 88 + x; const ty = -116 + y; const scale = 0.5; return [{ d: 1, v: [ ['m', 232 * scale + tx, 116 * scale + ty, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['b', 232 * scale + tx, 180.1 * scale + ty, 180.1 * scale + tx, 232 * scale + ty, 116 * scale + tx, 232 * scale + ty, { r: ROTATE_VERTICAL }], ['b', 51.9 * scale + tx, 232 * scale + ty, 0 * scale + tx, 180.1 * scale + ty, 0 * scale + tx, 116 * scale + ty, { r: ROTATE_HORIZONTAL }], ['b', 0 * scale + tx, 51.9 * scale + ty, 51.9 * scale + tx, 0 * scale + ty, 116 * scale + tx, 0 * scale + ty, { r: ROTATE_VERTICAL }], ['b', 180.1 * scale + tx, 0 * scale + ty, 232 * scale + tx, 51.9 * scale + ty, 232 * scale + tx, 116 * scale + ty, { r: ROTATE_HORIZONTAL, c: 1 }], ] }] } //Ð export function getLatin8(x, y) { return [{ d: 1, v: [ ['m', x - 40, y, { x: 0, y: 1, r: ROTATE_VERTICAL }], ['l', 100 + x, y, { x: 0, y: 1, f: 1 }], ] }] } //Ç export function getLatin9(x, y) { return [{ d: -1, v: [ ['m', x, y, { p: 1 }], ['b', 9.3 + x, 11.6 + y, 15.6 + x, 27.1 + y, 15.6 + x, 40.9 + y], ['b', 15.6 + x, 83.3 + y, -18.2 + x, 107.8 + y, -59.5 + x, 107.8 + y], ['b', -70.9 + x, 107.8 + y, -82.9 + x, 106.2 + y, -93.7 + x, 102.7 + y, { x: 0.5, f: 1 }], ] }] } //Ą export function getLatin10(x, y) { return [{ d: -1, v: [ ['m', x, y, { p: 1 }], ['b', 22.6 - 42.2 + x, 14.8 + y, -42.2 + x, 37.9 + y, -42.2 + x, 64.1 + y], ['b', -42.2 + x, 100.3 + y, 30.2 - 42.2 + x, 118.8 + y, 63.6 - 42.2 + x, 118.8 + y], ['b', 68.3 - 42.2 + x, 118.8 + y, 72.9 - 42.2 + x, 118.4 + y, 77.4 - 42.2 + x, 117.6 + y, { x: 0.5, f: 1 }], ] }] } //Ċ export function getLatin11(x, y) { return [{ d: 1, v: [ ['a', x, y, { x: 0, y: 0 }], ] }]; } //Č export function getLatin12(x, y) { const tx = -68 + x; const ty = y; return [{ d: -1, v: [ ['m', 0 + tx, ty, { r: getR(0 + tx, ty, 68 - VERTEX_GAP2 + tx, 50 + ty), y: 0, x: 0 }], ['l', 68 - VERTEX_GAP2 + tx, 50 + ty, { r: getR(0 + tx, ty, 68 - VERTEX_GAP2 + tx, 50 + ty), y: 0, x: 0, f: 1, }], ['l', 68 + VERTEX_GAP2 + tx, 50 + ty, { r: getR(68 + VERTEX_GAP2 + tx, 50 + ty, 68 + 68 + tx, ty), y: 0, x: 0, f: 1, v: 1 }], ['l', 68 + 68 + tx, ty, { y: 0, x: 0, f: 1 }] ] }]; } //ď export function getLatin13(x, y) { return [{ d: -1, v: [ ['m', x, y, { x: 0, y: 0 }], ['l', x, 80 + y, { x: 0, y: 0, f: 1 }], ] }]; } //Ē export function getLatin14(x, y) { return [{ d: 1, v: [ ['m', x - 50, y, { x: 0, y: 0 }], ['l', x + 50, y, { x: 0, y: 0, f: 1 }], ] }]; } ================================================ FILE: src/font/lower.js ================================================ import { generateFontData, ROTATE_HORIZONTAL, ROTATE_VERTICAL, ROTATE_NONE, VERTEX_GAP, VERTEX_GAP2, getR, getCurveR } from './util.js'; export const DATA_LA = [{ d: -1, v: [ ['m', 232, 8, { y: -3.4, r: ROTATE_HORIZONTAL }], ['l', 232, 116, { r: ROTATE_NONE }], ['b', 232, 180.1, 180.1, 232, 116, 232, { r: ROTATE_VERTICAL }], ['b', 51.9, 232, 0, 180.1, 0, 116, { r: ROTATE_HORIZONTAL }], ['b', 0, 51.9, 51.9, 0, 116, 0, { r: ROTATE_VERTICAL }], ['b', 180.1, 0, 232, 51.9, 232, 116, { r: ROTATE_HORIZONTAL }], ['l', 232, 224, { y: -0.1, r: ROTATE_HORIZONTAL, f: 1 }] ] }]; export const DATA_LC = [{ d: 1, v: [ ['m', 212.1, 182.9, { r: getCurveR(212.1, 182.9, 191.1, 213.2, 156.1, 233.1, 116.5, 233.1, 0), f: 1 }], ['b', 191.1, 213.2, 156.1, 233.1, 116.5, 233.1, { r: ROTATE_VERTICAL }], ['b', 52.4, 233.1, 0.5, 181.2, 0.5, 117.1, { r: ROTATE_HORIZONTAL }], ['b', 0.5, 53, 52.4, 1.1, 116.5, 1.1, { r: ROTATE_VERTICAL }], ['b', 156.1, 1.1, 191.1, 21, 212.1, 51.3], ] }]; export const DATA_LD = [{ d: -1, v: [ ['m', 232, 0, { y: 0 }], ['l', 232, 116 + 123, { r: ROTATE_NONE }], ['b', 232, 180.1 + 123, 180.1, 232 + 123, 116, 232 + 123, { r: ROTATE_VERTICAL }], ['b', 51.9, 232 + 123, 0, 180.1 + 123, 0, 116 + 123, { r: ROTATE_HORIZONTAL }], ['b', 0, 51.9 + 123, 51.9, 0 + 123, 116, 0 + 123, { r: ROTATE_VERTICAL }], ['b', 180.1, 0 + 123, 232, 51.9 + 123, 232, 116 + 123, { r: ROTATE_HORIZONTAL }], ['l', 232, 352, { y: 0, f: 1 }], ] }]; export const DATA_LE = [{ d: 1, v: [ ['m', 211.6, 182.9, { r: getCurveR(211.6, 182.9, 191.1, 213.2, 156.1, 233.1, 116.5, 233.1, 0), f: 1 }], ['b', 191.1, 213.2, 156.1, 233.1, 116.5, 233.1, { r: ROTATE_VERTICAL }], ['b', 52.4, 233.1, 0.5, 181.2, 0.5, 117.1, { r: ROTATE_HORIZONTAL }], ['b', 0.5, 53, 52.4, 1.1, 116.5, 1.1, { r: ROTATE_VERTICAL }], ['b', 176.4, 1.1, 224.9, 47.2, 225.5, 106.1, { r: ROTATE_HORIZONTAL }], ['l', 0.5, 106.1, { r: ROTATE_HORIZONTAL, p: 1 }], ] }]; export const DATA_LG = [{ d: -1, v: [ ['m', 232, 5, { y: -2.8 }], ['l', 232, 116, { r: ROTATE_NONE }], ['b', 232, 180.1, 180.1, 232, 116, 232, { r: ROTATE_VERTICAL }], ['b', 51.9, 232, 0, 180.1, 0, 116, { r: ROTATE_HORIZONTAL }], ['b', 0, 51.9, 51.9, 0, 116, 0, { r: ROTATE_VERTICAL }], ['b', 180.1, 0, 232, 51.9, 232, 116, { r: ROTATE_HORIZONTAL }], ['l', 232, 222], ['b', 234.5, 300.3, 180.2, 338.5, 116, 338, { y: 0.64, r: ROTATE_VERTICAL }], ['b', 76.2, 337.7, 36.6, 320.7, 15.7, 290.1, { y: 0.64, f: 1 }], ] }]; export const DATA_LH = [{ d: -1, v: [ ['m', 0, 0, { y: 0, r: ROTATE_HORIZONTAL }], ['l', 0, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 91 + 123, { r: ROTATE_NONE }], ['b', 0, 40.7 + 123, 40.7, 0 + 123, 91, 0 + 123, { r: ROTATE_VERTICAL }], ['b', 141.3, 0 + 123, 182, 40.7 + 123, 182, 91 + 123, { r: ROTATE_HORIZONTAL }], ['l', 182, 352, { y: 0, f: 1 }], ] }]; export const DATA_LN = [{ d: -1, v: [ ['m', 0, 130, { y: -3.3 }], ['l', 0, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 91 + 123, { y: 0, r: ROTATE_HORIZONTAL, p: 1 }], ['b', 0, 40.7 + 123, 40.7, 0 + 123, 91, 0 + 123, { r: ROTATE_VERTICAL }], ['b', 141.3, 0 + 123, 182, 40.7 + 123, 182, 91 + 123, { r: ROTATE_HORIZONTAL }], ['l', 182, 352, { y: 0, f: 1 }], ] }]; export const DATA_LO = [{ d: 1, v: [ ['m', 232, 116, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['b', 232, 180.1, 180.1, 232, 116, 232, { r: ROTATE_VERTICAL }], ['b', 51.9, 232, 0, 180.1, 0, 116, { r: ROTATE_HORIZONTAL }], ['b', 0, 51.9, 51.9, 0, 116, 0, { r: ROTATE_VERTICAL }], ['b', 180.1, 0, 232, 51.9, 232, 116, { r: ROTATE_HORIZONTAL, c: 1 }], ] }]; export const DATA_LS = [{ d: 1, v: [ ['m', 0 * 0.642, 295.4 * 0.642, { r: getCurveR(0 * 0.642, 295.4 * 0.642, 17.6 * 0.642, 332.1 * 0.642, 58.3 * 0.642, 360 * 0.642, 110.3 * 0.642, 360 * 0.642, 0), f: 1 }], ['b', 17.6 * 0.642, 332.1 * 0.642, 58.3 * 0.642, 360 * 0.642, 110.3 * 0.642, 360 * 0.642], ['b', 173.9 * 0.642, 360 * 0.642, 223.8 * 0.642, 329.6 * 0.642, 224 * 0.642, 271 * 0.642], ['b', 224.2 * 0.642, 214.7 * 0.642, 180.7 * 0.642, 189.6 * 0.642, 112.4 * 0.642, 173.3 * 0.642], ['b', 47.3 * 0.642, 157.7 * 0.642, 10.9 * 0.642, 130.6 * 0.642, 12 * 0.642, 84.4 * 0.642], ['b', 13.3 * 0.642, 29.8 * 0.642, 57.3 * 0.642, 0 * 0.642, 114.8 * 0.642, 0 * 0.642], ['b', 158.4 * 0.642, 0 * 0.642, 196.5 * 0.642, 20.5 * 0.642, 212 * 0.642, 51.3 * 0.642], ] }]; export const DATA_LU = [{ d: -1, v: [ ['m', 0, 130, { y: -3 }], ['l', 0, 0 + 265, { r: ROTATE_HORIZONTAL }], ['b', 0, 50.3 + 265, 40.7, 91 + 265, 91, 91 + 265, { r: ROTATE_VERTICAL }], ['b', 141.3, 91 + 265, 182, 50.3 + 265, 182, 0 + 265, { r: ROTATE_HORIZONTAL, p: 1, f: 1, }], ] }, { d: -1, v: [ ['m', 182, 130, { y: -3 }], ['l', 182, 352, { y: 0, f: 1 }], ] } ]; export const DATA_LY = [{ d: -1, v: [ ['m', 225.5, 0, { y: -3, r: getR(225.5, 0, 116.3, 248.8) }], ['l', 116.3, 248.8, { x: 0.5, y: 0.64 }], ['b', 71.8, 349.6, 0, 331.5, 0, 331.5, { x: 0.5, y: 0.64, r: getCurveR(0, 331.5, 71.8, 349.6, 116.3, 248.8, 0, 331.5, 0), f: 1 }], ] }, { d: -1, v: [ ['m', 3.2, 0, { y: -3, r: getR(3.2, 0, 125.7, 226.6) }], ['l', 125.7, 226.6, { p: 1, f: 1 }], ] } ]; export const LOWER = { 'a': generateFontData( 600, 232, 232, 10, 2, -64, -64, JSON.parse(JSON.stringify(DATA_LA)) ), 'b': generateFontData( 600, 232, 352, -10, -2, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { y: 0, r: ROTATE_HORIZONTAL }], ['l', 0, 116 + 123, { r: ROTATE_NONE }], ['b', 0, 180.1 + 123, 51.9, 232 + 123, 116, 232 + 123, { r: ROTATE_VERTICAL }], ['b', 180.1, 232 + 123, 232, 180.1 + 123, 232, 116 + 123, { r: ROTATE_HORIZONTAL }], ['b', 232, 51.9 + 123, 180.1, 0 + 123, 116, 0 + 123, { r: ROTATE_VERTICAL }], ['b', 51.9, 0 + 123, 0, 51.9 + 123, 0, 116 + 123, { r: ROTATE_HORIZONTAL }], ['l', 0, 352, { y: 0, r: ROTATE_HORIZONTAL, f: 1 }] ] }, ] ), 'c': generateFontData( 520, 212.1, 233.1, 2, -10, -64, -64, JSON.parse(JSON.stringify(DATA_LC)) ), 'd': generateFontData( 600, 232, 352, 10, 2, 0, 0, JSON.parse(JSON.stringify(DATA_LD)) ), 'e': generateFontData( 570, 225.5, 233.1, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LE)) ), 'f': generateFontData( 356, 232, 352, -40, -40, 0, 0, [{ d: -1, v: [ ['m', 166.6, 33, { x: 0.5, r: getCurveR(166.6, 33, 159.3, 13.1, 139.2, 0, 116.9, 0, 0) }], ['b', 159.3, 13.1, 139.2, 0, 116.9, 0, { r: ROTATE_VERTICAL }], ['b', 88.2, 0, 65, 23.2, 65, 51.9, { r: ROTATE_HORIZONTAL }], ['l', 65, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 130, { x: 0, r: ROTATE_VERTICAL }], ['l', 154, 130, { x: 0, f: 1 }], ] } ] ), 'g': generateFontData( 600, 232, 338, 10, 2, -117, -117, JSON.parse(JSON.stringify(DATA_LG)) ), 'h': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LH)) ), 'i': generateFontData( 200, 0, 352, 0, 0, 0, 0, [{ d: 1, v: [ ['a', 0, 90, { y: -3 }], ] }, { d: 1, v: [ ['m', 0, 352, { y: 0, f: 1 }], ['l', 0, 130, { y: -3 }], ] }] ), 'j': generateFontData( 220, 115.9, 352, -60, -60, 0, 0, [{ d: 1, v: [ ['a', 0, 90, { y: -3 }], ] }, { d: 1, v: [ ['m', 0 - 115.9, 317 + 127, { x: 0.4, y: 0.63, r: getCurveR(0 - 115.9, 317 + 127, 12.6 - 115.9, 327.4 + 127, 29.6 - 115.9, 333.2 + 127, 45.9 - 115.9, 334.2 + 127, 0), f: 1 }], ['b', 12.6 - 115.9, 327.4 + 127, 29.6 - 115.9, 333.2 + 127, 45.9 - 115.9, 334.2 + 127, { x: 0.4, y: 0.63, r: ROTATE_VERTICAL }], ['b', 84.5 - 115.9, 336.5 + 127, 115.9 - 115.9, 308.1 + 127, 115.9 - 115.9, 269.4 + 127, { x: 0.4, y: 0.63, r: ROTATE_HORIZONTAL }], ['l', 115.9 - 115.9, 0 + 127 + 3, { y: -3 }], ] }] ), 'k': generateFontData( 450, 164, 352, -10, -10, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { y: 0, r: ROTATE_HORIZONTAL }], ['l', 0, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 160, 130, { x: 0.7, y: 0, r: getR(164, 130, 0, 106 + 130 - VERTEX_GAP2), f: 1 }], ['l', 0, 106 + 130 - VERTEX_GAP2, { r: ROTATE_VERTICAL, p: 1 }], ['l', 0, 106 + 130 + VERTEX_GAP2, { r: ROTATE_VERTICAL, p: 1, v: 1 }], ['l', 164, 352, { x: 0.7, y: 0.7, f: 1 }], ] } ] ), 'l': generateFontData( 200, 0, 352, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 0, 352, { y: 0, f: 1 }], ['l', 0, 0, { y: 0 }], ] }] ), 'm': generateFontData( 740, 150 + 150, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 130, { y: -3.6 }], ['l', 0, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 75 + 123, { y: 0, r: ROTATE_HORIZONTAL, p: 1 }], ['b', 0, 33.6 + 123, 33.6, 0 + 123, 75, 0 + 123, { r: ROTATE_VERTICAL }], ['b', 116.4, 0 + 123, 150, 33.6 + 123, 150, 75 + 123, { r: ROTATE_HORIZONTAL }], ['l', 150, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0 + 150, 75 + 123, { y: 0, r: ROTATE_HORIZONTAL, p: 1 }], ['b', 0 + 150, 33.6 + 123, 33.6 + 150, 0 + 123, 75 + 150, 0 + 123, { r: ROTATE_VERTICAL }], ['b', 116.4 + 150, 0 + 123, 150 + 150, 33.6 + 123, 150 + 150, 75 + 123, { r: ROTATE_HORIZONTAL }], ['l', 150 + 150, 352, { y: 0, f: 1 }], ] } ] ), 'n': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LN)) ), 'o': generateFontData( 580, 232, 232, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LO)) ), 'p': generateFontData( 600, 232, 338, -10, -2, -117, -117, [{ d: -1, v: [ ['m', 0, 5, { y: -2.8 }], ['l', 0, 116, { r: ROTATE_NONE }], ['b', 0, 180.1, 51.9, 232, 116, 232, { r: ROTATE_VERTICAL }], ['b', 180.1, 232, 232, 180.1, 232, 116, { r: ROTATE_HORIZONTAL }], ['b', 232, 51.9, 180.1, 0, 116, 0, { r: ROTATE_VERTICAL }], ['b', 51.9, 0, 0, 51.9, 0, 116, { r: ROTATE_HORIZONTAL }], ['l', 0, 338, { y: 0, f: 1 }], ] }] ), 'q': generateFontData( 600, 232, 338, 10, 2, -117, -117, [{ d: -1, v: [ ['m', 232, 5, { y: -2.8 }], ['l', 232, 116, { r: ROTATE_NONE }], ['b', 232, 180.1, 180.1, 232, 116, 232, { r: ROTATE_VERTICAL }], ['b', 51.9, 232, 0, 180.1, 0, 116, { r: ROTATE_HORIZONTAL }], ['b', 0, 51.9, 51.9, 0, 116, 0, { r: ROTATE_VERTICAL }], ['b', 180.1, 0, 232, 51.9, 232, 116, { r: ROTATE_HORIZONTAL }], ['l', 232, 338, { y: 0, f: 1 }], ] }] ), 'r': generateFontData( 340, 119.2, 352, -20, -20, 0, 0, [{ d: -1, v: [ ['m', 0, 130, { y: -3.3 }], ['l', 0, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 57 + 124, { r: ROTATE_HORIZONTAL, p: 1, }], ['b', 0, 57 + 124, 41.9, -22.8 + 124, 119.2, 4.5 + 124, { x: 0, y: 2, r: getCurveR(119.2, 4.5 + 124, 41.9, -22.8 + 124, 0, 57 + 124, 119.2, 4.5 + 124, 0), f: 1 }], ] } ] ), 's': generateFontData( 400, 224 * 0.642, 360 * 0.642, 0, 0, -64, -64, JSON.parse(JSON.stringify(DATA_LS)) ), 't': generateFontData( 356, 232, 352, -30, -30, 0, 0, [{ d: -1, v: [ ['m', 65, 0, { y: 0 }], ['l', 65, 298.2 + 6], ['b', 65, 326.9 + 6, 88.2, 350.1 + 6, 116.9, 350.1 + 6, { r: ROTATE_VERTICAL }], ['b', 139.2, 350.1 + 6, 159.3, 337 + 6, 166.6, 317.1, { x: 0, f: 1 }] ] }, { d: -1, v: [ ['m', 0, 130, { x: 0, r: ROTATE_VERTICAL }], ['l', 154, 130, { x: 0, f: 1 }], ] } ] ), 'u': generateFontData( 520, 182, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_LU)) ), 'v': generateFontData( 500, 200, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 130, { x: 0.6, y: -3, r: getR(0, 130, 100 - VERTEX_GAP2, 352) }], ['l', 100 - VERTEX_GAP2, 352, { r: getR(0, 130, 100 - VERTEX_GAP2, 352), f: 1 }], ['l', 100 + VERTEX_GAP2, 352, { r: getR(100 + VERTEX_GAP2, 352, 200, 130), f: 1, v: 1 }], ['l', 200, 130, { x: 0.6, y: -3, f: 1 }], ] }] ), 'w': generateFontData( 700, 310, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 130, { x: 0.6, y: -3, r: getR(0, 130, 78 - VERTEX_GAP2, 352) }], ['l', 78 - VERTEX_GAP2, 352, { r: getR(0, 130, 78 - VERTEX_GAP2, 352), f: 1 }], ['l', 78 + VERTEX_GAP2, 352, { r: getR(78 + VERTEX_GAP2, 352, 155 - VERTEX_GAP2, 130), f: 1, v: 1 }], ['l', 155 - VERTEX_GAP2, 130, { y: 1, r: getR(78 + VERTEX_GAP2, 352, 155 - VERTEX_GAP2, 130), f: 1 }], ['l', 155 + VERTEX_GAP2, 130, { y: 1, r: getR(155 + VERTEX_GAP2, 130, 233 - VERTEX_GAP2, 352), f: 1, v: 1 }], ['l', 233 - VERTEX_GAP2, 352, { r: getR(155 + VERTEX_GAP2, 130, 233 - VERTEX_GAP2, 352), f: 1 }], ['l', 233 + VERTEX_GAP2, 352, { r: getR(233 + VERTEX_GAP2, 352, 310, 130), f: 1, v: 1 }], ['l', 310, 130, { x: 0.6, y: -3, f: 1 }], ] }] ), 'x': generateFontData( 490, 210, 352, 0, 0, 0, -7, [{ d: -1, v: [ ['m', 10, 130, { x: 0.5, y: -1, r: getR(10, 130, 210, 352) }], ['l', 210, 352, { x: 0.5, y: 0.5, f: 1 }] ] }, { d: -1, v: [ ['m', 200, 130, { x: 0.5, y: -1, r: getR(200, 130, 0, 352) }], ['l', 0, 352, { x: 0.5, y: 0.5, f: 1 }] ] } ] ), 'y': generateFontData( 500, 225.5, 331.5, 10, 10, -119, -119, JSON.parse(JSON.stringify(DATA_LY)) ), 'z': generateFontData( // 232, 224 420, 172, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 6, 130, { x: -0.5, y: 1, r: ROTATE_VERTICAL, }], ['l', 166, 130, { x: 1.8, y: 1, r: ROTATE_VERTICAL, f: 1 }], ['l', 166, 130 + VERTEX_GAP, { x: 1.8, y: 1, r: ROTATE_HORIZONTAL, p: 1, v: 1 }], ['l', 0, 352 - VERTEX_GAP, { x: 1.7, r: ROTATE_HORIZONTAL, p: 1 }], ['l', 0, 352, { x: 1.7, r: ROTATE_VERTICAL, f: 1, v: 1 }], ['l', 172, 352, { x: -0.4, r: ROTATE_VERTICAL, f: 1 }] ] }] ) }; ================================================ FILE: src/font/number.js ================================================ import { generateFontData, ROTATE_HORIZONTAL, ROTATE_VERTICAL, ROTATE_NONE, VERTEX_GAP, getR, getCurveR } from './util.js'; export const NUMBER = { '0': generateFontData( 660, 270, 360, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 270, 180, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['b', 270, 279.4, 209.6, 360, 135, 360, { r: ROTATE_VERTICAL }], ['b', 60.4, 360, 0, 279.4, 0, 180, { r: ROTATE_HORIZONTAL }], ['b', 0, 80.6, 60.4, 0, 135, 0, { r: ROTATE_VERTICAL }], ['b', 209.6, 0, 270, 80.6, 270, 180, { r: ROTATE_HORIZONTAL, c: 1 }], ] }] ), '1': generateFontData( 380, 76, 352, 15, 15, 0, 0, [{ d: -1, v: [ ['m', 0, 51, { x: -2, y: 2, r: getR(0, 51, 76 - VERTEX_GAP, 0) }], ['l', 76 - VERTEX_GAP, 0, { r: ROTATE_HORIZONTAL, p: 1 }], ['l', 76, 0, { r: ROTATE_HORIZONTAL, f: 1, v: 1 }], ['l', 76, 352, { y: 0, f: 1 }], ] }] ), '2': generateFontData( 580, 210, 356, 0, 0, 2, 2, [{ d: -1, v: [ ['m', 3.9, 68.8, { x: 1.2, y: 1.2, r: getCurveR(3.9, 68.8, 16.7, 29, 54.2, 3.1, 98.2, 0.2, 0) }], ['b', 16.7, 29, 54.2, 3.1, 98.2, 0.2], ['b', 151.8, -3.3, 208.5, 38.3, 198.9, 100.1], ['b', 197.1, 111.8, 196.4, 142.4, 101.5, 235.2], ['b', 11.4, 323.2, 0, 356 - VERTEX_GAP, 0, 356 - VERTEX_GAP, { r: ROTATE_NONE }], ['l', 0, 356 - VERTEX_GAP, { r: ROTATE_VERTICAL, p: 1 }], ['l', 0, 356, { r: ROTATE_VERTICAL, f: 1, v: 1 }], ['l', 210, 356, { x: -0.5, f: 1 }], ] }] ), '3': generateFontData( 580, 222.1, 360, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 10.7, 66.3, { r: getCurveR(10.7, 66.3, 11.2, 64.8, 11.7, 63.3, 12.3, 61.8, 0) }], ['b', 11.2, 64.8, 11.7, 63.3, 12.3, 61.8, { r: ROTATE_NONE }], ['b', 25.8, 25.9, 64.5, 0, 110.1, 0, { r: ROTATE_VERTICAL }], ['b', 167, 0, 213.1, 40.3, 213.1, 90, { r: ROTATE_HORIZONTAL }], ['b', 213.1, 139.7, 167, 180, 110.1, 179.9, { r: ROTATE_VERTICAL, f: 1 }], ['l', 100.1, 179.9, { x: -5, y: 1, r: ROTATE_VERTICAL, f: 1 }], ['l', 110.1, 180, { r: ROTATE_VERTICAL, p: 1 }], ['b', 172, 180, 222.1, 220.3, 222.1, 270, { r: ROTATE_HORIZONTAL }], ['b', 222.1, 319.7, 172, 360, 110.1, 360, { r: ROTATE_VERTICAL }], ['b', 56.9, 360, 12.4, 330.2, 1, 290.3, { f: 1 }], ] }] ), '4': generateFontData( 596, 236, 352, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 175, 352, { y: 0, f: 1 }], ['l', 175, 0, { f: 1 }], ['l', 175 - VERTEX_GAP, 0, { r: ROTATE_VERTICAL, p: 1, v: 1 }], ['l', 0, 276 - VERTEX_GAP, { r: ROTATE_HORIZONTAL, p: 1 }], ['l', 0, 276, { r: ROTATE_VERTICAL, f: 1, v: 1 }], ['l', 236, 276, { x: -0.5 }], ] }] ), '5': generateFontData( 596, 208.5, 356, 0, -5, -2, -2, [{ d: 1, v: [ ['m', 0, 295.7, { r: getCurveR(0, 295.7, 15.3, 333.8, 52.2, 356.2, 97.5, 356, 0), f: 1 }], ['b', 15.3, 333.8, 52.2, 356.2, 97.5, 356, { r: ROTATE_VERTICAL }], ['b', 159.1, 355.7, 206.1, 306.9, 208.5, 240.8, { r: ROTATE_HORIZONTAL }], ['b', 210.9, 173.9, 162.7, 120.8, 97.5, 125.6, { r: ROTATE_VERTICAL }], ['b', 59.4, 128.4, 25.5, 145.8, 5.6, 176.4, { f: 1 }], ['l', 5.6, 176.4, { r: ROTATE_NONE }], ['l', 5.6 - VERTEX_GAP, 176.4, { r: ROTATE_HORIZONTAL, p: 1, v: 1 }], ['l', 11.5, 0, { r: ROTATE_VERTICAL, f: 1 }], ['l', 193.5, 0, { x: -0.5 }], ] }] ), '6': generateFontData( 596, 215.8, 360, 0, -2, 0, 0, [{ d: 1, v: [ ['m', 7.6, 272.3, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['b', 6.4, 265.8, 5.8, 259.1, 5.8, 252.2, { r: ROTATE_HORIZONTAL }], ['b', 5.8, 192.6, 52.8, 144.2, 110.8, 144.2, { r: ROTATE_VERTICAL }], ['b', 168.7, 144.2, 215.8, 192.6, 215.8, 252.2, { r: ROTATE_HORIZONTAL }], ['b', 215.8, 311.9, 168.7, 360, 110.8, 360, { r: ROTATE_VERTICAL }], ['b', 59.5, 360, 16.8, 322.4, 7.6, 272.4, { r: ROTATE_NONE }], ['b', 7.6, 272.4, -44.1, 8.8, 122.2, 0.2], ['b', 165.5, -2.1, 193.8, 21, 212.1, 56.4], ] }] ), '7': generateFontData( 540, 213, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: 0, r: ROTATE_VERTICAL }], ['l', 213, 0, { r: ROTATE_VERTICAL, f: 1 }], ['l', 213, 0.1, { r: ROTATE_NONE }], ['l', 72.7, 352, { y: 0.1, f: 1 }], ] }] ), '8': generateFontData( 596, 224, 360, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 112, 180, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['b', 50.1, 180, 0, 220.3, 0, 270, { r: ROTATE_HORIZONTAL }], ['b', 0, 319.7, 50.1, 360, 112, 360, { r: ROTATE_VERTICAL }], ['b', 173.9, 360, 224, 319.7, 224, 270, { r: ROTATE_HORIZONTAL }], ['b', 224, 220.3, 173.9, 180, 112, 180, { r: ROTATE_VERTICAL }], ['b', 55.1, 180, 9, 139.7, 9, 90, { r: ROTATE_HORIZONTAL }], ['b', 9, 40.3, 55.1, 0, 112, 0, { r: ROTATE_VERTICAL }], ['b', 168.9, 0, 215, 40.3, 215, 90, { r: ROTATE_HORIZONTAL }], ['b', 215, 139.7, 168.9, 180, 112, 180, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ] }] ), '9': generateFontData( 596, 215.8, 360, 0, -2, 0, 0, [{ d: -1, v: [ ['m', 208.2, 88, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['b', 209.4, 94.5, 210, 101.2, 210, 108, { r: ROTATE_HORIZONTAL }], ['b', 210, 167.6, 163, 216, 105, 216, { r: ROTATE_VERTICAL }], ['b', 47, 216, -0, 167.6, 0, 108, { r: ROTATE_HORIZONTAL }], ['b', 0, 48.4, 47, -0, 105, 0, { r: ROTATE_VERTICAL }], ['b', 156.3, 0, 199, 37.8, 208.2, 87.8, { r: ROTATE_NONE }], ['b', 208.2, 87.8, 259.8, 351.4, 93.5, 360], ['b', 50.3, 362.3, 21.9, 339.2, 3.6, 303.8, { f: 1 }], ] }] ) }; ================================================ FILE: src/font/special.js ================================================ import { generateFontData, ROTATE_HORIZONTAL, ROTATE_VERTICAL, ROTATE_NONE, getR, getCurveR, VERTEX_GAP2 } from './util.js'; export const SPECIAL = { ' ': generateFontData( 336, 0, 0, 0, 0, 0, 0, [{ d: 1, v: [] }] ), 'tofu': generateFontData( 672, 232, 352, 0, 0, 0, 0, [{ //c: 'square', d: -1, v: [ ['m', 0, 0, { r: ROTATE_HORIZONTAL }], ['l', 232, 0, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 232, 352, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0, 352, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0, 0, { r: ROTATE_HORIZONTAL, p: 1, f: 1, c: 1 }], ] }, { d: 1, v: [ ['m', 0, 0, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['l', 232, 352, { r: ROTATE_NONE }], ] } ] ), '?': generateFontData( 520, 190.348, 360, 0, -5, 0, 0, [{ d: 1, v: [ ['a', 190.348 / 2 - 6, 356], ] }, { d: -1, v: [ ['m', 0, 87.8, { r: getCurveR(0, 87.8, 12, -2.3, 99.1, 0, 0, 87.8, 0) }], ['b', 0, 87.8, 12, -2.3, 99.1, 0, { r: ROTATE_VERTICAL }], ['b', 186.2, 2.4, 204.5, 75.2, 180.9, 121.4], ['b', 157.3, 167.6, 119.7, 178.3, 97.4, 223.2], ['b', 90.5, 237.1, 88.1, 249.8, 88, 260.8, { r: ROTATE_HORIZONTAL, f: 1 }], ] }] ), '¿': generateFontData( 520, 190.348, 360, 0, -5, 0, 0, [{ d: 1, v: [ ['a', 190.348 / 2 + 6, 356 - 451 + 188], ] }, { d: -1, v: [ ['m', 190.3, 173.0 + 188, { r: getCurveR(190.3, 173.0 + 188, 178.3, 263.1 + 188, 91.2, 260.8 + 188, 190.3, 173.0 + 188, 0) }], ['b', 190.3, 173.0 + 188, 178.3, 263.1 + 188, 91.2, 260.8 + 188, { r: ROTATE_VERTICAL }], ['b', 4.1, 258.4 + 188, -14.2, 185.6 + 188, 9.4, 139.4 + 188], ['b', 33.0, 93.2 + 188, 70.6, 82.5 + 188, 92.9, 37.6 + 188], ['b', 99.8, 23.7 + 188, 102.2, 11.0 + 188, 102.3, 0.0 + 188, { r: ROTATE_HORIZONTAL, f: 1 }], ] }] ), '!': generateFontData( 465, 8, 355, 0, -5, 0, 0, [{ d: 1, v: [ ['a', 8 / 2, 356], ] }, { d: -1, v: [ ['m', 4, 0, { y: 0 }], ['l', 4, 260.8, { f: 1 }], ] }] ), '¡': generateFontData( 465, 8, 355, 0, -5, 0, 0, [{ d: 1, v: [ ['a', 8 / 2, 356 - 451 + 188], ] }, { d: -1, v: [ ['m', 4, 0 + 188], ['l', 4, 260.8 + 188, { f: 1, y: 0.3 }], ] }] ), '$': generateFontData( 568, 224, 360, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 212, 51.3, { r: getCurveR(0, 295.4, 17.6, 332.1, 58.3, 360, 110.3, 360, 0), f: 1 }], ['b', 196.5, 20.5, 158.4, 0, 114.8, 0], ['b', 57.3, 0, 13.3, 29.8, 12, 84.4], ['b', 10.9, 130.6, 47.3, 157.7, 112.4, 173.3], ['b', 180.7, 189.6, 224.2, 214.7, 224, 271], ['b', 223.8, 329.6, 173.9, 360, 110.3, 360], ['b', 58.3, 360, 17.6, 332.1, 0, 295.4, { f: 1 }], ] }, { d: -1, v: [ ['m', 112, 0 - 30, { y: 0 }], ['l', 112, 360 + 30, { y: 0, f: 1 }], ] }] ), '@': generateFontData( 820, 343.425, 360, 0, 0, -30, -30, [{ d: -1, v: [ ['m', 251.9, 92.9, { r: getR(251.9, 92.9, 238.5, 181.7) }], ['l', 238.5, 181.7, { r: ROTATE_NONE }], ['b', 227.8, 236, 194.7, 267.2, 143.7, 259.2], ['b', 99.1, 252.2, 87.7, 208.5, 90.1, 177.5], ['b', 92.5, 148.4, 118.1, 91, 183.3, 99.1], ['b', 251, 107.5, 238.5, 181.7, 238.5, 181.7, { r: ROTATE_NONE }], ['l', 232.5, 221.5], ['b', 232.5, 221.5, 227.2, 257.6, 256, 263.6], ['b', 284.9, 269.7, 309, 241.3, 309, 241.3, { r: ROTATE_NONE }], ['b', 309, 241.3, 343.4, 209, 343.4, 146.7], ['b', 343.4, 84.3, 297.4, 3.5, 178.6, 0.1], ['b', 59.7, -3.4, -5.3, 105.2, 0.3, 203.4], ['b', 6.1, 303.7, 93.2, 354.5, 175.5, 359.5], ['b', 175.5, 359.5, 246.5, 364.9, 302.7, 339.8, { f: 1 }], ] }] ), '#': generateFontData( 760, 290 + 24, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 70 + 47, 0, { y: 0, r: getR(70 + 47, 0, 0 + 47, 352) }], ['l', 0 + 47, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 70 + 150 + 47, 0, { y: 0, r: getR(70 + 150 + 47, 0, 0 + 150 + 47, 352) }], ['l', 0 + 150 + 47, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0 + 24, 117, { x: 0, r: ROTATE_VERTICAL }], ['l', 290 + 24, 117, { x: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 352 - 117, { x: 0, r: ROTATE_VERTICAL }], ['l', 290, 352 - 117, { x: 0, f: 1 }], ] }] ), '%': generateFontData( 920, 352 + 36, 360, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 289.1 + 18, 5.1, { x: 0, y: 0, r: getR(289.1 + 18, 5.1, 62.9 + 18, 354.9) }], ['l', 62.9 + 18, 354.9, { x: 0, y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 146, 73, { r: ROTATE_HORIZONTAL, p: 1, }], ['b', 146, 113.3, 113.3, 146, 73, 146, { r: ROTATE_VERTICAL }], ['b', 32.7, 146, 0, 113.3, 0, 73, { r: ROTATE_HORIZONTAL }], ['b', 0, 32.7, 32.7, 0, 73, 0, { r: ROTATE_VERTICAL }], ['b', 113.3, 0, 146, 32.7, 146, 73, { r: ROTATE_HORIZONTAL, c: 1, f: 1 }], ] }, { d: -1, v: [ ['m', 352 + 36, 287, { r: ROTATE_HORIZONTAL, p: 1, }], ['b', 352 + 36, 327.3, 319.3 + 36, 360, 279 + 36, 360, { r: ROTATE_VERTICAL }], ['b', 238.7 + 36, 360, 206 + 36, 327.3, 206 + 36, 287, { r: ROTATE_HORIZONTAL }], ['b', 206 + 36, 246.7, 238.7 + 36, 214, 279 + 36, 214, { r: ROTATE_VERTICAL }], ['b', 319.3 + 36, 214, 352 + 36, 246.7, 352 + 36, 287, { r: ROTATE_HORIZONTAL, c: 1, f: 1 }], ] }] ), '^': generateFontData( 596, 88 + 88, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 150, { r: getR(0, 150, 88 - VERTEX_GAP2, 0) }], ['l', 88 - VERTEX_GAP2, 0, { r: getR(0, 150, 88 - VERTEX_GAP2, 0), f: 1 }], ['l', 88 + VERTEX_GAP2, 0, { r: getR(88 + VERTEX_GAP2, 0, 88 + 88, 150), f: 1, v: 1 }], ['l', 88 + 88, 150, { f: 1 }] ] }] ), '·': generateFontData( 231, 8, 355, 0, 0, 0, 0, [{ d: 1, v: [ ['a', 8 / 2, 355 - 1.5 - 170], ] }] ), '×': generateFontData( 712, 176.8, 176.8, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: 0, y: 0, r: getR(0, 0, 176.8, 176.8), }], ['l', 176.8, 176.8, { x: 0, y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 176.8, 0, { x: 0, y: 0, r: getR(176.8, 0, 0, 176.88), }], ['l', 0, 176.8, { x: 0, y: 0, f: 1 }], ] }] ), '÷': generateFontData( 712, 188, 0, 0, 0, 0, 0, [{ d: 1, v: [ ['a', (188 / 2), 110], ] }, { d: 1, v: [ ['a', (188 / 2), -110], ] }, { d: -1, v: [ ['m', 0, 0, { x: 0, y: 0, r: ROTATE_VERTICAL }], ['l', 188, 0, { x: 0, y: 0, f: 1 }], ] } ] ), '«': generateFontData( 896, 310, 236, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 150, 236, { r: getR(150, 236, 0, 118 + VERTEX_GAP2), f: 1 }], ['l', 0, 118 + VERTEX_GAP2, { r: getR(150, 236, 0, 118 + VERTEX_GAP2), f: 1 }], ['l', 0, 118 - VERTEX_GAP2, { r: getR(0, 118 - VERTEX_GAP2, 150, 0), f: 1, v: 1 }], ['l', 150, 0] ] }, { d: 1, v: [ ['m', 150 + 160, 236, { r: getR(150 + 160, 236, 0 + 160, 118 + VERTEX_GAP2), f: 1 }], ['l', 0 + 160, 118 + VERTEX_GAP2, { r: getR(150 + 160, 236, 0 + 160, 118 + VERTEX_GAP2), f: 1 }], ['l', 0 + 160, 118 - VERTEX_GAP2, { r: getR(0 + 160, 118 - VERTEX_GAP2, 150 + 160, 0), f: 1, v: 1 }], ['l', 150 + 160, 0] ] }] ), '»': generateFontData( 896, 310, 236, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 0, 236, { r: getR(0, 236, 150, 118 + VERTEX_GAP2), f: 1 }], ['l', 150, 118 + VERTEX_GAP2, { r: getR(0, 236, 0, 118 + VERTEX_GAP2), f: 1 }], ['l', 150, 118 - VERTEX_GAP2, { r: getR(150, 118 - VERTEX_GAP2, 0, 0), f: 1, v: 1 }], ['l', 0, 0] ] }, { d: 1, v: [ ['m', 0 + 160, 236, { r: getR(0 + 160, 236, 150 + 160, 118 + VERTEX_GAP2), f: 1 }], ['l', 150 + 160, 118 + VERTEX_GAP2, { r: getR(0, 236, 0, 118 + VERTEX_GAP2), f: 1 }], ['l', 150 + 160, 118 - VERTEX_GAP2, { r: getR(150 + 160, 118 - VERTEX_GAP2, 0 + 160, 0), f: 1, v: 1 }], ['l', 0 + 160, 0] ] }] ), '&': generateFontData( 660, 259.191, 360, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 257.9, 355, { x: 0.5, y: 0.5, r: getR(257.9, 355, 52.8, 135.3), f: 1 }], ['l', 52.8, 135.3], ['b', 52.8, 135.3, -2.2, 79.5, 46.6, 26.7], ['b', 46.6, 26.7, 68.1, 0, 101.8, 0, { r: ROTATE_VERTICAL }], ['b', 137.2, 0, 174.1, 21.1, 181.2, 65.3], ['b', 188.6, 111.7, 142.6, 142.9, 108.9, 162.9], ['b', 75.2, 182.8, 40.8, 211.4, 40.8, 211.4, { r: ROTATE_NONE }], ['b', 35, 217.1, -34.7, 273.7, 22.2, 330.5], ['b', 22.2, 330.5, 48.1, 360, 93.4, 360, { r: ROTATE_VERTICAL }], ['b', 138.6, 360, 212.2, 322, 259.2, 200.5], ] }] ), '*': generateFontData( 558, 183.597, 212, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 91.8, 0, { x: 0, y: 0 }], ['l', 91.8, 212, { x: 0, y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 53, { x: 0, y: 0, r: getR(0, 53, 183.6, 159) }], ['l', 183.6, 159, { x: 0, y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 159, { x: 0, y: 0, r: getR(0, 159, 183.6, 53) }], ['l', 183.6, 53, { x: 0, y: 0, f: 1 }], ] }] ), '+': generateFontData( 712, 250, 250, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 125, 0, { x: 0, y: 0, }], ['l', 125, 250, { x: 0, y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 125, { x: 0, y: 0, r: ROTATE_VERTICAL }], ['l', 250, 125, { x: 0, y: 0, f: 1 }], ] }] ), '=': generateFontData( 712, 216, 86, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: 0, y: 0, r: ROTATE_VERTICAL }], ['l', 216, 0, { x: 0, y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 86, { x: 0, y: 0, r: ROTATE_VERTICAL }], ['l', 216, 86, { x: 0, y: 0, f: 1 }], ] }] ), '-': generateFontData( 712, 188, 0, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: 0, y: 0, r: ROTATE_VERTICAL }], ['l', 188, 0, { x: 0, y: 0, f: 1 }], ] }] ), '_': generateFontData( 481, 235, 400, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 400, { x: 0, y: 0, r: ROTATE_VERTICAL }], ['l', 235, 400, { x: 0, y: 0, f: 1 }], ] }] ), ':': generateFontData( 231, 8, 355, 0, 0, 0, 0, [{ d: 1, v: [ ['a', 8 / 2, 355 - 1.5 - 170], ] }, { d: 1, v: [ ['a', 8 / 2, 355 - 1.5], ] } ] ), ';': generateFontData( 231, 8, 355, 0, 0, 0, 0, [{ d: 1, v: [ ['a', 8 / 2, 355 - 1.5 - 170], ] }, { d: -1, v: [ ['m', 8 / 2, 350, { x: 0, y: 2, r: getR(8 / 2, 350, 8 / 2 - 10, 80 + 350) }], ['l', 8 / 2 - 10, 80 + 350, { x: 0, y: 0.5, f: 1 }], ] }] ), '.': generateFontData( 231, 8, 355, 0, 0, 0, 0, [{ d: 1, v: [ ['a', 8 / 2, 355 - 1.5], ] }] ), ',': generateFontData( 231, 10, 355, 10, 10, 0, 0, [{ d: -1, v: [ ['m', 10, 350, { x: 0, y: 2, r: getR(10, 350, 0, 80 + 350) }], ['l', 0, 80 + 350, { x: 0, y: 0.5, f: 1 }], ] }] ), "'": generateFontData( 173, 0, 360, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: 0, y: 0 }], ['l', 0, 80, { x: 0, y: 0, f: 1 }], ] }] ), '"': generateFontData( 297, 60, 360, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: -1.5, y: 0 }], ['l', 0, 80, { x: -1.5, y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 60, 0, { x: -1.5, y: 0 }], ['l', 60, 80, { x: -1.5, y: 0, f: 1 }], ] }] ), '~': generateFontData( 731, 199.391, 47.063, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 199.4, 20.7, { x: 0, y: 0, r: getCurveR(199.4, 20.7, 187.6, 36.6, 168.2, 47.1, 148.2, 47.1, 0), f: 1 }], ['b', 187.6, 36.6, 168.2, 47.1, 148.2, 47.1, { x: 0, y: 0, r: ROTATE_VERTICAL }], ['b', 129.1, 47.1, 112.1, 36.6, 95.3, 25.5, { x: 0, y: 0 }], ['b', 76.8, 13.2, 59.1, 0, 39.6, 0, { x: 0, y: 0, r: ROTATE_VERTICAL }], ['b', 22.3, 0, 10.9, 8.9, 0, 20, { x: 0, y: 0 }], ] }] ), '(': generateFontData( 365, 107.865, 360, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 107.9, 360, { y: 0.8, r: getCurveR(107.9, 360, 39.7, 321.1, 0, 259.8, 0, 182.9, 0), f: 1 }], ['b', 39.7, 321.1, 0, 259.8, 0, 182.9, { y: 0.8, r: ROTATE_HORIZONTAL }], ['b', 0, 100.2, 39.7, 38.9, 107.9, 0, { y: 0.8 }], ] }] ), ')': generateFontData( 365, 107.865, 360, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { y: 0.8, r: getCurveR(0, 0, 68.2, 38.9, 107.9, 100.2, 107.9, 177, 0) }], ['b', 68.2, 38.9, 107.9, 100.2, 107.9, 177, { y: 0.8, r: ROTATE_HORIZONTAL }], ['b', 107.9, 259.8, 68.2, 321.1, 0, 360, { y: 0.8, f: 1 }], ] }] ), '{': generateFontData( 385, 107.865, 360, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 94.5, 360, { x: -0.5, r: ROTATE_VERTICAL }], ['l', 77.9, 360, { x: -0.5 }], ['b', 57.4, 360, 37, 343, 37, 310.7, { x: -0.5 }], ['l', 37, 233.4, { x: -0.5 }], ['b', 37, 207.9, 24.3, 183.7, 3.8, 180.7, { x: -0.5, r: ROTATE_VERTICAL }], ['l', 3.8, 179.8, { x: -0.5, r: ROTATE_VERTICAL, p: 1 }], ['b', 24.3, 176.8, 37, 153.1, 37, 126.7, { x: -0.5 }], ['l', 37, 49.4, { x: -0.5 }], ['b', 37, 17.1, 57.4, 0.1, 77.9, 0.1, { x: -0.5 }], ['l', 94.5, 0.1, { x: -0.5, }], ] }] ), '}': generateFontData( 385, 107.865, 360, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 13.4, 0.1, { x: -0.5, r: ROTATE_VERTICAL }], ['l', 30, 0.1, { x: -0.5 }], ['b', 50.4, 0.1, 70.8, 17.1, 70.8, 49.4, { x: -0.5 }], ['l', 70.8, 126.7, { x: -0.5 }], ['b', 70.8, 153.1, 83.6, 176.8, 104, 179.8, { x: -0.5, r: ROTATE_VERTICAL }], ['l', 104, 180.7, { x: -0.5, r: ROTATE_VERTICAL, p: 1 }], ['b', 83.6, 183.7, 70.8, 207.9, 70.8, 233.4, { x: -0.5 }], ['l', 70.8, 310.7, { x: -0.5 }], ['b', 70.8, 343, 50.4, 360, 30, 360, { x: -0.5 }], ['l', 13.4, 360, { x: -0.5 }], ] }] ), '[': generateFontData( 365, 66, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 66, 0, { x: -1, r: ROTATE_VERTICAL }], ['l', 0, 0, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0, 352, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 66, 352, { x: -1, f: 1 }], ] }] ), ']': generateFontData( 365, 66, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: -1, r: ROTATE_VERTICAL }], ['l', 66, 0, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 66, 352, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0, 352, { x: -1, f: 1 }], ] }] ), '<': generateFontData( 423, 90, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 90, 0, { x: -1, y: 0.3, r: getR(90, 0, 0, 176) }], ['l', 0, 176, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 90, 352, { x: -1, y: 0.3, f: 1 }], ] }] ), '>': generateFontData( 423, 90, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: -1, y: 0.3, r: getR(0, 0, 90, 176) }], ['l', 90, 176, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0, 352, { x: -1, y: 0.3, f: 1 }], ] }] ), '/': generateFontData( 433, 130, 352, 0, 0, 0, 0, [{ d: 1, v: [ ['m', 0, 352, { r: getR(0, 352, 130, 0), f: 1, y: 0 }], ['l', 130, 0, { y: 0 }] ] }] ), 'þ': generateFontData( 600, 232, 338, -10, -2, -117, -117, [{ d: -1, v: [ ['m', 0, -106, { y: 0 }], ['l', 0, 116, { r: ROTATE_NONE }], ['b', 0, 180.1, 51.9, 232, 116, 232, { r: ROTATE_VERTICAL }], ['b', 180.1, 232, 232, 180.1, 232, 116, { r: ROTATE_HORIZONTAL }], ['b', 232, 51.9, 180.1, 0, 116, 0, { r: ROTATE_VERTICAL }], ['b', 51.9, 0, 0, 51.9, 0, 116, { r: ROTATE_HORIZONTAL }], ['l', 0, 338, { y: 0, f: 1 }], ] }] ), 'Þ': generateFontData( 520, 162, 352, -5, -70, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: 0, y: 0, r: ROTATE_HORIZONTAL, }], ['l', 0, 352, { x: 0, y: 0, r: ROTATE_HORIZONTAL, f: 1 }], ] }, { d: 1, v: [ ['m', 0, 281.6, { x: 0, r: ROTATE_VERTICAL, f: 1, p: 1 }], ['l', 57, 281.6, { x: -0.5, r: ROTATE_VERTICAL, f: 1 }], ['b', 115.0, 281.6, 162.0, 233.4, 162.0, 175.4, { x: -0.5, r: ROTATE_HORIZONTAL }], ['b', 162.0, 117.4, 115.0, 70.4, 57.0, 70.4, { x: -0.5, r: ROTATE_VERTICAL }], ['l', 0, 70.4, { x: 0, r: ROTATE_VERTICAL, f: 1, p: 1 }], ] } ] ), 'ß': generateFontData( 596, 209, 352, -10, -10, 0, 0, [{ d: 1, v: [ ['m', 0.0, 348.3, { r: ROTATE_HORIZONTAL, f: 1, x: 0, y: 0 }], ['l', 0.0, 104.3, { x: 0 }], ['b', 0.0, 46.0, 36.0, 0.0, 98.9, 0.0, { x: 0 }], ['b', 145.2, 0.0, 191.0, 27.9, 191.0, 81.0, { x: 1 }], ['b', 191.0, 110.7, 165.6, 131.8, 151.8, 140.9], ['l', 140.0, 148.8], ['b', 120.6, 161.7, 110.8, 172.8, 110.8, 185.5], ['b', 110.8, 206.7, 131.6, 213.8, 140.0, 217.5], //['l', 163.7, 228.6], ['b', 190.6, 241.1, 211.0, 262.7, 211.0, 289.6], ['b', 211.0, 329.5, 174.8, 352.0, 142.5, 352.0], ['b', 97.3, 352.0, 75.2, 319.7, 72.3, 289.3], ] }] ), }; ================================================ FILE: src/font/upper.js ================================================ import { generateFontData, ROTATE_HORIZONTAL, ROTATE_VERTICAL, VERTEX_GAP, VERTEX_GAP2, getR, getCurveR } from './util.js'; export const DATA_UA = [{ d: -1, v: [ ['m', 0, 352, { x: 0.55, y: 0.3, r: getR(0, 352, 145 - VERTEX_GAP2, 0), }], ['l', 145 - VERTEX_GAP2, 0, { r: getR(0, 352, 145 - VERTEX_GAP2, 0), f: 1 }], ['l', 145 + VERTEX_GAP2, 0, { r: getR(290, 352, 145 + VERTEX_GAP2, 0), f: 1, v: 1 }], ['l', 290, 352, { x: 0.55, y: 0.3, f: 1 }], ] }, { d: -1, v: [ ['m', 47, 237, { r: ROTATE_VERTICAL, p: 1 }], ['l', 243, 237, { r: ROTATE_VERTICAL, p: 1, f: 1, }], ] } ]; export const DATA_UC = [{ d: 1, v: [ ['m', 293.1, 320.1, { r: getCurveR(293.1, 320.1, 262.2, 345, 222.8, 360, 180, 360, 0), f: 1 }], ['b', 262.2, 345, 222.8, 360, 180, 360], ['b', 80.6, 360, 0, 279.4, 0, 180], ['b', 0, 80.6, 80.6, 0, 180, 0], ['b', 222.8, 0, 262.2, 15, 293.1, 39.9], ] }]; export const DATA_UD = [{ d: -1, v: [ ['m', 95, 352, { r: ROTATE_VERTICAL, f: 1 }], ['b', 191.6, 352, 270, 271.6, 270, 175, { r: ROTATE_HORIZONTAL }], ['b', 270, 78.4, 191.6, 0, 95, 0, { r: ROTATE_VERTICAL }], ['l', 0, 0, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0, 352, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 95, 352, { r: ROTATE_VERTICAL, f: 1 }], ] }]; export const DATA_UE = [{ d: -1, v: [ ['m', 192, 0, { x: 0, r: ROTATE_VERTICAL, }], ['l', 0, 0, { r: ROTATE_HORIZONTAL, f: 1, x: 0.5 }], ['l', 0, 352, { f: 1, x: 0.5 }], ['l', 192, 352, { x: 0, r: ROTATE_VERTICAL, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 164, { r: ROTATE_VERTICAL, p: 1, x: 0.5 }], ['l', 180, 164, { x: 0, r: ROTATE_VERTICAL, f: 1 }], ] } ]; export const DATA_UG = [{ d: 1, v: [ ['m', 202, 180, { r: ROTATE_VERTICAL, f: 1 }], ['l', 352, 180, { f: 1 }], ['b', 352, 279.4, 279.4, 360, 180, 360, { r: ROTATE_VERTICAL }], ['b', 80.6, 360, 0, 279.4, 0, 180, { r: ROTATE_HORIZONTAL }], ['b', 0, 80.6, 80.6, 0, 180, 0, { r: ROTATE_VERTICAL }], ['b', 222.8, 0, 262.1, 14.9, 293, 39.9], ] }]; export const DATA_UH = [{ d: -1, v: [ ['m', 0, 0, { y: 0, r: ROTATE_HORIZONTAL }], ['l', 0, 352, { y: 0, r: ROTATE_HORIZONTAL, f: 1 }], ] }, { d: -1, v: [ ['m', 232, 0, { y: 0, r: ROTATE_HORIZONTAL }], ['l', 232, 352, { y: 0, r: ROTATE_HORIZONTAL, f: 1 }], ] }, { d: -1, v: [ ['m', 0, 164, { r: ROTATE_VERTICAL, p: 1 }], ['l', 232, 164, { r: ROTATE_VERTICAL, f: 1, p: 1 }], ] } ]; export const DATA_UI = [{ d: 1, v: [ ['m', 0, 352, { y: 0, r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0, 0, { y: 0, r: ROTATE_HORIZONTAL }], ] }]; export const DATA_UJ = [{ d: 1, v: [ ['m', 0, 310.5 + 0.5, { r: getCurveR(0, 310.5 + 0.5, 16.2, 341.1 + 0.5, 49.3, 355.5 + 0.5, 86, 355.5 + 0.5, 0), f: 1 }], ['b', 16.2, 341.1 + 0.5, 49.3, 355.5 + 0.5, 86, 355.5 + 0.5, { r: ROTATE_VERTICAL }], ['b', 133.5, 355.5 + 0.5, 172, 317 + 0.5, 172, 269.5 + 0.5], ['l', 172.5, 0, { y: 0, r: ROTATE_HORIZONTAL }], ] }]; export const DATA_UN = [{ d: -1, v: [ ['m', 0, 352, { y: 0, r: ROTATE_HORIZONTAL }], ['l', 0, 0, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0 + VERTEX_GAP, 0, { r: ROTATE_HORIZONTAL, p: 1, f: 1, v: 1 }], ['l', 250 - VERTEX_GAP, 351, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['l', 250, 351, { r: ROTATE_HORIZONTAL, f: 1, v: 1 }], ['l', 250, 0, { y: 0, r: ROTATE_HORIZONTAL, f: 1 }], ] }]; export const DATA_UO = [{ d: 1, v: [ ['m', 360, 180, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['b', 360, 279.4, 279.4, 360, 180, 360, { r: ROTATE_VERTICAL }], ['b', 80.6, 360, 0, 279.4, 0, 180, { r: ROTATE_HORIZONTAL }], ['b', 0, 80.6, 80.6, 0, 180, 0, { r: ROTATE_VERTICAL }], ['b', 279.4, 0, 360, 80.6, 360, 180, { r: ROTATE_HORIZONTAL, c: 1 }], ] }]; export const DATA_US = [{ d: 1, v: [ ['m', 0, 295.4, { r: getCurveR(0, 295.4, 17.6, 332.1, 58.3, 360, 110.3, 360, 0), f: 1 }], ['b', 17.6, 332.1, 58.3, 360, 110.3, 360], ['b', 173.9, 360, 223.8, 329.6, 224, 271], ['b', 224.2, 214.7, 180.7, 189.6, 112.4, 173.3], ['b', 47.3, 157.7, 10.9, 130.6, 12, 84.4], ['b', 13.3, 29.8, 57.3, 0, 114.8, 0], ['b', 158.4, 0, 196.5, 20.5, 212, 51.3], ] }]; export const DATA_UU = [{ d: 1, v: [ ['m', 250, 0, { y: 0, r: ROTATE_HORIZONTAL }], ['l', 250, 230 + 1, { r: ROTATE_HORIZONTAL }], ['b', 250, 299 + 1, 194, 355 + 1, 125, 355 + 1, { r: ROTATE_VERTICAL }], ['b', 56, 355 + 1, 0, 299 + 1, 0, 230 + 1, { r: ROTATE_HORIZONTAL }], ['l', 0, 0, { y: 0, r: ROTATE_HORIZONTAL }], ] }]; export const DATA_UY = [{ d: -1, v: [ ['m', 0, 0, { x: 0.6, y: 0.3, r: getR(0, 0, 135, 186), }], ['l', 135, 186, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 270, 0, { x: 0.6, y: 0.3, f: 1 }] ] }, { d: -1, v: [ ['m', 135, 186, { r: ROTATE_HORIZONTAL, p: 1 }], ['l', 135, 352, { y: 0, f: 1 }], ] } ]; export const UPPER = { 'A': generateFontData( 620, 290, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UA)) ), 'B': generateFontData( 596, 209, 352, -10, -10, 0, 0, [{ d: 1, v: [ ['m', 0, 164, { r: ROTATE_VERTICAL, p: 1 }], ['l', 116, 164, { r: ROTATE_VERTICAL, p: 1, f: 1 }], ['b', 167.4, 164, 209, 205.6, 209, 257, { r: ROTATE_HORIZONTAL }], ['b', 209, 308.4, 167.4, 352, 116, 352, { r: ROTATE_VERTICAL }], ['l', 0, 352, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0, 0, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 116, 0, { r: ROTATE_VERTICAL }], ['b', 161.3, 0, 198, 36.7, 198, 82, { r: ROTATE_HORIZONTAL }], ['b', 198, 127.3, 161.3, 164, 116, 164, { r: ROTATE_VERTICAL }] ] }] ), 'C': generateFontData( 700, 293.1, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UC)) ), 'D': generateFontData( 721, 270, 352, -10, -10, 0, 0, JSON.parse(JSON.stringify(DATA_UD)) ), 'E': generateFontData( 520, 192, 352, -5, -80, 0, 0, JSON.parse(JSON.stringify(DATA_UE)) ), 'F': generateFontData( 510, 192, 352, -5, -80, 0, 0, [{ d: -1, v: [ ['m', 192, 0, { x: 0, r: ROTATE_VERTICAL, }], ['l', 0, 0, { r: ROTATE_HORIZONTAL, f: 1, x: 0.5 }], ['l', 0, 352, { y: 0, f: 1, x: 0.5 }], ] }, { d: -1, v: [ ['m', 0, 164, { r: ROTATE_VERTICAL, p: 1, x: 0.5 }], ['l', 180, 164, { x: 0, r: ROTATE_VERTICAL, f: 1 }], ] } ] ), 'G': generateFontData( 840, 352, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UG)) ), 'H': generateFontData( 684, 232, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UH)) ), 'I': generateFontData( 249, 0, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UI)) ), 'J': generateFontData( 472, 172.5, 355.5, 10, 20, -2, -2, JSON.parse(JSON.stringify(DATA_UJ)) ), 'K': generateFontData( 616, 232, 352, -10, -20, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { y: 0, r: ROTATE_HORIZONTAL }], ['l', 0, 352, { y: 0, r: ROTATE_HORIZONTAL, f: 1 }], ] }, { d: -1, v: [ ['m', 212, 0, { x: 0.7, y: 0.7, r: getR(212, 0, 0, 164 - VERTEX_GAP2), }], ['l', 0, 164 - VERTEX_GAP2, { r: ROTATE_VERTICAL, p: 1 }], ['l', 0, 164 + VERTEX_GAP2, { r: ROTATE_VERTICAL, p: 1, v: 1 }], ['l', 232, 352, { x: 0.7, y: 0.7, f: 1 }], ] } ] ), 'L': generateFontData( 529, 192, 352, -10, -20, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { y: 0 }], ['l', 0, 352, { f: 1 }], ['l', 192, 352, { x: 0, f: 1 }], ] }] ), 'M': generateFontData( 885, 330, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 352, { y: 0, r: ROTATE_HORIZONTAL }], ['l', 0, 0, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0 + VERTEX_GAP, 0, { r: ROTATE_HORIZONTAL, p: 1, f: 1, v: 1 }], ['l', 165 - VERTEX_GAP2, 330, { r: getR(165 - VERTEX_GAP2, 330, 165 - VERTEX_GAP2, 330), f: 1 }], ['l', 165 + VERTEX_GAP2, 330, { r: getR(165 + VERTEX_GAP2, 330, 330 - VERTEX_GAP, 0), f: 1, v: 1 }], ['l', 330 - VERTEX_GAP, 0, { r: ROTATE_HORIZONTAL, p: 1, f: 1 }], ['l', 330, 0, { r: ROTATE_HORIZONTAL, f: 1, v: 1 }], ['l', 330, 352, { y: 0, r: ROTATE_HORIZONTAL, f: 1 }], ] }] ), 'N': generateFontData( 721, 250, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UN)) ), 'O': generateFontData( 850, 360, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UO)) ), 'P': generateFontData( 568, 210, 352, -10, -10, -0.5, -0.5, [{ d: 1, v: [ ['m', 0, 352, { y: 0, f: 1 }], ['l', 0, 0, { f: 1 }], ['l', 117, 0, { r: ROTATE_VERTICAL }], ['b', 168.4, 0, 210, 41.6, 210, 93, { r: ROTATE_HORIZONTAL }], ['b', 210, 144.4, 168.4, 186, 117, 186, { r: ROTATE_VERTICAL }], ['l', 0, 186, { r: ROTATE_VERTICAL, p: 1 }], ] }] ), 'Q': generateFontData( 850, 360, 360, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 360, 180, { r: ROTATE_VERTICAL, p: 1, f: 1 }], ['b', 360, 80.6, 279.4, 0, 180, 0, { r: ROTATE_VERTICAL }], ['b', 80.6, 0, 0, 80.6, 0, 180, { r: ROTATE_HORIZONTAL }], ['b', 0, 279.4, 80.6, 360, 180, 360, { r: ROTATE_VERTICAL }], ['b', 279.4, 360, 360, 279.4, 360, 180, { r: ROTATE_HORIZONTAL, c: 1, f: 1 }], ] }, { d: -1, v: [ ['m', 222, 222, { x: 0.5, y: 0.5, r: getR(222, 222, 360, 360), }], ['l', 360, 360, { x: 0.5, y: 0.5, f: 1 }] ] } ] ), 'R': generateFontData( 634, 232, 352, -10, -10, -0.5, -0.5, [{ d: -1, v: [ ['m', 0, 186, { r: ROTATE_VERTICAL, p: 1 }], ['l', 139, 186, { r: ROTATE_VERTICAL }], ['b', 190.4, 186, 232, 144.4, 232, 93, { r: ROTATE_HORIZONTAL }], ['b', 232, 41.6, 190.4, 0, 139, 0, { r: ROTATE_VERTICAL }], ['l', 0, 0, { r: ROTATE_HORIZONTAL, f: 1 }], ['l', 0, 352, { y: 0, f: 1 }], ] }, { d: -1, v: [ ['m', 139, 186, { p: 1, r: getR(139, 186, 232, 352), }], ['l', 232, 352, { x: 0.5, y: 0.39, f: 1 }], ] } ] ), 'S': generateFontData( 560, 224, 360, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_US)) ), 'T': generateFontData( 568, 232, 352, 0, 0, -0.5, -0.5, [{ d: -1, v: [ ['m', 0, 0, { x: 0, r: ROTATE_VERTICAL }], ['l', 232, 0, { x: 0, r: ROTATE_VERTICAL, f: 1 }], ] }, { d: -1, v: [ ['m', 116, 0, { r: ROTATE_HORIZONTAL, p: 1 }], ['l', 116, 352, { y: 0, r: ROTATE_HORIZONTAL, f: 1 }], ] } ] ), 'U': generateFontData( 712, 250, 355, 0, 0, -0.5, -0.5, JSON.parse(JSON.stringify(DATA_UU)) ), 'V': generateFontData( 650, 270, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: 0.6, y: 0.1, r: getR(0, 0, 135 - VERTEX_GAP2, 352), }], ['l', 135 - VERTEX_GAP2, 352, { r: getR(0, 0, 135 - VERTEX_GAP2, 352), f: 1 }], ['l', 135 + VERTEX_GAP2, 352, { r: getR(135 + VERTEX_GAP2, 352, 270, 0), f: 1, v: 1 }], ['l', 270, 0, { x: 0.6, y: 0.1, f: 1 }], ] }] ), 'W': generateFontData( 894, 390, 352, 0, 0, 0, 0, [{ d: -1, v: [ ['m', 0, 0, { x: 0.6, y: 0.05, r: getR(0, 0, 86 - VERTEX_GAP2, 352), }], ['l', 86 - VERTEX_GAP2, 352, { r: getR(0, 0, 86 - VERTEX_GAP2, 352), f: 1 }], ['l', 86 + VERTEX_GAP2, 352, { r: getR(86 + VERTEX_GAP2, 352, 195 - VERTEX_GAP2, 0), f: 1, v: 1 }], ['l', 195 - VERTEX_GAP2, 0, { r: getR(86 + VERTEX_GAP2, 352, 195 - VERTEX_GAP2, 0), f: 1 }], ['l', 195 + VERTEX_GAP2, 0, { r: getR(195 + VERTEX_GAP2, 0, 304 - VERTEX_GAP2, 352), f: 1, v: 1 }], ['l', 304 - VERTEX_GAP2, 352, { r: getR(195 + VERTEX_GAP2, 0, 304 - VERTEX_GAP2, 352), f: 1 }], ['l', 304 + VERTEX_GAP2, 352, { r: getR(304 + VERTEX_GAP2, 352, 390, 0), f: 1, v: 1 }], ['l', 390, 0, { x: 0.6, y: 0.05, f: 1 }], ] }] ), 'X': generateFontData( 660, 270, 352, 0, 0, 0, -7, [{ d: -1, v: [ ['m', 10, 0, { x: 0.5, y: 0.3, r: getR(10, 0, 270, 352), }], ['l', 270, 352, { x: 0.5, y: 0.5, f: 1 }] ] }, { d: -1, v: [ ['m', 260, 0, { x: 0.5, y: 0.3, r: getR(260, 0, 0, 352), }], ['l', 0, 352, { x: 0.5, y: 0.5, f: 1 }] ] } ] ), 'Y': generateFontData( 673, 270, 352, 0, 0, 0, 0, JSON.parse(JSON.stringify(DATA_UY)) ), 'Z': generateFontData( 558, 232, 352, 0, -5, 0, 0, [{ d: -1, v: [ ['m', 8, 0, { x: 0, r: ROTATE_VERTICAL }], ['l', 224, 0, { r: ROTATE_VERTICAL, f: 1 }], ['l', 224, 0 + VERTEX_GAP, { r: ROTATE_HORIZONTAL, p: 1, v: 1 }], ['l', 0, 352 - VERTEX_GAP, { r: ROTATE_HORIZONTAL, p: 1 }], ['l', 0, 352, { r: ROTATE_VERTICAL, f: 1, v: 1 }], ['l', 232, 352, { x: 0, r: ROTATE_VERTICAL, f: 1 }] ] }] ) }; ================================================ FILE: src/font/util.js ================================================ import { Vector } from '../core/vector.js'; import { bezierTangent } from '../core/paths.js'; export const ROTATE_HORIZONTAL = 180 * (Math.PI / 180); export const ROTATE_VERTICAL = 90 * (Math.PI / 180); export const ROTATE_NONE = -100; export const VERTEX_GAP = 3; export const VERTEX_GAP2 = VERTEX_GAP / 2; export const TOFU = 'tofu'; const FONT_HEIGHT = 824; export function generateFontData(w, fw, fh, x1, x2, y1, y2, path) { const arr = []; const total = path.length; let i; for (i = 0; i < total; i++) { arr.push({ d: path[i].d, v: setCenter(path[i].v, fw, fh) }); } return { rect: { w: w, h: FONT_HEIGHT, fw: fw, fh: fh }, ratio: { x1: x1, x2: x2, y1: y1, y2: y2, }, p: arr, clone: () => { const arr2 = []; for (let i = 0; i < arr.length; i++) { arr2[i] = { d: arr[i].d, v: arr[i].v }; } const v = { rect: { w: w, h: FONT_HEIGHT, fw: fw, fh: fh }, ratio: { x1: x1, x2: x2, y1: y1, y2: y2, }, p: arr2, }; return v; } }; } function setCenter(arr, fw, fh) { const total = arr.length; const cx = fw / 2; const cy = fh / 2; let mp, i, ct = []; for (i = 0; i < total; i++) { mp = arr[i]; mp[1] -= cx; mp[2] -= cy; if (mp[0] == 'b') { mp[3] -= cx; mp[4] -= cy; mp[5] -= cx; mp[6] -= cy; } ct.push(new Vector(mp)); } return ct; } export function getR(x1, y1, x2, y2) { const x = x1 - x2; const y = y1 - y2; return -Math.atan2(x, y); } export function getCurveR(x1, y1, x2, y2, x3, y3, x4, y4, t) { const x = bezierTangent(x1, x2, x3, x4, t); const y = bezierTangent(y1, y2, y3, y4, t); return -Math.atan2(x, y); } ================================================ FILE: src/index.js ================================================ const LeonSans = require('./leonsans').default; module.exports = LeonSans; ================================================ FILE: src/leonsans.js ================================================ /*! * VERSION: 1.6.3 * DATE: 2019-09-13 * https://leon-sans.com * * @license Copyright (c) 2019, Jongmin Kim. All rights reserved. **/ import { Dispatcher } from './core/dispatcher.js'; import { MIN_FONT_WEIGHT, MAX_FONT_WEIGHT, shuffle } from './core/util.js'; import { Lines } from './draw/canvas/lines.js'; import { Points } from './draw/canvas/points.js'; import { Grids } from './draw/canvas/grids.js'; import { Wave } from './draw/canvas/wave.js'; import { Pattern } from './draw/canvas/pattern.js'; import { Color } from './draw/canvas/color.js'; import { Colorful } from './draw/canvas/colorful.js'; import { PixiLines } from './draw/pixi/lines.js'; import { PixiColor } from './draw/pixi/color.js'; import { Model } from './core/model.js'; export default class LeonSans extends Dispatcher { constructor({ text = '', size = 500, weight = MIN_FONT_WEIGHT, color = ['#000000'], colorful = ['#c5d73f', '#9d529c', '#49a9db', '#fec330', '#5eb96e', '#fc5356', '#f38f31'], tracking = 0, leading = 0, align = 'left', pathGap = 0.5, amplitude = 0.5, width = 0, breakWord = false, fps = 30, isPath = false, isWave = false, } = {}) { super(); this.size_ = size; this.weight_ = weight; this.color_ = color; this.colorful_ = shuffle(colorful); this.tracking_ = tracking; this.leading_ = leading; this.pathGap_ = pathGap; this.amplitude_ = amplitude; this.width_ = width; this.breakWord_ = breakWord; this.fps_ = fps; this.fpsTime_ = 1000 / this.fps_; this.isPath_ = isPath; this.isWave_ = isWave; this.model = new Model(); this.str_ = null; this.time_ = null; this.isFps_ = false; this.isForceRander_ = false; this.updateID_ = 0; this.dPathsID_ = null; this.pPathsID_ = null; this.wPathsID_ = null; this.guideID_ = null; this.text = text; this.model.align = align; } on(event, callback) { super.on(event, callback); this.update(); } off(event, callback) { super.off(event, callback); } get text() { return this.str_; } set text(str) { if (this.str_ == str) return; this.str_ = str; this.update(); } get size() { return this.size_; } set size(v) { if (this.size_ == v) return; this.size_ = v; this.update(); this.isForceRander_ = true; } get weight() { return this.weight_; } set weight(v) { if (v < MIN_FONT_WEIGHT) { v = MIN_FONT_WEIGHT; } else if (v > MAX_FONT_WEIGHT) { v = MAX_FONT_WEIGHT; } if (this.weight_ == v) return; this.weight_ = v; this.update(); this.isForceRander_ = true; } get color() { return this.color_; } set color(v) { if (this.color_ == v) return; this.color_ = v; } get tracking() { return this.tracking_; } set tracking(v) { if (this.tracking_ == v) return; this.tracking_ = v; this.update(); this.isForceRander_ = true; } get leading() { return this.leading_; } set leading(v) { if (this.leading_ == v) return; this.leading_ = v; this.update(); this.isForceRander_ = true; } get align() { return this.model.align; } set align(v) { if (this.model.align != v) { this.model.align = v; this.updateID_++; this.updateSignal(); } } get pathGap() { return this.pathGap_; } set pathGap(v) { if (this.pathGap_ != v) { this.pathGap_ = v; this.updatePatternPaths(true); this.updateWavePaths(true); this.isForceRander_ = true; } } get amplitude() { return this.amplitude_; } set amplitude(v) { this.amplitude_ = v; } get rect() { return this.model.rect; } set maxWidth(v) { if (this.width_ == v) return; this.width_ = v; this.update(); } get maxWidth() { return this.width_; } set breakWord(v) { if (this.breakWord_ == v) return; this.breakWord_ = v; this.update(); } get breakWord() { return this.breakWord_; } get isPath() { return this.isPath_; } set isPath(v) { this.isPath_ = v; this.updatePatternPaths(true); } get isWave() { return this.isWave_; } set isWave(v) { this.isWave_ = v; this.updateWavePaths(true); } get fps() { return this.fps_; } set fps(v) { this.fps_ = v; this.fpsTime_ = 1000 / this.fps_; } get lineWidth() { return this.model.lineWidth; } get scale() { return this.model.scale; } get drawing() { return this.model.drawing; } get data() { return this.model.data; } get paths() { return this.model.paths; } get drawingPaths() { return this.model.drawingPaths; } get wavePaths() { return this.model.wavePaths; } position(x = 0, y = 0) { if (this.model.position(x, y)) { this.updateID_++; this.updateSignal(); } } update() { this.updateID_++; this.model.update( this.str_, this.width_, this.breakWord_, this.weight_, this.size_, this.tracking_, this.leading_ ); if (this.isPath_ || this.isWave_) { this.updatePatternPaths(); this.updateWavePaths(); } else { this.updateSignal(); } } updateGuide() { if (this.guideID_ != this.updateID_) { this.guideID_ = this.updateID_; this.model.updateGuide(); } } /** * Update paths for drawing in WebGL (PIXI.js). It's very expensive, only call when it needs. */ updateDrawingPaths() { if (this.dPathsID_ != this.updateID_) { this.dPathsID_ = this.updateID_; this.model.updateDrawingPaths(); } } /** * Update paths for pattern * @param {boolean} force - Force execution */ updatePatternPaths(force) { if (this.isPath_ && (force || this.pPathsID_ != this.updateID_)) { this.pPathsID_ = this.updateID_; this.model.updatePatternPaths(this.pathGap_); this.isForceRander_ = true; this.updateSignal(); } } /** * Update paths for wave effect * @param {boolean} force - Force execution */ updateWavePaths(force) { if (this.isWave_ && (force || this.wPathsID_ != this.updateID_)) { this.wPathsID_ = this.updateID_; this.model.updateWavePaths(this.pathGap_); this.isForceRander_ = true; this.updateSignal(); } } updateSignal() { this.model.updateLinesForRect(); this.model.updatePathsForRect(); this.dispatch('update', this.model); } reset() { this.size_ = 500; this.weight_ = MIN_FONT_WEIGHT; this.color_ = ['#000000']; this.tracking_ = 0; this.leading_ = 0; this.pathGap_ = 0.5; this.amplitude_ = 0.5; this.width_ = 0; this.breakWord_ = false; this.fps_ = 30; this.fpsTime_ = 1000 / this.fps_; this.isPath_ = false; this.isWave_ = false; this.str_ = null; this.time_ = null; this.isFps_ = false; this.isForceRander_ = false; this.updateID_ = 0; this.dPathsID_ = null; this.pPathsID_ = null; this.wPathsID_ = null; this.guideID_ = null; this.model.reset(); } dispose() { this.reset(); this.model = null; } /** * Draw text in WebGL with PIXI.js * @param {PIXI.Graphics} graphics */ drawPixi(graphics) { const total = this.model.data.length; let i, d, color; for (i = 0; i < total; i++) { d = this.model.data[i]; color = PixiColor(i, d, this.color_); PixiLines(graphics, d, this.lineWidth, color); } } /** * Draw text in the Canvas element. * @param {CanvasRenderingContext2D} ctx */ draw(ctx) { ctx.lineWidth = this.lineWidth; const total = this.model.data.length; let i, d; for (i = 0; i < total; i++) { d = this.model.data[i]; Color(ctx, i, d, this.color_); Lines(ctx, d); } } /** * Draw the colorful effect. * @param {CanvasRenderingContext2D} ctx */ drawColorful(ctx) { ctx.lineWidth = this.lineWidth; Colorful(ctx, this.model, this.colorful_); } /** * Draw the wave effect. * @param {CanvasRenderingContext2D} ctx * @param {DOMHighResTimeStamp} t time stemp from requestAnimationFrame() */ wave(ctx, t) { ctx.lineWidth = this.lineWidth; if (t) { if (!this.time_) this.time_ = t; const p = t - this.time_; if (p > this.fpsTime_ || this.isForceRander_) { this.time_ = t; this.isFps_ = true; } else { this.isFps_ = false; } } this.isForceRander_ = false; const total = this.model.data.length; let i, d; for (i = 0; i < total; i++) { d = this.model.data[i]; Color(ctx, i, d, this.color_); Wave(ctx, d, this.model.scale, this.amplitude_, this.weight_, this.isFps_); } } /** * Draw rectangle shapes at each path point. * @param {CanvasRenderingContext2D} ctx * @param {number} w pattern width * @param {number} h pattern height */ pattern(ctx, w, h) { const tw = w * this.model.scale; const th = h * this.model.scale; const total = this.model.data.length; let i, d; for (i = 0; i < total; i++) { d = this.model.data[i]; Pattern(ctx, d, tw, th); } } /** * Draw grid for each type. * @param {CanvasRenderingContext2D} ctx */ grid(ctx) { this.updateGuide(); const total = this.model.data.length; let i, d; for (i = 0; i < total; i++) { d = this.model.data[i]; Grids(ctx, d); } } /** * Draw circles at each drawing point and lines for each type. * @param {CanvasRenderingContext2D} ctx */ point(ctx) { const total = this.model.data.length; let i, d; for (i = 0; i < total; i++) { d = this.model.data[i]; Points(ctx, d); } } /** * Draw outline box for the text. * @param {CanvasRenderingContext2D} ctx * @private */ box(ctx) { ctx.lineWidth = 1; ctx.beginPath(); ctx.strokeStyle = "#0b90dc"; ctx.rect(this.model.rect.x, this.model.rect.y, this.model.rect.w, this.model.rect.h); ctx.stroke(); } }