// node_modules/.bin/ts-node example/display-command.ts | display
import * as Jimp from "jimp";
import { Rect } from "../src/layout";
import { Canvas, DisplayCommand } from "../src/painting";
import { Color } from "../src/css";
const black = new Color(0, 0, 0, 255);
const canvas = Canvas.Create(200, 100);
canvas.paintItem(new DisplayCommand.SolidColor(black, new Rect(10, 20, 30, 30)));
Jimp.create(canvas.width, canvas.height)
.then((value: Jimp) => {
let buffer = value.bitmap.data;
for (let i = 0; i < canvas.pixels.length; i++) {
buffer[i * 4] = canvas.pixels[i].r;
buffer[i * 4 + 1] = canvas.pixels[i].g;
buffer[i * 4 + 2] = canvas.pixels[i].b;
buffer[i * 4 + 3] = canvas.pixels[i].a;
}
return value.getBufferAsync(Jimp.MIME_PNG);
})
.then((value: Buffer) => {
process.stdout.write(value);
})
.catch((error: Error) => {
console.error(error);
});
import { Rect } from "../src/layout";
test("rect", () => {
expect(new Rect(1, 2, 3, 4).height).toBe(4);
});
export class Rect {
x: number;
y: number;
width: number;
height: number;
constructor(x: number, y: number, width: number, height: number) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
import { Canvas, DisplayCommand } from "../src/painting";
import { Color } from "../src/css";
import { Rect } from "../src/layout";
const white = new Color(255, 255, 255, 255);
const black = new Color(0, 0, 0, 255);
test("solid color", () => {
expect(new DisplayCommand.SolidColor(white, new Rect(0, 0, 0, 0)).format).toEqual(
DisplayCommand.Format.SolidColor
);
});
test("canvas paint item", () => {
const canvas = Canvas.Create(2, 3);
canvas.paintItem(new DisplayCommand.SolidColor(black, new Rect(0, 0, 1, 1)));
expect(canvas.pixels).toEqual([black, white, white, white, white, white]);
});
import { Color } from "./css";
import { Rect } from "./layout";
const mathClamp = require("math-clamp");
export class Canvas {
// snip
paintItem(item: DisplayCommand) {
switch (item.format) {
case DisplayCommand.Format.SolidColor:
const rect = item.rect;
const color = item.color;
let x0 = mathClamp(rect.x, 0.0, this.width);
let y0 = mathClamp(rect.y, 0.0, this.height);
let x1 = mathClamp(rect.x + rect.width, 0.0, this.width);
let y1 = mathClamp(rect.y + rect.height, 0.0, this.height);
for (let y = y0; y < y1; y++) {
for (let x = x0; x < x1; x++) {
// TODO: alpha compositing with existing pixel
this.pixels[x + y * this.width] = color;
}
}
}
}
}
export namespace DisplayCommand {
export enum Format {
SolidColor
}
export class SolidColor {
readonly format = Format.SolidColor;
color: Color;
rect: Rect;
constructor(color: Color, rect: Rect) {
this.color = color;
this.rect = rect;
}
}
}
export type DisplayCommand = DisplayCommand.SolidColor;
It works!
references
- Let's build a browser engine! Part 1: Getting started
- mbrubeck/robinson
- sanemat/js-toy-engine
- sanemat/ts-toy-engine
series
- Let's build browser engine! in typescript vol0 Toy browser engine
- Let's build browser engine! in typescript vol1 Canvas with Color
- Let's build browser engine! in typescript vol2 Display Command
- Let's build browser engine! in typescript vol3 Layout Box, Dimensions
- Let's build browser engine! in typescript vol4 Layout Tree to Display List
Top comments (0)