Files
lime/samples/TextRendering/Source/Main.hx

309 lines
7.6 KiB
Haxe
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package;
import lime.app.Application;
import lime.math.Matrix4;
import lime.graphics.*;
import lime.graphics.opengl.*;
import lime.utils.*;
class TextField {
private var vertexBuffer:GLBuffer;
private var indexBuffer:GLBuffer;
private var texture:GLTexture;
private var numTriangles:Int;
private var size:Int;
private var text:String;
private var image:ImageBuffer;
private var points:Array<TextFormat.PosInfo>;
public function new (text:String, size:Int, textFormat:TextFormat, font:Font, context:RenderContext, x:Float=0, y:Float=0) {
points = textFormat.fromString (font, size, text);
image = font.createImage ();
this.text = text;
this.size = size;
init (context, textFormat, font, x, y);
}
public function init (context:RenderContext, textFormat:TextFormat, font:Font, x:Float, y:Float) {
switch (context) {
// case CANVAS (context):
// context.fillStyle = "#" + StringTools.hex (config.background, 6);
// context.fillRect (0, 0, window.width, window.height);
// context.drawImage (image.src, 0, 0, image.width, image.height);
// case DOM (element):
// #if js
// element.style.backgroundColor = "#" + StringTools.hex (config.background, 6);
// element.appendChild (image);
// #end
case FLASH (sprite):
#if flash
var bitmap = new flash.display.Bitmap (image.src);
sprite.addChild (bitmap);
#end
case OPENGL (gl):
var vertices = new Array<Float>();
var indices = new Array<Int>();
var left, top, right, bottom;
var glyphRects = font.glyphs.get (size);
if (glyphRects == null) return;
if (textFormat.direction == RightToLeft) {
var width = 0.0;
for (p in points) {
if (!glyphRects.exists(p.codepoint)) continue;
var glyph = glyphRects.get(p.codepoint);
width += p.advance.x;
}
x -= width;
}
for (p in points) {
if (!glyphRects.exists(p.codepoint)) continue;
var glyph = glyphRects.get(p.codepoint);
left = glyph.x / image.width;
top = glyph.y / image.height;
right = left + glyph.width / image.width;
bottom = top + glyph.height / image.height;
var pointLeft = x + p.offset.x + glyph.xOffset;
var pointTop = y + p.offset.y - glyph.yOffset;
var pointRight = pointLeft + glyph.width;
var pointBottom = pointTop + glyph.height;
vertices.push(pointRight);
vertices.push(pointBottom);
vertices.push(right);
vertices.push(bottom);
vertices.push(pointLeft);
vertices.push(pointBottom);
vertices.push(left);
vertices.push(bottom);
vertices.push(pointRight);
vertices.push(pointTop);
vertices.push(right);
vertices.push(top);
vertices.push(pointLeft);
vertices.push(pointTop);
vertices.push(left);
vertices.push(top);
var i = Std.int(indices.length / 6) * 4;
indices.push(i);
indices.push(i+1);
indices.push(i+2);
indices.push(i+1);
indices.push(i+2);
indices.push(i+3);
x += p.advance.x;
y -= p.advance.y; // flip because of y-axis direction
}
numTriangles = indices.length;
vertexBuffer = gl.createBuffer ();
gl.bindBuffer (gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData (gl.ARRAY_BUFFER, new Float32Array (cast vertices), gl.STATIC_DRAW);
indexBuffer = gl.createBuffer ();
gl.bindBuffer (gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, new UInt8Array (cast indices), gl.STATIC_DRAW);
var format = image.bitsPerPixel == 1 ? GL.ALPHA : GL.RGBA;
texture = gl.createTexture ();
gl.bindTexture (gl.TEXTURE_2D, texture);
#if js
gl.texImage2D (gl.TEXTURE_2D, 0, format, format, gl.UNSIGNED_BYTE, image.src);
#else
gl.texImage2D (gl.TEXTURE_2D, 0, format, image.width, image.height, 0, format, gl.UNSIGNED_BYTE, image.data);
#end
gl.texParameteri (gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri (gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
default:
}
}
public function render (context:RenderContext, vertexAttribute:Int, textureAttribute:Int) {
switch (context) {
case OPENGL (gl):
gl.activeTexture (gl.TEXTURE0);
gl.bindTexture (gl.TEXTURE_2D, texture);
gl.bindBuffer (gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer (vertexAttribute, 2, gl.FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer (textureAttribute, 2, gl.FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 2 * Float32Array.BYTES_PER_ELEMENT);
gl.bindBuffer (gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.drawElements (gl.TRIANGLES, numTriangles, gl.UNSIGNED_BYTE, 0);
default:
}
}
}
class Main extends Application {
private var matrixUniform:GLUniformLocation;
private var program:GLProgram;
private var textureAttribute:Int;
private var vertexAttribute:Int;
private var textFields:Array<TextField>;
public function new () {
super ();
textFields = new Array<TextField> ();
}
public override function init (context:RenderContext):Void {
textFields.push(new TextField ("صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ", 16,
new TextFormat (RightToLeft, ScriptArabic, "ar"),
Font.fromFile ("assets/amiri-regular.ttf"),
context, window.width, 80));
textFields.push(new TextField ("The quick brown fox jumps over the lazy dog.", 16,
new TextFormat (LeftToRight, ScriptLatin, "en"),
Font.fromFile ("assets/amiri-regular.ttf"),
context, 20, 20));
textFields.push(new TextField ("", 32,
new TextFormat (TopToBottom, ScriptHan, "zh"),
Font.fromFile ("assets/fireflysung.ttf"),
context, 50, 170));
switch (context) {
case OPENGL (gl):
var vertexSource =
"attribute vec4 aPosition;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
uniform mat4 uMatrix;
void main(void) {
vTexCoord = aTexCoord;
gl_Position = uMatrix * aPosition;
}";
var fragmentSource =
"#ifdef GL_ES
precision mediump float;
#endif
varying vec2 vTexCoord;
uniform sampler2D uImage0;
void main(void)
{
gl_FragColor = vec4 (0, 0, 0, texture2D (uImage0, vTexCoord).a);
}";
program = GLUtils.createProgram (vertexSource, fragmentSource);
gl.useProgram (program);
vertexAttribute = gl.getAttribLocation (program, "aPosition");
textureAttribute = gl.getAttribLocation (program, "aTexCoord");
matrixUniform = gl.getUniformLocation (program, "uMatrix");
var imageUniform = gl.getUniformLocation (program, "uImage0");
gl.enableVertexAttribArray (vertexAttribute);
gl.enableVertexAttribArray (textureAttribute);
gl.uniform1i (imageUniform, 0);
#if desktop
gl.enable (gl.TEXTURE_2D);
#end
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
gl.viewport (0, 0, window.width, window.height);
default:
}
}
public override function render (context:RenderContext):Void {
switch (context) {
case OPENGL (gl):
var r = ((config.background >> 16) & 0xFF) / 0xFF;
var g = ((config.background >> 8) & 0xFF) / 0xFF;
var b = (config.background & 0xFF) / 0xFF;
var a = ((config.background >> 24) & 0xFF) / 0xFF;
gl.clearColor (r, g, b, a);
gl.clear (gl.COLOR_BUFFER_BIT);
var matrix = Matrix4.createOrtho (0, window.width, window.height, 0, -10, 10);
gl.uniformMatrix4fv (matrixUniform, false, matrix);
for (i in 0...textFields.length) {
textFields[i].render (context, vertexAttribute, textureAttribute);
}
default:
}
}
}