|
|
|
@ -42,7 +42,7 @@ module.exports = class GLFontCache { |
|
|
|
|
ctx.textAlign = 'center' |
|
|
|
|
ctx.textBaseline = 'middle' |
|
|
|
|
ctx.fillStyle = 'white' |
|
|
|
|
ctx.fillText(character, cellSize.width * 1.5, cellSize.height * 1.5) |
|
|
|
|
this.drawCharacter(character) |
|
|
|
|
|
|
|
|
|
let imageData = ctx.getImageData(0, 0, width, height) |
|
|
|
|
|
|
|
|
@ -56,4 +56,146 @@ module.exports = class GLFontCache { |
|
|
|
|
|
|
|
|
|
return texture |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
drawCharacter (character) { |
|
|
|
|
const { ctx, cellSize } = this |
|
|
|
|
|
|
|
|
|
let screenX = cellSize.width |
|
|
|
|
let screenY = cellSize.height |
|
|
|
|
|
|
|
|
|
let codePoint = character.codePointAt(0) |
|
|
|
|
if (codePoint >= 0x2580 && codePoint <= 0x259F) { |
|
|
|
|
// block elements
|
|
|
|
|
ctx.beginPath() |
|
|
|
|
const left = screenX |
|
|
|
|
const top = screenY |
|
|
|
|
const cw = cellSize.width |
|
|
|
|
const ch = cellSize.height |
|
|
|
|
const c2w = cellSize.width / 2 |
|
|
|
|
const c2h = cellSize.height / 2 |
|
|
|
|
|
|
|
|
|
// http://www.fileformat.info/info/unicode/block/block_elements/utf8test.htm
|
|
|
|
|
// 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
|
|
|
|
|
// 0x2580 ▀ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▉ ▊ ▋ ▌ ▍ ▎ ▏
|
|
|
|
|
// 0x2590 ▐ ░ ▒ ▓ ▔ ▕ ▖ ▗ ▘ ▙ ▚ ▛ ▜ ▝ ▞ ▟
|
|
|
|
|
|
|
|
|
|
if (codePoint === 0x2580) { |
|
|
|
|
// upper half block >▀<
|
|
|
|
|
ctx.rect(left, top, cw, c2h) |
|
|
|
|
} else if (codePoint <= 0x2588) { |
|
|
|
|
// lower n eighth block (increasing) >▁< to >█<
|
|
|
|
|
let offset = (1 - (codePoint - 0x2580) / 8) * ch |
|
|
|
|
ctx.rect(left, top + offset, cw, ch - offset) |
|
|
|
|
} else if (codePoint <= 0x258F) { |
|
|
|
|
// left n eighth block (decreasing) >▉< to >▏<
|
|
|
|
|
let offset = (codePoint - 0x2588) / 8 * cw |
|
|
|
|
ctx.rect(left, top, cw - offset, ch) |
|
|
|
|
} else if (codePoint === 0x2590) { |
|
|
|
|
// right half block >▐<
|
|
|
|
|
ctx.rect(left + c2w, top, c2w, ch) |
|
|
|
|
} else if (codePoint <= 0x2593) { |
|
|
|
|
// shading >░< >▒< >▓<
|
|
|
|
|
|
|
|
|
|
// dot spacing by dividing cell size by a constant. This could be
|
|
|
|
|
// reworked to always return a whole number, but that would require
|
|
|
|
|
// prime factorization, and doing that without a loop would let you
|
|
|
|
|
// take over the world, which is not within the scope of this project.
|
|
|
|
|
let dotSpacingX, dotSpacingY, dotSize |
|
|
|
|
if (codePoint === 0x2591) { |
|
|
|
|
dotSpacingX = cw / 4 |
|
|
|
|
dotSpacingY = ch / 10 |
|
|
|
|
dotSize = 1 |
|
|
|
|
} else if (codePoint === 0x2592) { |
|
|
|
|
dotSpacingX = cw / 6 |
|
|
|
|
dotSpacingY = cw / 10 |
|
|
|
|
dotSize = 1 |
|
|
|
|
} else if (codePoint === 0x2593) { |
|
|
|
|
dotSpacingX = cw / 4 |
|
|
|
|
dotSpacingY = cw / 7 |
|
|
|
|
dotSize = 2 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let alignRight = false |
|
|
|
|
for (let dy = 0; dy < ch; dy += dotSpacingY) { |
|
|
|
|
for (let dx = 0; dx < cw; dx += dotSpacingX) { |
|
|
|
|
// prevent overflow
|
|
|
|
|
let dotSizeY = Math.min(dotSize, ch - dy) |
|
|
|
|
ctx.rect(left + (alignRight ? cw - dx - dotSize : dx), top + dy, dotSize, dotSizeY) |
|
|
|
|
} |
|
|
|
|
alignRight = !alignRight |
|
|
|
|
} |
|
|
|
|
} else if (codePoint === 0x2594) { |
|
|
|
|
// upper one eighth block >▔<
|
|
|
|
|
ctx.rect(left, top, cw, ch / 8) |
|
|
|
|
} else if (codePoint === 0x2595) { |
|
|
|
|
// right one eighth block >▕<
|
|
|
|
|
ctx.rect(left + (7 / 8) * cw, top, cw / 8, ch) |
|
|
|
|
} else if (codePoint === 0x2596) { |
|
|
|
|
// left bottom quadrant >▖<
|
|
|
|
|
ctx.rect(left, top + c2h, c2w, c2h) |
|
|
|
|
} else if (codePoint === 0x2597) { |
|
|
|
|
// right bottom quadrant >▗<
|
|
|
|
|
ctx.rect(left + c2w, top + c2h, c2w, c2h) |
|
|
|
|
} else if (codePoint === 0x2598) { |
|
|
|
|
// left top quadrant >▘<
|
|
|
|
|
ctx.rect(left, top, c2w, c2h) |
|
|
|
|
} else if (codePoint === 0x2599) { |
|
|
|
|
// left chair >▙<
|
|
|
|
|
ctx.rect(left, top, c2w, ch) |
|
|
|
|
ctx.rect(left + c2w, top + c2h, c2w, c2h) |
|
|
|
|
} else if (codePoint === 0x259A) { |
|
|
|
|
// quadrants lt rb >▚<
|
|
|
|
|
ctx.rect(left, top, c2w, c2h) |
|
|
|
|
ctx.rect(left + c2w, top + c2h, c2w, c2h) |
|
|
|
|
} else if (codePoint === 0x259B) { |
|
|
|
|
// left chair upside down >▛<
|
|
|
|
|
ctx.rect(left, top, c2w, ch) |
|
|
|
|
ctx.rect(left + c2w, top, c2w, c2h) |
|
|
|
|
} else if (codePoint === 0x259C) { |
|
|
|
|
// right chair upside down >▜<
|
|
|
|
|
ctx.rect(left, top, cw, c2h) |
|
|
|
|
ctx.rect(left + c2w, top + c2h, c2w, c2h) |
|
|
|
|
} else if (codePoint === 0x259D) { |
|
|
|
|
// right top quadrant >▝<
|
|
|
|
|
ctx.rect(left + c2w, top, c2w, c2h) |
|
|
|
|
} else if (codePoint === 0x259E) { |
|
|
|
|
// quadrants lb rt >▞<
|
|
|
|
|
ctx.rect(left, top + c2h, c2w, c2h) |
|
|
|
|
ctx.rect(left + c2w, top, c2w, c2h) |
|
|
|
|
} else if (codePoint === 0x259F) { |
|
|
|
|
// right chair upside down >▟<
|
|
|
|
|
ctx.rect(left, top + c2h, c2w, c2h) |
|
|
|
|
ctx.rect(left + c2w, top, c2w, ch) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ctx.fill() |
|
|
|
|
} else if (codePoint >= 0xE0B0 && codePoint <= 0xE0B3) { |
|
|
|
|
// powerline symbols, except branch, line, and lock. Basically, just the triangles
|
|
|
|
|
ctx.beginPath() |
|
|
|
|
|
|
|
|
|
if (codePoint === 0xE0B0 || codePoint === 0xE0B1) { |
|
|
|
|
// right-pointing triangle
|
|
|
|
|
ctx.moveTo(screenX, screenY) |
|
|
|
|
ctx.lineTo(screenX + cellSize.width, screenY + cellSize.height / 2) |
|
|
|
|
ctx.lineTo(screenX, screenY + cellSize.height) |
|
|
|
|
} else if (codePoint === 0xE0B2 || codePoint === 0xE0B3) { |
|
|
|
|
// left-pointing triangle
|
|
|
|
|
ctx.moveTo(screenX + cellSize.width, screenY) |
|
|
|
|
ctx.lineTo(screenX, screenY + cellSize.height / 2) |
|
|
|
|
ctx.lineTo(screenX + cellSize.width, screenY + cellSize.height) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (codePoint % 2 === 0) { |
|
|
|
|
// triangle
|
|
|
|
|
ctx.fill() |
|
|
|
|
} else { |
|
|
|
|
// chevron
|
|
|
|
|
ctx.strokeStyle = ctx.fillStyle |
|
|
|
|
ctx.stroke() |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Draw other characters using the text renderer
|
|
|
|
|
ctx.fillText(character, cellSize.width * 1.5, cellSize.height * 1.5) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|