Adding simplistic font rendering for HTML5 and Flash
This commit is contained in:
@@ -4,6 +4,7 @@ package lime;
|
||||
|
||||
import haxe.Unserializer;
|
||||
import lime.graphics.Image;
|
||||
import lime.graphics.Font;
|
||||
import lime.utils.ByteArray;
|
||||
|
||||
|
||||
@@ -456,11 +457,11 @@ class Assets {
|
||||
|
||||
}
|
||||
|
||||
/*if (type == AssetType.FONT || type == null) {
|
||||
if (type == AssetType.FONT || type == null) {
|
||||
|
||||
if (cache.font.exists (id)) return true;
|
||||
|
||||
}*/
|
||||
}
|
||||
|
||||
if (type == AssetType.SOUND || type == AssetType.MUSIC || type == null) {
|
||||
|
||||
@@ -1100,13 +1101,13 @@ class AssetCache {
|
||||
|
||||
public var enabled:Bool = true;
|
||||
public var image:Map<String, Image>;
|
||||
//public var font:Map<String, Font>;
|
||||
public var font:Map<String, Font>;
|
||||
public var sound:Map<String, Dynamic /*Sound*/>;
|
||||
|
||||
|
||||
public function new () {
|
||||
|
||||
//font = new Map<String, Font> ();
|
||||
font = new Map<String, Font> ();
|
||||
image = new Map<String, Image> ();
|
||||
sound = new Map<String, Dynamic /*Sound*/> ();
|
||||
|
||||
@@ -1117,7 +1118,7 @@ class AssetCache {
|
||||
|
||||
if (prefix == null) {
|
||||
|
||||
//font = new Map<String, Font> ();
|
||||
font = new Map<String, Font> ();
|
||||
image = new Map<String, Image> ();
|
||||
sound = new Map<String, Dynamic /*Sound*/> ();
|
||||
|
||||
@@ -1135,7 +1136,7 @@ class AssetCache {
|
||||
|
||||
}
|
||||
|
||||
/*var keys = font.keys ();
|
||||
var keys = font.keys ();
|
||||
|
||||
for (key in keys) {
|
||||
|
||||
@@ -1145,7 +1146,7 @@ class AssetCache {
|
||||
|
||||
}
|
||||
|
||||
}*/
|
||||
}
|
||||
|
||||
var keys = sound.keys ();
|
||||
|
||||
@@ -1462,22 +1463,22 @@ class Assets {
|
||||
#end
|
||||
|
||||
var bytes = File.getBytes (path);
|
||||
var resourceName = "NME_font_" + (classType.pack.length > 0 ? classType.pack.join ("_") + "_" : "") + classType.name;
|
||||
var resourceName = "LIME_font_" + (classType.pack.length > 0 ? classType.pack.join ("_") + "_" : "") + classType.name;
|
||||
|
||||
Context.addResource (resourceName, bytes);
|
||||
|
||||
var fieldValue = { pos: position, expr: EConst(CString(resourceName)) };
|
||||
fields.push ({ kind: FVar(macro :String, fieldValue), name: "resourceName", access: [ APublic, AStatic ], pos: position });
|
||||
|
||||
//var constructor = macro {
|
||||
//
|
||||
//super();
|
||||
//
|
||||
//fontName = resourceName;
|
||||
//
|
||||
//};
|
||||
//
|
||||
//fields.push ({ name: "new", access: [ APublic ], kind: FFun({ args: [], expr: constructor, params: [], ret: null }), pos: Context.currentPos() });
|
||||
var constructor = macro {
|
||||
|
||||
super();
|
||||
|
||||
fontName = resourceName;
|
||||
|
||||
};
|
||||
|
||||
fields.push ({ name: "new", access: [ APublic ], kind: FFun({ args: [], expr: constructor, params: [], ret: null }), pos: Context.currentPos() });
|
||||
|
||||
return fields;
|
||||
|
||||
|
||||
@@ -1,30 +1,205 @@
|
||||
package lime.graphics;
|
||||
|
||||
import haxe.ds.StringMap;
|
||||
import lime.utils.UInt8Array;
|
||||
import lime.system.System;
|
||||
#if js
|
||||
import js.html.CanvasElement;
|
||||
import js.html.CanvasRenderingContext2D;
|
||||
#end
|
||||
|
||||
typedef GlyphRect = {
|
||||
var x:Float;
|
||||
var y:Float;
|
||||
var width:Float;
|
||||
var height:Float;
|
||||
}
|
||||
|
||||
typedef GlyphData = {
|
||||
var image:Image;
|
||||
var glyphs:Array<Dynamic>;
|
||||
var glyphs:StringMap<GlyphRect>;
|
||||
};
|
||||
|
||||
@:autoBuild(lime.Assets.embedFont())
|
||||
class Font {
|
||||
|
||||
#if (cpp || neko)
|
||||
public var handle:Dynamic;
|
||||
#if js
|
||||
|
||||
private static var __canvas:CanvasElement;
|
||||
private static var __context:CanvasRenderingContext2D;
|
||||
|
||||
#elseif (cpp || neko)
|
||||
|
||||
public var handle:GlyphRect;
|
||||
|
||||
#end
|
||||
|
||||
public var fontFace(default, null):String;
|
||||
|
||||
public function new (fontFace:String) {
|
||||
|
||||
this.fontFace = fontFace;
|
||||
|
||||
#if (cpp || neko)
|
||||
|
||||
handle = lime_font_load (fontFace);
|
||||
|
||||
#end
|
||||
|
||||
}
|
||||
|
||||
public function createImage (size:Int, glyphs:String="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^`'\"/\\&*()[]{}<>|:;_-+=?,. "):GlyphData {
|
||||
|
||||
#if (cpp || neko)
|
||||
var glyphRects = new StringMap<GlyphRect>();
|
||||
|
||||
#if js
|
||||
|
||||
if (__canvas == null) {
|
||||
|
||||
__canvas = cast js.Browser.document.createElement ("canvas");
|
||||
__context = cast __canvas.getContext ("2d");
|
||||
|
||||
}
|
||||
|
||||
__canvas.width = __canvas.height = 128;
|
||||
__context.fillStyle = "#000000";
|
||||
__context.textBaseline = "top";
|
||||
__context.textAlign = "left";
|
||||
__context.font = size + "px " + fontFace;
|
||||
|
||||
// canvas doesn't give the appropriate metrics so the values have to be padded...
|
||||
var padding = size / 4;
|
||||
|
||||
var x = 0.0, y = 0.0, i = 0;
|
||||
|
||||
var height = size + padding;
|
||||
|
||||
while (i < glyphs.length) {
|
||||
|
||||
var c = glyphs.charAt(i++);
|
||||
var metrics = __context.measureText (c);
|
||||
var width = metrics.width + 4; // fudge because of incorrect text metrics
|
||||
|
||||
if (x + width > __canvas.width) {
|
||||
|
||||
y += height + 1;
|
||||
x = 0;
|
||||
|
||||
}
|
||||
|
||||
if (y + height > __canvas.height) {
|
||||
|
||||
if (__canvas.width < __canvas.height) {
|
||||
|
||||
__canvas.width *= 2;
|
||||
|
||||
} else {
|
||||
|
||||
__canvas.height *= 2;
|
||||
|
||||
}
|
||||
|
||||
__context.clearRect (0, 0, __canvas.width, __canvas.height);
|
||||
__context.textBaseline = "top";
|
||||
__context.textAlign = "left";
|
||||
__context.fillStyle = "#000000";
|
||||
__context.font = size + "px " + fontFace;
|
||||
|
||||
glyphRects = new StringMap<GlyphRect>();
|
||||
x = y = i = 0;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
__context.fillText (c, x + 2, y);
|
||||
glyphRects.set(c, {
|
||||
x: x,
|
||||
y: y,
|
||||
width: width,
|
||||
height: height
|
||||
});
|
||||
|
||||
x += width;
|
||||
|
||||
}
|
||||
|
||||
var image = new js.html.Image ();
|
||||
image.src = __canvas.toDataURL();
|
||||
return {
|
||||
glyphs: glyphRects,
|
||||
image: new lime.graphics.Image (image, __canvas.width, __canvas.height)
|
||||
}
|
||||
|
||||
#elseif flash
|
||||
|
||||
var bd = new flash.display.BitmapData(128, 128, true, 0);
|
||||
var tf = new flash.text.TextField ();
|
||||
var format = new flash.text.TextFormat ();
|
||||
format.size = size;
|
||||
format.font = fontFace;
|
||||
tf.defaultTextFormat = format;
|
||||
// tf.embedFonts = true;
|
||||
var mat = new flash.geom.Matrix ();
|
||||
|
||||
var i = 0, x = 0.0, y = 0.0, maxHeight = 0.0;
|
||||
|
||||
while (i < glyphs.length) {
|
||||
|
||||
var c = glyphs.charAt(i++);
|
||||
tf.text = c;
|
||||
|
||||
if (x + tf.textWidth > bd.width) {
|
||||
|
||||
y += maxHeight + 1;
|
||||
x = maxHeight = 0;
|
||||
|
||||
}
|
||||
|
||||
if (y + tf.textHeight > bd.height) {
|
||||
|
||||
if (bd.width < bd.height) {
|
||||
|
||||
bd = new flash.display.BitmapData(bd.width * 2, bd.height, true, 0);
|
||||
|
||||
} else {
|
||||
|
||||
bd = new flash.display.BitmapData(bd.width, bd.height * 2, true, 0);
|
||||
|
||||
}
|
||||
|
||||
glyphRects = new StringMap<GlyphRect>();
|
||||
x = y = maxHeight = i = 0;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
mat.identity ();
|
||||
mat.translate (x, y);
|
||||
bd.draw (tf, mat);
|
||||
|
||||
glyphRects.set(c, {
|
||||
x: x,
|
||||
y: y,
|
||||
width: tf.textWidth + 2,
|
||||
height: tf.textHeight + 2
|
||||
});
|
||||
|
||||
x += tf.textWidth + 4;
|
||||
|
||||
if (tf.textHeight + 4 > maxHeight) {
|
||||
|
||||
maxHeight = tf.textHeight + 4;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
glyphs: glyphRects,
|
||||
image: new Image (bd, bd.width, bd.height)
|
||||
}
|
||||
|
||||
#elseif (cpp || neko)
|
||||
|
||||
var data = lime_font_load_glyphs (handle, size, glyphs);
|
||||
|
||||
@@ -34,8 +209,19 @@ class Font {
|
||||
|
||||
} else {
|
||||
|
||||
for (glyph in cast (data.glyphs, Array<Dynamic>)) {
|
||||
|
||||
glyphRects.set (glyph.char, {
|
||||
x: glyph.x,
|
||||
y: glyph.y,
|
||||
width: glyph.width,
|
||||
height: glyph.height,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
glyphs: data.glyphs,
|
||||
glyphs: glyphRects,
|
||||
image: new Image (new UInt8Array (data.image.data), data.image.width, data.image.height, data.image.bpp)
|
||||
};
|
||||
|
||||
@@ -43,8 +229,6 @@ class Font {
|
||||
|
||||
#end
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
#if (cpp || neko)
|
||||
|
||||
@@ -610,8 +610,8 @@ class DefaultAssetLibrary extends AssetLibrary {
|
||||
|
||||
#elseif html5
|
||||
|
||||
//::foreach assets::::if (type == "font")::@:keep class __ASSET__::flatName:: extends openfl.text.Font { #if (!openfl_html5_dom) public function new () { super (); fontName = "::id::"; } #end }::end::
|
||||
//::end::
|
||||
::foreach assets::::if (type == "font")::@:keep class __ASSET__::flatName:: extends lime.graphics.Font { public function new () { super ("::id::"); } }::end::
|
||||
::end::
|
||||
|
||||
#elseif (windows || mac || linux)
|
||||
|
||||
@@ -621,7 +621,8 @@ class DefaultAssetLibrary extends AssetLibrary {
|
||||
//::elseif (type == "music")::@:sound("::sourcePath::") class __ASSET__::flatName:: extends openfl.media.Sound {}
|
||||
//::elseif (type == "font")::@:font("::sourcePath::") class __ASSET__::flatName:: extends openfl.text.Font {}
|
||||
//::else::@:file("::sourcePath::") class __ASSET__::flatName:: extends lime.utils.ByteArray {}
|
||||
::end::::end::::end::::end::
|
||||
//::end::::end::::end::
|
||||
::end::
|
||||
|
||||
#end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user