Skip to content

Commit

Permalink
feat: cozette font for glyph renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
hpcreery committed Dec 3, 2024
1 parent 353d24a commit 23012cc
Show file tree
Hide file tree
Showing 8 changed files with 599 additions and 4 deletions.
76 changes: 74 additions & 2 deletions src/renderer/src/renderer/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import { vec2 } from "gl-matrix"
import earcut from "earcut"
import { fontInfo } from "./text/glyph/font"

import { fontInfo as cozetteFontInfo } from './text/cozette/font'

const {
LINE_RECORD_PARAMETERS,
PAD_RECORD_PARAMETERS,
Expand Down Expand Up @@ -213,6 +215,12 @@ export const ReglRenderers: TReglRenderers = {
renderToScreen: undefined,
}

/**
* This glyph renderer is deprecated and will be removed in the future.
* @param regl
* @param glyphData
* @deprecated Use initializeFontRenderer instead
*/
export function initializeGlyphRenderer(regl: REGL.Regl, glyphData: Uint8ClampedArray): void {
const texture = regl.texture({
data: glyphData,
Expand Down Expand Up @@ -275,6 +283,69 @@ export function initializeGlyphRenderer(regl: REGL.Regl, glyphData: Uint8Clamped
})
}


export function initializeFontRenderer(regl: REGL.Regl, data: Uint8ClampedArray): void {
const texture = regl.texture({
data,
width: cozetteFontInfo.textureWidth,
height: cozetteFontInfo.textureHeight,
format: "rgba",
type: "uint8",
mag: "nearest",
min: "nearest",
})

ReglRenderers.drawDatumText = regl<
DatumTextUniforms,
DatumTextAttributes,
DatumTextAttachments,
Record<string, never>,
REGL.DefaultContext & WorldContext
>({
frag: GlyphtextFrag,
vert: GlyphtextVert,

attributes: {
a_position: {
buffer: regl.prop<DatumTextAttachments, "positions">("positions"),
offset: 0,
stride: 2 * glFloatSize,
divisor: 1,
},
a_texcoord: {
buffer: regl.prop<DatumTextAttachments, "texcoords">("texcoords"),
offset: 0,
stride: 2 * glFloatSize,
divisor: 1,
},
a_StringIndex: {
buffer: regl.prop<DatumTextAttachments, "stringIndexes">("stringIndexes"),
offset: 0,
stride: 1 * glFloatSize,
divisor: 1,
},
a_Vertex_Position: [
[0, 0],
[0, 1],
[1, 0],
[1, 0],
[0, 1],
[1, 1],
],
},

uniforms: {
u_texture: texture,
u_TextureDimensions: [cozetteFontInfo.textureWidth, cozetteFontInfo.textureHeight],
u_LetterDimensions: [cozetteFontInfo.fontWidth, cozetteFontInfo.fontHeight],
},

instances: regl.prop<SurfaceAttachments, "length">("length"),
count: 6,
primitive: "triangles",
})
}

export function initializeRenderers(regl: REGL.Regl): void {
ReglRenderers.drawPads = regl<PadUniforms, PadAttributes, PadAttachments, Record<string, never>, REGL.DefaultContext & WorldContext>({
frag: PadFrag,
Expand Down Expand Up @@ -1068,19 +1139,20 @@ export class DatumTextShaderCollection {
const stringIndexes: number[] = []
image.map((record) => {
if (record.type !== FeatureTypeIdentifier.DATUM_TEXT) return
const string = record.text.toLowerCase()
const string = record.text
const x = record.x
const y = record.y
for (let i = 0; i < string.length; ++i) {
const letter = string[i]
const glyphInfo = fontInfo.glyphInfos[letter]
const glyphInfo = cozetteFontInfo.glyphInfos[letter]
if (glyphInfo !== undefined) {
positions.push(x, y)
texcoords.push(glyphInfo.x, glyphInfo.y)
stringIndexes.push(i)
}
}
})

this.attachment.positions(positions)
this.attachment.texcoords(texcoords)
this.attachment.stringIndexes(stringIndexes)
Expand Down
6 changes: 5 additions & 1 deletion src/renderer/src/renderer/engine.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import REGL from "regl"
import { mat3, vec2, vec3, vec4 } from "gl-matrix"
import LayerRenderer, { LayerRendererProps } from "./layer"
import { initializeGlyphRenderer, initializeRenderers, ReglRenderers, ScreenRenderProps } from "./collections"
import { initializeGlyphRenderer, initializeFontRenderer, initializeRenderers, ReglRenderers, ScreenRenderProps } from "./collections"
import * as Shapes from "./shapes"
import * as Comlink from "comlink"
import plugins from "./plugins"
Expand Down Expand Up @@ -441,6 +441,10 @@ export class RenderEngineBackend {
initializeGlyphRenderer(this.regl, glyphData)
}

public initializeFontRenderer(fontData: Uint8ClampedArray): void {
initializeFontRenderer(this.regl, fontData)
}

public resize(width: number, height: number): void {
this.viewBox.width = width
this.viewBox.height = height
Expand Down
48 changes: 47 additions & 1 deletion src/renderer/src/renderer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { AddLayerProps } from "./plugins"
import font from "./text/glyph/font.png?arraybuffer"
import { fontInfo } from "./text/glyph/font"

import cozetteFont from "./text/cozette/CozetteVector.ttf?url"
import { fontInfo as cozetteFontInfo } from './text/cozette/font'

const Worker = new EngineWorker()
export const ComWorker = Comlink.wrap<typeof RenderEngineBackend>(Worker)

Expand Down Expand Up @@ -122,7 +125,7 @@ export class RenderEngine {
width: this.canvasGL.width,
height: this.canvasGL.height,
})
this.sendGlyphData()
this.sendFontData()
new ResizeObserver(() => this.resize()).observe(this.CONTAINER)
this.addControls()
this.render({
Expand Down Expand Up @@ -342,6 +345,13 @@ export class RenderEngine {
backend.render(props)
}

/**
* Send the glyph data to the engine
* This has now been deprecated in favor of using the font renderer
* Will be removed in the future
* @deprecated
*/
// @ts-ignore - unused
private sendGlyphData(): void {
const canvas = document.createElement("canvas")
const context = canvas.getContext("2d")
Expand All @@ -359,6 +369,42 @@ export class RenderEngine {
image.src = URL.createObjectURL(new Blob([font]))
}

private sendFontData(): void {
const f = new FontFace("cozette", `url(${cozetteFont})`)
f.load().then((font) => {
document.fonts.add(font)
const canvas = document.createElement("canvas")
const context = canvas.getContext("2d")
if (!context) throw new Error("Could not get 2d context")
canvas.width = cozetteFontInfo.textureWidth
canvas.height = cozetteFontInfo.textureHeight
context.font = "13px cozette"
context.fillStyle = "white"
context.textBaseline = "top"
context.lineWidth = 2
context.strokeStyle = "black"
const characters = Object.keys(cozetteFontInfo.glyphInfos)
for (let i = 0; i < characters.length; i++) {
const char = characters[i]
context.strokeText(char, cozetteFontInfo.glyphInfos[char].x, cozetteFontInfo.glyphInfos[char].y)
context.fillText(char, cozetteFontInfo.glyphInfos[char].x, cozetteFontInfo.glyphInfos[char].y)
}

const imageData = context.getImageData(0, 0, cozetteFontInfo.textureWidth, cozetteFontInfo.textureHeight)
this.backend.then((engine) => {
engine.initializeFontRenderer(imageData.data)
})

// download font image sample
// const canvasUrl = canvas.toDataURL("image/png", 1);
// const createEl = document.createElement('a');
// createEl.href = canvasUrl;
// createEl.download = "font.png";
// createEl.click();
// createEl.remove();
})
}

public downloadImage(): void {
const canvasUrl = this.canvasGL.toDataURL("image/jpeg", 1);
const createEl = document.createElement('a');
Expand Down
Binary file not shown.
1 change: 1 addition & 0 deletions src/renderer/src/renderer/text/cozette/characters.ts

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 23012cc

Please sign in to comment.