From 489b47deadec721534cf457e3bfc12f66f479796 Mon Sep 17 00:00:00 2001 From: Jongmin Kim Date: Thu, 29 Aug 2019 16:51:47 -0700 Subject: [PATCH] Add files via upload --- src/core/align.js | 17 + src/core/dispatcher.js | 46 +++ src/core/group.js | 125 ++++++ src/core/guide.js | 45 +++ src/core/length.js | 123 ++++++ src/core/model.js | 311 ++++++++++++++ src/core/paths.js | 200 +++++++++ src/core/point.js | 21 + src/core/util.js | 214 ++++++++++ src/core/vector.js | 101 +++++ src/draw/index.js | 2 + src/font/index.js | 23 ++ src/font/lower.js | 884 ++++++++++++++++++++++++++++++++++++++++ src/font/number.js | 344 ++++++++++++++++ src/font/special.js | 890 ++++++++++++++++++++++++++++++++++++++++ src/font/upper.js | 892 +++++++++++++++++++++++++++++++++++++++++ src/font/util.js | 76 ++++ 17 files changed, 4314 insertions(+) create mode 100644 src/core/align.js create mode 100644 src/core/dispatcher.js create mode 100644 src/core/group.js create mode 100644 src/core/guide.js create mode 100644 src/core/length.js create mode 100644 src/core/model.js create mode 100644 src/core/paths.js create mode 100644 src/core/point.js create mode 100644 src/core/util.js create mode 100644 src/core/vector.js create mode 100644 src/draw/index.js create mode 100644 src/font/index.js create mode 100644 src/font/lower.js create mode 100644 src/font/number.js create mode 100644 src/font/special.js create mode 100644 src/font/upper.js create mode 100644 src/font/util.js diff --git a/src/core/align.js b/src/core/align.js new file mode 100644 index 0000000..97d0db4 --- /dev/null +++ b/src/core/align.js @@ -0,0 +1,17 @@ +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; + } +} \ No newline at end of file diff --git a/src/core/dispatcher.js b/src/core/dispatcher.js new file mode 100644 index 0000000..3cf4716 --- /dev/null +++ b/src/core/dispatcher.js @@ -0,0 +1,46 @@ +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); + }); + } +} \ No newline at end of file diff --git a/src/core/group.js b/src/core/group.js new file mode 100644 index 0000000..c8c967d --- /dev/null +++ b/src/core/group.js @@ -0,0 +1,125 @@ +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; +} \ No newline at end of file diff --git a/src/core/guide.js b/src/core/guide.js new file mode 100644 index 0000000..939ae4e --- /dev/null +++ b/src/core/guide.js @@ -0,0 +1,45 @@ +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; +} \ No newline at end of file diff --git a/src/core/length.js b/src/core/length.js new file mode 100644 index 0000000..04bd116 --- /dev/null +++ b/src/core/length.js @@ -0,0 +1,123 @@ +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); +} \ No newline at end of file diff --git a/src/core/model.js b/src/core/model.js new file mode 100644 index 0000000..7ff06a3 --- /dev/null +++ b/src/core/model.js @@ -0,0 +1,311 @@ +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; + } +} \ No newline at end of file diff --git a/src/core/paths.js b/src/core/paths.js new file mode 100644 index 0000000..9aad7fe --- /dev/null +++ b/src/core/paths.js @@ -0,0 +1,200 @@ +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)); +} \ No newline at end of file diff --git a/src/core/point.js b/src/core/point.js new file mode 100644 index 0000000..7b1243b --- /dev/null +++ b/src/core/point.js @@ -0,0 +1,21 @@ +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; + } +}); \ No newline at end of file diff --git a/src/core/util.js b/src/core/util.js new file mode 100644 index 0000000..d23ae6e --- /dev/null +++ b/src/core/util.js @@ -0,0 +1,214 @@ +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; +} \ No newline at end of file diff --git a/src/core/vector.js b/src/core/vector.js new file mode 100644 index 0000000..d070c34 --- /dev/null +++ b/src/core/vector.js @@ -0,0 +1,101 @@ +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 +} \ No newline at end of file diff --git a/src/draw/index.js b/src/draw/index.js new file mode 100644 index 0000000..1b9c716 --- /dev/null +++ b/src/draw/index.js @@ -0,0 +1,2 @@ +const LeonSans = require('./LeonSans').default; +module.exports = LeonSans; \ No newline at end of file diff --git a/src/font/index.js b/src/font/index.js new file mode 100644 index 0000000..3d8df2f --- /dev/null +++ b/src/font/index.js @@ -0,0 +1,23 @@ +import { + UPPER +} from './upper.js'; +import { + LOWER +} from './lower.js'; +import { + NUMBER +} from './number.js'; +import { + SPECIAL +} from './special.js'; +import { + TOFU +} from './util.js'; + +const DATA = Object.assign({}, UPPER, LOWER, NUMBER, SPECIAL); + +export function typo(v) { + var t = DATA[v] || DATA[TOFU]; + t.v = v; + return t; +} \ No newline at end of file diff --git a/src/font/lower.js b/src/font/lower.js new file mode 100644 index 0000000..d820a73 --- /dev/null +++ b/src/font/lower.js @@ -0,0 +1,884 @@ +import { + generateFontData, + ROTATE_HORIZONTAL, + ROTATE_VERTICAL, + ROTATE_NONE, + VERTEX_GAP, + VERTEX_GAP2, + getR, + getCurveR +} from './util.js'; + +export const LOWER = { + 'a': generateFontData( + 600, 232, 232, + 10, 2, -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 + }] + ] + }, ] + ), + '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, + [{ + 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], + ] + }] + ), + 'd': generateFontData( + 600, 232, 352, + 10, 2, 0, 0, + [{ + 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 + }], + ] + }, ] + ), + 'e': generateFontData( + 570, 225.5, 233.1, + 0, 0, -64, -64, + [{ + 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 + }], + ] + }] + ), + '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, + [{ + 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 + }], + ] + }] + ), + 'h': generateFontData( + 520, 182, 352, + 0, 0, 0, 0, + [{ + 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 + }], + ] + }] + ), + '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, + [{ + 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 + }], + ] + } + + ] + ), + 'o': generateFontData( + 580, 232, 232, + 0, 0, -64, -64, + [{ + 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 + }], + ] + }] + ), + '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, + [{ + 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], + ] + }] + ), + '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, + [{ + 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 + }], + ] + } + ] + ), + '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, + [{ + 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 + }], + ] + } + ] + ), + '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 + }] + ] + }] + ) +}; \ No newline at end of file diff --git a/src/font/number.js b/src/font/number.js new file mode 100644 index 0000000..38c7a3e --- /dev/null +++ b/src/font/number.js @@ -0,0 +1,344 @@ +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 + }], + ] + }] + ) +}; \ No newline at end of file diff --git a/src/font/special.js b/src/font/special.js new file mode 100644 index 0000000..b436937 --- /dev/null +++ b/src/font/special.js @@ -0,0 +1,890 @@ +import { + generateFontData, + ROTATE_HORIZONTAL, + ROTATE_VERTICAL, + ROTATE_NONE, + VERTEX_GAP, + 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 - 4, 360 - 4], + ] + }, { + 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( + 465, 8, 355, + 0, -5, 0, 0, + [{ + d: 1, + v: [ + ['a', 8 / 2, 355 - 1.5], + ] + }, { + d: -1, + v: [ + ['m', 4, 0, { + y: 0 + }], + ['l', 4, 260.8, { + f: 1 + }], + ] + }] + ), + '$': 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_GAP, 0) + }], + ['l', 88 - VERTEX_GAP, 0, { + r: getR(0, 150, 88 - VERTEX_GAP, 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( + 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 + }] + ] + }] + ) +}; \ No newline at end of file diff --git a/src/font/upper.js b/src/font/upper.js new file mode 100644 index 0000000..4b1fc9e --- /dev/null +++ b/src/font/upper.js @@ -0,0 +1,892 @@ +import { + generateFontData, + ROTATE_HORIZONTAL, + ROTATE_VERTICAL, + ROTATE_NONE, + VERTEX_GAP, + VERTEX_GAP2, + getR, + getCurveR +} from './util.js'; + +export const UPPER = { + 'A': generateFontData( + 620, 290, 352, + 0, 0, 0, 0, + [{ + 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, + }], + ] + } + ] + ), + '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, + [{ + 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], + ] + }] + ), + 'D': generateFontData( + 721, 270, 352, + -10, -10, 0, 0, + [{ + //c: 'square', + 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 + }], + ] + }] + ), + 'E': generateFontData( + 520, 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, { + 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 + }], + ] + } + ] + ), + '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, + [{ + 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], + ] + }] + ), + 'H': generateFontData( + 684, 232, 352, + 0, 0, 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', 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 + }], + ] + }, + ] + ), + 'I': generateFontData( + 249, 0, 352, + 0, 0, 0, 0, + [{ + d: 1, + v: [ + ['m', 0, 352, { + y: 0, + r: ROTATE_HORIZONTAL, + f: 1 + }], + ['l', 0, 0, { + y: 0, + r: ROTATE_HORIZONTAL + }], + ] + }, ] + ), + 'J': generateFontData( + 472, 172.5, 355.5, + 10, 20, -2, -2, + [{ + 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 + }], + ] + }, ] + ), + '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, + [{ + 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 + }], + ] + }] + ), + 'O': generateFontData( + 850, 360, 360, + 0, 0, 0, 0, + [{ + 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 + }], + ] + }] + ), + '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, + [{ + 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], + ] + }] + ), + '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, + [{ + 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 + }], + ] + }] + ), + '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, + [{ + 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 + }], + ] + } + ] + ), + '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 + }] + ] + }] + ) +}; \ No newline at end of file diff --git a/src/font/util.js b/src/font/util.js new file mode 100644 index 0000000..c713956 --- /dev/null +++ b/src/font/util.js @@ -0,0 +1,76 @@ +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 + }; +} + +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); +} \ No newline at end of file