Decouple text renderers from HTML canvas elements.
This allows for offscreen rendering of text.
This commit is contained in:
parent
562851fd6e
commit
32de1d3441
|
@ -63,10 +63,23 @@ interface PerspectiveMovementKeys {
|
||||||
[keyCode: number]: boolean;
|
[keyCode: number]: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class Camera {
|
export interface CameraView {
|
||||||
protected canvas: HTMLCanvasElement;
|
readonly width: number;
|
||||||
|
readonly height: number;
|
||||||
|
readonly classList: DOMTokenList | null;
|
||||||
|
|
||||||
constructor(canvas: HTMLCanvasElement) {
|
addEventListener<K extends keyof HTMLElementEventMap>(type: K,
|
||||||
|
listener: (this: HTMLCanvasElement,
|
||||||
|
ev: HTMLElementEventMap[K]) =>
|
||||||
|
any,
|
||||||
|
useCapture?: boolean): void;
|
||||||
|
getBoundingClientRect(): ClientRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class Camera {
|
||||||
|
protected canvas: CameraView;
|
||||||
|
|
||||||
|
constructor(canvas: CameraView) {
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +101,7 @@ export class OrthographicCamera extends Camera {
|
||||||
private readonly scaleBounds: boolean;
|
private readonly scaleBounds: boolean;
|
||||||
private readonly ignoreBounds: boolean;
|
private readonly ignoreBounds: boolean;
|
||||||
|
|
||||||
constructor(canvas: HTMLCanvasElement, options?: OrthographicCameraOptions) {
|
constructor(canvas: CameraView, options?: OrthographicCameraOptions) {
|
||||||
super(canvas);
|
super(canvas);
|
||||||
|
|
||||||
if (options == null)
|
if (options == null)
|
||||||
|
@ -104,16 +117,21 @@ export class OrthographicCamera extends Camera {
|
||||||
|
|
||||||
this._bounds = glmatrix.vec4.create();
|
this._bounds = glmatrix.vec4.create();
|
||||||
|
|
||||||
|
if (this.canvas != null) {
|
||||||
this.canvas.addEventListener('wheel', event => this.onWheel(event), false);
|
this.canvas.addEventListener('wheel', event => this.onWheel(event), false);
|
||||||
this.canvas.addEventListener('mousedown', event => this.onMouseDown(event), false);
|
this.canvas.addEventListener('mousedown', event => this.onMouseDown(event), false);
|
||||||
this.canvas.addEventListener('mouseup', event => this.onMouseUp(event), false);
|
this.canvas.addEventListener('mouseup', event => this.onMouseUp(event), false);
|
||||||
this.canvas.addEventListener('mousemove', event => this.onMouseMove(event), false);
|
this.canvas.addEventListener('mousemove', event => this.onMouseMove(event), false);
|
||||||
|
}
|
||||||
|
|
||||||
this.onPan = null;
|
this.onPan = null;
|
||||||
this.onZoom = null;
|
this.onZoom = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
onWheel(event: MouseWheelEvent): void {
|
onWheel(event: MouseWheelEvent): void {
|
||||||
|
if (this.canvas == null)
|
||||||
|
throw new Error("onWheel() with no canvas?!");
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (!event.ctrlKey) {
|
if (!event.ctrlKey) {
|
||||||
|
@ -161,10 +179,12 @@ export class OrthographicCamera extends Camera {
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMouseDown(event: MouseEvent): void {
|
private onMouseDown(event: MouseEvent): void {
|
||||||
|
if (this.canvas.classList != null)
|
||||||
this.canvas.classList.add('pf-grabbing');
|
this.canvas.classList.add('pf-grabbing');
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMouseUp(event: MouseEvent): void {
|
private onMouseUp(event: MouseEvent): void {
|
||||||
|
if (this.canvas.classList != null)
|
||||||
this.canvas.classList.remove('pf-grabbing');
|
this.canvas.classList.remove('pf-grabbing');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +263,8 @@ export class OrthographicCamera extends Camera {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PerspectiveCamera extends Camera {
|
export class PerspectiveCamera extends Camera {
|
||||||
|
canvas: HTMLCanvasElement;
|
||||||
|
|
||||||
onChange: (() => void) | null;
|
onChange: (() => void) | null;
|
||||||
|
|
||||||
translation: glmatrix.vec3;
|
translation: glmatrix.vec3;
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {StemDarkeningMode, SubpixelAAType} from './aa-strategy';
|
||||||
import {DemoAppController} from './app-controller';
|
import {DemoAppController} from './app-controller';
|
||||||
import {Atlas, AtlasGlyph, SUBPIXEL_GRANULARITY} from './atlas';
|
import {Atlas, AtlasGlyph, SUBPIXEL_GRANULARITY} from './atlas';
|
||||||
import PathfinderBufferTexture from './buffer-texture';
|
import PathfinderBufferTexture from './buffer-texture';
|
||||||
import {OrthographicCamera} from "./camera";
|
import {CameraView, OrthographicCamera} from "./camera";
|
||||||
import {createFramebuffer, createFramebufferColorTexture} from './gl-utils';
|
import {createFramebuffer, createFramebufferColorTexture} from './gl-utils';
|
||||||
import {createFramebufferDepthTexture, QUAD_ELEMENTS, setTextureParameters} from './gl-utils';
|
import {createFramebufferDepthTexture, QUAD_ELEMENTS, setTextureParameters} from './gl-utils';
|
||||||
import {UniformMap} from './gl-utils';
|
import {UniformMap} from './gl-utils';
|
||||||
|
@ -260,6 +260,10 @@ class TextDemoView extends DemoView implements TextRenderContext {
|
||||||
|
|
||||||
appController: TextDemoController;
|
appController: TextDemoController;
|
||||||
|
|
||||||
|
get cameraView(): CameraView {
|
||||||
|
return this.canvas;
|
||||||
|
}
|
||||||
|
|
||||||
get atlasGlyphs(): AtlasGlyph[] {
|
get atlasGlyphs(): AtlasGlyph[] {
|
||||||
return this.appController.atlasGlyphs;
|
return this.appController.atlasGlyphs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import * as _ from 'lodash';
|
||||||
import {AntialiasingStrategy, AntialiasingStrategyName, NoAAStrategy} from './aa-strategy';
|
import {AntialiasingStrategy, AntialiasingStrategyName, NoAAStrategy} from './aa-strategy';
|
||||||
import {StemDarkeningMode, SubpixelAAType} from './aa-strategy';
|
import {StemDarkeningMode, SubpixelAAType} from './aa-strategy';
|
||||||
import {Atlas, ATLAS_SIZE, AtlasGlyph, GlyphKey, SUBPIXEL_GRANULARITY} from './atlas';
|
import {Atlas, ATLAS_SIZE, AtlasGlyph, GlyphKey, SUBPIXEL_GRANULARITY} from './atlas';
|
||||||
import {OrthographicCamera} from './camera';
|
import {CameraView, OrthographicCamera} from './camera';
|
||||||
import {createFramebuffer, createFramebufferDepthTexture, QUAD_ELEMENTS} from './gl-utils';
|
import {createFramebuffer, createFramebufferDepthTexture, QUAD_ELEMENTS} from './gl-utils';
|
||||||
import {UniformMap} from './gl-utils';
|
import {UniformMap} from './gl-utils';
|
||||||
import {Renderer} from './renderer';
|
import {Renderer} from './renderer';
|
||||||
|
@ -44,6 +44,7 @@ const ANTIALIASING_STRATEGIES: AntialiasingStrategyTable = {
|
||||||
export interface TextRenderContext extends RenderContext {
|
export interface TextRenderContext extends RenderContext {
|
||||||
atlasGlyphs: AtlasGlyph[];
|
atlasGlyphs: AtlasGlyph[];
|
||||||
|
|
||||||
|
readonly cameraView: CameraView;
|
||||||
readonly atlas: Atlas;
|
readonly atlas: Atlas;
|
||||||
readonly layout: SimpleTextLayout;
|
readonly layout: SimpleTextLayout;
|
||||||
readonly glyphStore: GlyphStore;
|
readonly glyphStore: GlyphStore;
|
||||||
|
@ -53,9 +54,6 @@ export interface TextRenderContext extends RenderContext {
|
||||||
readonly layoutPixelsPerUnit: number;
|
readonly layoutPixelsPerUnit: number;
|
||||||
readonly useHinting: boolean;
|
readonly useHinting: boolean;
|
||||||
|
|
||||||
// TODO(pcwalton): Remove this.
|
|
||||||
readonly canvas: HTMLCanvasElement;
|
|
||||||
|
|
||||||
newTimingsReceived(timings: Timings): void;
|
newTimingsReceived(timings: Timings): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +137,7 @@ export class TextRenderer extends Renderer {
|
||||||
constructor(renderContext: TextRenderContext) {
|
constructor(renderContext: TextRenderContext) {
|
||||||
super(renderContext);
|
super(renderContext);
|
||||||
|
|
||||||
this.camera = new OrthographicCamera(this.renderContext.canvas, {
|
this.camera = new OrthographicCamera(this.renderContext.cameraView, {
|
||||||
maxScale: MAX_SCALE,
|
maxScale: MAX_SCALE,
|
||||||
minScale: MIN_SCALE,
|
minScale: MIN_SCALE,
|
||||||
});
|
});
|
||||||
|
@ -244,8 +242,8 @@ export class TextRenderer extends Renderer {
|
||||||
this.renderContext.gl.bindFramebuffer(this.renderContext.gl.FRAMEBUFFER, null);
|
this.renderContext.gl.bindFramebuffer(this.renderContext.gl.FRAMEBUFFER, null);
|
||||||
this.renderContext.gl.viewport(0,
|
this.renderContext.gl.viewport(0,
|
||||||
0,
|
0,
|
||||||
this.renderContext.canvas.width,
|
this.renderContext.cameraView.width,
|
||||||
this.renderContext.canvas.height);
|
this.renderContext.cameraView.height);
|
||||||
this.renderContext.gl.disable(this.renderContext.gl.DEPTH_TEST);
|
this.renderContext.gl.disable(this.renderContext.gl.DEPTH_TEST);
|
||||||
this.renderContext.gl.disable(this.renderContext.gl.SCISSOR_TEST);
|
this.renderContext.gl.disable(this.renderContext.gl.SCISSOR_TEST);
|
||||||
this.renderContext.gl.blendEquation(this.renderContext.gl.FUNC_ADD);
|
this.renderContext.gl.blendEquation(this.renderContext.gl.FUNC_ADD);
|
||||||
|
@ -288,8 +286,8 @@ export class TextRenderer extends Renderer {
|
||||||
const transform = glmatrix.mat4.create();
|
const transform = glmatrix.mat4.create();
|
||||||
glmatrix.mat4.fromTranslation(transform, [-1.0, -1.0, 0.0]);
|
glmatrix.mat4.fromTranslation(transform, [-1.0, -1.0, 0.0]);
|
||||||
glmatrix.mat4.scale(transform, transform, [
|
glmatrix.mat4.scale(transform, transform, [
|
||||||
2.0 / this.renderContext.canvas.width,
|
2.0 / this.renderContext.cameraView.width,
|
||||||
2.0 / this.renderContext.canvas.height,
|
2.0 / this.renderContext.cameraView.height,
|
||||||
1.0,
|
1.0,
|
||||||
]);
|
]);
|
||||||
glmatrix.mat4.translate(transform,
|
glmatrix.mat4.translate(transform,
|
||||||
|
@ -439,8 +437,8 @@ export class TextRenderer extends Renderer {
|
||||||
const canvasRect = glmatrix.vec4.clone([
|
const canvasRect = glmatrix.vec4.clone([
|
||||||
-translation[0],
|
-translation[0],
|
||||||
-translation[1],
|
-translation[1],
|
||||||
-translation[0] + this.renderContext.canvas.width,
|
-translation[0] + this.renderContext.cameraView.width,
|
||||||
-translation[1] + this.renderContext.canvas.height,
|
-translation[1] + this.renderContext.cameraView.height,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let atlasGlyphs = [];
|
let atlasGlyphs = [];
|
||||||
|
|
Loading…
Reference in New Issue