Skip to content

Commit

Permalink
Initial text rendering (#10)
Browse files Browse the repository at this point in the history
Initial text rendering
  • Loading branch information
bryphe committed Oct 20, 2018
1 parent f4e0550 commit 07a51f0
Show file tree
Hide file tree
Showing 16 changed files with 322 additions and 91 deletions.
5 changes: 5 additions & 0 deletions esy.json
Expand Up @@ -7,6 +7,7 @@
},
"dependencies": {
"@esy-ocaml/reason": "*",
"reason-fontkit": "*",
"reason-glfw": "*",
"reason-gl-matrix": "*",
"reason-reactify": "*",
Expand All @@ -20,13 +21,17 @@
"ocaml": "~4.6.0"
},
"resolutions": {
"reason-fontkit": "github:bryphe/reason-fontkit#1826064",
"reason-glfw": "github:bryphe/reason-glfw#883e1b6",
"reason-gl-matrix": "github:bryphe/reason-gl-matrix#0ae52c1",
"reason-reactify": "github:bryphe/reason-reactify#a62c8e4",
"esy-cmake": "github:bryphe/esy-cmake#5a40a8e",
"esy-freetype2": "github:bryphe/esy-freetype2#bdce79aa3",
"esy-harfbuzz": "github:bryphe/esy-harfbuzz#b9fcbe3",
"flex": "github:bryphe/flex#a73c134",
"@opam/menhir": "20171013",
"@esy-ocaml/esy-installer": "0.0.1",
"refmterr": "github:bryphe/BetterErrors#76500c2",
"@opam/re": "1.8.0"
},
"devDependencies": {
Expand Down
41 changes: 39 additions & 2 deletions esy.lock.json
@@ -1,5 +1,5 @@
{
"hash": "ce9d2feac388890ad9ad7d6dfb93ffee",
"hash": "60f794242b9974a81484050965c5adbd",
"root": "root@path:./esy.json",
"node": {
"root@path:./esy.json": {
Expand All @@ -16,7 +16,7 @@
"@opam/js_of_ocaml-compiler@opam:3.2.1",
"@opam/js_of_ocaml-lwt@opam:3.2.1", "@opam/lwt@opam:4.1.0",
"@opam/lwt_ppx@opam:1.2.1", "flex@github:bryphe/flex#a73c134",
"ocaml@4.6.7",
"ocaml@4.6.7", "reason-fontkit@github:bryphe/reason-fontkit#1826064",
"reason-gl-matrix@github:bryphe/reason-gl-matrix#0ae52c1",
"reason-glfw@github:bryphe/reason-glfw#883e1b6",
"reason-reactify@github:bryphe/reason-reactify#a62c8e4"
Expand Down Expand Up @@ -82,6 +82,23 @@
"refmterr@3.1.7"
]
},
"reason-fontkit@github:bryphe/reason-fontkit#1826064": {
"record": {
"name": "reason-fontkit",
"version": "github:bryphe/reason-fontkit#1826064",
"source": "github:bryphe/reason-fontkit#1826064",
"files": [],
"opam": null
},
"dependencies": [
"@esy-ocaml/reason@3.3.3", "@opam/dune@opam:1.4.0",
"esy-cmake@github:bryphe/esy-cmake#5a40a8e",
"esy-freetype2@github:bryphe/esy-freetype2#bdce79aa3",
"esy-harfbuzz@github:bryphe/esy-harfbuzz#b9fcbe3",
"reason-gl-matrix@github:bryphe/reason-gl-matrix#0ae52c1",
"reason-glfw@github:bryphe/reason-glfw#883e1b6", "refmterr@3.1.7"
]
},
"ocaml@4.6.7": {
"record": {
"name": "ocaml",
Expand All @@ -105,6 +122,26 @@
"@esy-ocaml/reason@3.3.3", "@opam/dune@opam:1.4.0", "refmterr@3.1.7"
]
},
"esy-harfbuzz@github:bryphe/esy-harfbuzz#b9fcbe3": {
"record": {
"name": "esy-harfbuzz",
"version": "github:bryphe/esy-harfbuzz#b9fcbe3",
"source": "github:bryphe/esy-harfbuzz#b9fcbe3",
"files": [],
"opam": null
},
"dependencies": []
},
"esy-freetype2@github:bryphe/esy-freetype2#bdce79aa3": {
"record": {
"name": "esy-freetype2",
"version": "github:bryphe/esy-freetype2#bdce79aa3",
"source": "github:bryphe/esy-freetype2#bdce79aa3",
"files": [],
"opam": null
},
"dependencies": [ "esy-cmake@github:bryphe/esy-cmake#5a40a8e" ]
},
"esy-cmake@github:bryphe/esy-cmake#5a40a8e": {
"record": {
"name": "esy-cmake",
Expand Down
7 changes: 7 additions & 0 deletions examples/Bin.re
Expand Up @@ -24,8 +24,15 @@ let init = app => {
let child2 = new UI.viewNode("child2", Vec3.create(0.0, 1.0, 1.0));
child2#setStyle({...Layout.defaultStyle, width: 200, height: 200});

let child3 = new UI.textNode("child3", "HELLO WORLD", Vec3.create(1.0, 1.0, 1.0));

let child4 = new UI.viewNode("child4", Vec3.create(1.0, 1.0, 1.0));
child4#setStyle({...Layout.defaultStyle, width: 200, height: 200});

rootNode#addChild(child1);
rootNode#addChild(child2);
rootNode#addChild(child3);
rootNode#addChild(child4);

UI.render(rootNode);
});
Expand Down
Binary file added examples/Roboto-Regular.ttf
Binary file not shown.
2 changes: 1 addition & 1 deletion examples/dune
Expand Up @@ -12,4 +12,4 @@
(install
(section bin)
(package Revery)
(files binary.dat index.html Bin.bc.js gl-matrix-min.js))
(files Roboto-Regular.ttf binary.dat index.html Bin.bc.js gl-matrix-min.js))
10 changes: 3 additions & 7 deletions src/Shaders/BasicShader.re
Expand Up @@ -27,16 +27,12 @@ let varying: list(ShaderVarying.t) = [{


let vsShader = {|
void main() {
gl_Position = vec4(aVertexPosition, 1.0);
vColor = uColor;
}
gl_Position = vec4(aVertexPosition, 1.0);
vColor = uColor;
|};

let fsShader = {|
void main() {
gl_FragColor = vec4(vColor, 1.0);
}
gl_FragColor = vec4(vColor, 1.0);
|};

let create = () => {
Expand Down
4 changes: 2 additions & 2 deletions src/Shaders/Shader.re
Expand Up @@ -130,11 +130,11 @@ let create = (~uniforms: list(ShaderUniform.t), ~attributes: list(ShaderAttribut
let vertexShader = generateAttributeVertexShaderBlock(attributes)
++ generateUniformVertexShaderBlock(uniforms)
++ generateVaryingBlock(varying)
++ vertexShader;
++ "void main() {\n" ++ vertexShader ++ "}\n";

let fragmentShader = generateUniformPixelShaderBlock(uniforms)
++ generateVaryingBlock(varying)
++ fragmentShader;
++ "void main() {\n" ++ fragmentShader ++ "}\n";

(uniforms, attributes, varying, vertexShader, fragmentShader);
};
Expand Down
60 changes: 60 additions & 0 deletions src/UI/FontRenderer.re
@@ -0,0 +1,60 @@

open Reglfw.Glfw;
open Fontkit;

let getGlyph = (font: Fontkit.fk_face, codepoint: int) => {
/* TODO: Cache */
Fontkit.renderGlyph(font, codepoint);
};

let getTexture = (font: Fontkit.fk_face, codepoint: int) => {
let glyph = getGlyph(font, codepoint);

let {image, _ } = glyph;

/* TODO: */
/* - Cache textures */
/* - Create texture atlas */
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

let texture = glCreateTexture();
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, GL_UNSIGNED_BYTE, image);
texture
};

type dimensions = {
width: int,
height: int,
}

let measure = (font: Fontkit.fk_face, text: string) => {
let shapedText = Fontkit.fk_shape(font, text);
let minY = ref(1000);
let maxY = ref(-1000);
let x = ref(0);

Array.iter(shape => {
let {height, bearingY, advance, _} = getGlyph(font, shape.codepoint);
let top = height + bearingY;
let bottom = top + height;

if (height > 0) {
minY := minY^ < top ? minY^ : top;
maxY := maxY^ > bottom ? maxY^ : bottom;
}

x := x^ + advance;
}, shapedText);

let d: dimensions = {
height: maxY^ - minY^,
width: int_of_float(float_of_int(x^) /. 64.0),
};
d;
};
2 changes: 2 additions & 0 deletions src/UI/Layout.re
Expand Up @@ -13,8 +13,10 @@ module LayoutTestUtils = LayoutTestUtils.Create(Node, Encoding);
module Layout = Layout.Create(Node, Encoding);
module LayoutPrint = LayoutPrint.Create(Node, Encoding);
module LayoutSupport = Layout.LayoutSupport;
module LayoutTypes = LayoutTypes.Create(Node, Encoding);

let defaultStyle = LayoutSupport.defaultStyle;
let createNode = (children, style) => LayoutSupport.createNode(~withChildren=children, ~andStyle=style, rootContext);
let createNodeWithMeasure = (children, style, measure) => LayoutSupport.createNode(~withChildren=children, ~andStyle=style, ~andMeasure=measure, rootContext);
let layoutNode = (node) => Layout.layoutNode(node, Encoding.cssUndefined, Encoding.cssUndefined, Ltr);
let printCssNode = (root) => LayoutPrint.printCssNode((root, {printLayout: true, printChildren: false, printStyle: true}));
43 changes: 43 additions & 0 deletions src/UI/Node.re
@@ -0,0 +1,43 @@
module Shaders = Revery_Shaders;
module Geometry = Revery_Geometry;
module Layout = Layout;
module LayoutTypes = Layout.LayoutTypes;

class node (_name: string) = {
as _this;

val _children: ref(list(node)) = ref([]);
val _style = ref(Layout.defaultStyle);
val _layoutNode = ref(Layout.createNode([||], Layout.defaultStyle));

pub draw = (layer: int) => {
List.iter((c) => c#draw(layer + 1), _children^)
};

pub measurements = () => {
(_layoutNode^).layout;
};

pub setStyle = (style) => {
_style := style;
};

pub addChild = (n: node) => {
_children := List.append(_children^, [n]);
};

pub getMeasureFunction = () => {
None;
};

pub toLayoutNode = () => {
let childNodes = List.map((c) => c#toLayoutNode(), _children^);
let node = switch (_this#getMeasureFunction()) {
| None => Layout.createNode(Array.of_list(childNodes), _style^);
| Some(m) => Layout.createNodeWithMeasure(Array.of_list(childNodes), _style^, m);
};

_layoutNode := node;
node;
};
};
73 changes: 3 additions & 70 deletions src/UI/Revery_UI.re
@@ -1,81 +1,14 @@
open Reglm;

module Shaders = Revery_Shaders;
module Geometry = Revery_Geometry;
module Layout = Layout;
module LayoutTypes = Layout.LayoutTypes;

class node (name: string) = {
as _this;

val _children: ref(list(node)) = ref([]);
val _style = ref(Layout.defaultStyle);
val _layoutNode = ref(Layout.createNode([||], Layout.defaultStyle));

pub draw = (layer: int) => {
print_endline("- Drawing: " ++ name ++ " | " ++ string_of_int(layer));
List.iter((c) => c#draw(layer + 1), _children^)
};

pub measurements = () => {
Layout.printCssNode(_layoutNode^);
(_layoutNode^).layout;
};

pub setStyle = (style) => {
_style := style;
};

pub addChild = (n: node) => {
_children := List.append(_children^, [n]);
};

pub toLayoutNode = () => {
let childNodes = List.map((c) => c#toLayoutNode(), _children^);
let node = Layout.createNode(Array.of_list(childNodes), _style^);
_layoutNode := node;
node;
};
};

class viewNode (name: string, color: Vec3.t) = {
as _this;

val _quad = Geometry.Cube.create();
val solidShader = SolidShader.create();


inherit (class node)(name) as _super;

pub! draw = (layer: int) => {
Shaders.CompiledShader.use(solidShader);
let projection = Mat4.create();
Mat4.ortho(projection, 0.0, 800.0, 600.0, 0.0, -0.01, -100.0);
Shaders.CompiledShader.setUniformMatrix4fv(solidShader, "uProjection", projection);

let dimensions = _super#measurements();

print_endline ("**" ++ name ++ "**");
print_endline ("- top: " ++ string_of_int(dimensions.top));
print_endline ("- left: " ++ string_of_int(dimensions.left));
print_endline ("- width: " ++ string_of_int(dimensions.width));
print_endline ("- height: " ++ string_of_int(dimensions.height));

Shaders.CompiledShader.setUniform3fv(solidShader, "uColor", color);
Shaders.CompiledShader.setUniform4f(solidShader, "uPosition",
float_of_int(dimensions.left),
float_of_int(dimensions.top),
float_of_int(dimensions.width),
float_of_int(dimensions.height));
Geometry.draw(_quad, solidShader);

_super#draw(layer);
};
};
class viewNode = ViewNode.viewNode;
class textNode = TextNode.textNode;

let layout = (node) => {
let rootLayoutNode = node#toLayoutNode();
Layout.layoutNode(rootLayoutNode);
/* Layout.printCssNode(rootLayoutNode); */
};

let render = (node) => {
Expand Down
12 changes: 4 additions & 8 deletions src/UI/SolidShader.re
Expand Up @@ -36,17 +36,13 @@ let varying: list(ShaderVarying.t) = [{


let vsShader = {|
void main() {
vec4 pos = vec4(uPosition.x + (aTexCoord.x * uPosition.z), uPosition.y + (aTexCoord.y * uPosition.w), 1, 1.0);
gl_Position = uProjection * pos;
vColor = uColor;
}
vec4 pos = vec4(uPosition.x + (aTexCoord.x * uPosition.z), uPosition.y + (aTexCoord.y * uPosition.w), 1, 1.0);
gl_Position = uProjection * pos;
vColor = uColor;
|};

let fsShader = {|
void main() {
gl_FragColor = vec4(vColor, 1.0);
}
gl_FragColor = vec4(vColor, 1.0);
|};

let create = () => {
Expand Down

0 comments on commit 07a51f0

Please sign in to comment.