فهرست منبع

Merge branch 'lime' of https://github.com/motion-twin/heaps into lime

kiroukou 9 سال پیش
والد
کامیت
ab73684e02
9فایلهای تغییر یافته به همراه162 افزوده شده و 20 حذف شده
  1. 23 13
      h2d/Text.hx
  2. 4 1
      h3d/impl/GlDriver.hx
  3. 16 0
      h3d/shader/WhiteAlpha.hx
  4. 1 0
      hxd/PixelFormat.hx
  5. 1 0
      hxd/Pixels.hx
  6. 4 2
      hxd/System.hx
  7. 5 3
      hxd/impl/LimeStage.hx
  8. 3 1
      hxd/res/Font.hx
  9. 105 0
      hxd/res/FontBuilder.hx

+ 23 - 13
h2d/Text.hx

@@ -27,6 +27,10 @@ class Text extends Drawable {
 	var calcWidth:Int;
 	var calcHeight:Int;
 	var calcSizeHeight:Int;
+	
+	#if lime
+	var waShader : h3d.shader.WhiteAlpha;
+	#end
 
 	public function new( font : Font, ?parent ) {
 		super(parent);
@@ -41,6 +45,12 @@ class Text extends Drawable {
 	function set_font(font) {
 		if( this.font == font ) return font;
 		this.font = font;
+		#if lime
+		if( font.tile.getTexture().format == ALPHA )
+			if( waShader == null ) addShader( waShader = new h3d.shader.WhiteAlpha() );
+		else
+			if( waShader != null ) removeShader( waShader );
+		#end
 		if( glyphs != null ) glyphs.remove();
 		glyphs = new TileGroup(font == null ? null : font.tile, this);
 		glyphs.visible = false;
@@ -133,8 +143,8 @@ class Text extends Drawable {
 			return text;
 		var lines = [], rest = text, restPos = 0;
 		var x = leftMargin, prevChar = -1;
-		for( i in 0...text.length ) {
-			var cc = text.charCodeAt(i);
+		for( i in 0...haxe.Utf8.length(text) ) {
+			var cc = haxe.Utf8.charCodeAt(text, i);
 			var e = font.getChar(cc);
 			var newline = cc == '\n'.code;
 			var esize = e.width + e.getKerningOffset(prevChar);
@@ -144,10 +154,10 @@ class Text extends Drawable {
 					x -= leftMargin;
 				}
 				var size = x + esize + letterSpacing;
-				var k = i + 1, max = text.length;
+				var k = i + 1, max = haxe.Utf8.length(text);
 				var prevChar = prevChar;
-				while( size <= maxWidth && k < text.length ) {
-					var cc = text.charCodeAt(k++);
+				while( size <= maxWidth && k < max ) {
+					var cc = haxe.Utf8.charCodeAt(text, k++);
 					if( font.charset.isSpace(cc) || cc == '\n'.code ) break;
 					var e = font.getChar(cc);
 					size += e.width + letterSpacing + e.getKerningOffset(prevChar);
@@ -155,7 +165,7 @@ class Text extends Drawable {
 				}
 				if( size > maxWidth ) {
 					newline = true;
-					lines.push(text.substr(restPos, i - restPos));
+					lines.push(haxe.Utf8.sub(text,restPos, i - restPos));
 					restPos = i;
 					if( font.charset.isSpace(cc) ) {
 						e = null;
@@ -171,10 +181,10 @@ class Text extends Drawable {
 			} else
 				prevChar = cc;
 		}
-		if( restPos < text.length ) {
+		if( restPos < haxe.Utf8.length(text) ) {
 			if( lines.length == 0 && leftMargin > 0 && x > maxWidth )
 				lines.push("");
-			lines.push(text.substr(restPos, text.length - restPos));
+			lines.push(haxe.Utf8.sub(text, restPos, haxe.Utf8.length(text) - restPos));
 		}
 		return lines.join("\n");
 	}
@@ -197,8 +207,8 @@ class Text extends Drawable {
 		var dl = font.lineHeight + lineSpacing;
 		var calcLines = !rebuild && lines != null;
 		var yMin = 0;
-		for( i in 0...text.length ) {
-			var cc = text.charCodeAt(i);
+		for( i in 0...haxe.Utf8.length(text) ) {
+			var cc = haxe.Utf8.charCodeAt(text,i);
 			var e = font.getChar(cc);
 			var newline = cc == '\n'.code;
 			var offs = e.getKerningOffset(prevChar);
@@ -206,10 +216,10 @@ class Text extends Drawable {
 			// if the next word goes past the max width, change it into a newline
 			if( font.charset.isBreakChar(cc) && maxWidth != null ) {
 				var size = x + esize + letterSpacing;
-				var k = i + 1, max = text.length;
+				var k = i + 1, max = haxe.Utf8.length(text);
 				var prevChar = prevChar;
-				while( size <= maxWidth && k < text.length ) {
-					var cc = text.charCodeAt(k++);
+				while( size <= maxWidth && k < max ) {
+					var cc = haxe.Utf8.charCodeAt(text, k++);
 					if( font.charset.isSpace(cc) || cc == '\n'.code ) break;
 					var e = font.getChar(cc);
 					size += e.width + letterSpacing + e.getKerningOffset(prevChar);

+ 4 - 1
h3d/impl/GlDriver.hx

@@ -374,13 +374,14 @@ class GlDriver extends Driver {
 	function getChannels( t : Texture ) {
 		return switch( t.internalFmt ) {
 		case GL.RGBA: GL.RGBA;
+		case GL.ALPHA: GL.ALPHA;
 		default: throw "Invalid format " + t.internalFmt;
 		}
 	}
 
 	override function isSupportedFormat( fmt : h3d.mat.Data.TextureFormat ) {
 		return switch( fmt ) {
-		case RGBA: true;
+		case RGBA, ALPHA: true;
 		case RGBA32F: hasFeature(FloatTextures);
 		default: false;
 		}
@@ -394,6 +395,8 @@ class GlDriver extends Driver {
 		switch( t.format ) {
 		case RGBA:
 			// default
+		case ALPHA:
+			tt.internalFmt = GL.ALPHA;
 		case RGBA32F if( hasFeature(FloatTextures) ):
 			tt.pixelFmt = GL.FLOAT;
 		default:

+ 16 - 0
h3d/shader/WhiteAlpha.hx

@@ -0,0 +1,16 @@
+package h3d.shader;
+
+class WhiteAlpha extends hxsl.Shader {
+
+	static var SRC = {
+
+		var textureColor : Vec4;
+
+		function fragment() {
+			textureColor.rgb = vec3(1.0);
+		}
+
+	};
+
+
+}

+ 1 - 0
hxd/PixelFormat.hx

@@ -6,4 +6,5 @@ enum PixelFormat {
 	RGBA;
 	RGBA16F;
 	RGBA32F;
+	ALPHA;
 }

+ 1 - 0
hxd/Pixels.hx

@@ -336,6 +336,7 @@ class Pixels {
 
 	public static function bytesPerPixel( format : PixelFormat ) {
 		return switch( format ) {
+		case ALPHA: 1;
 		case ARGB, BGRA, RGBA: 4;
 		case RGBA16F: 8;
 		case RGBA32F: 16;

+ 4 - 2
hxd/System.hx

@@ -270,11 +270,13 @@ class System {
 	}
 
 	static function get_width() {
-		return lime.app.Application.current.window.width;
+		var win = lime.app.Application.current.window;
+		return Std.int(win.width * win.scale);
 	}
 
 	static function get_height() {
-		return lime.app.Application.current.window.height;
+		var win = lime.app.Application.current.window;
+		return Std.int(win.height * win.scale);
 	}
 
 	static function get_isAndroid() {

+ 5 - 3
hxd/impl/LimeStage.hx

@@ -27,9 +27,9 @@ class LimeStage implements lime.app.IModule {
 			hxd.System.loopFunc();
 	}
 
-	public function onWindowResize(win, w, h){
-		width = w;
-		height = h;
+	public function onWindowResize(win:lime.ui.Window, w, h){
+		width = Std.int(w * win.scale);
+		height = Std.int(h * win.scale);
 		stage.onResize(null);
 	}
 
@@ -161,6 +161,8 @@ class LimeStage implements lime.app.IModule {
 	
 	public function onWindowRestore( window ){ }
 
+	public function onWindowDropFile( window, file:String ){ }
+
 	public function update( dt ){ }
 		
 }

+ 3 - 1
hxd/res/Font.hx

@@ -11,10 +11,12 @@ class Font extends Resource {
 		#elseif js
 		var name = "R_" + ~/[^A-Za-z0-9_]/g.replace(entry.path, "_");
 		return FontBuilder.getFont(name, size, options);
+		#elseif lime
+		return FontBuilder.getFont(name, size, options);
 		#else
 		throw "Not implemented for this platform";
 		return null;
 		#end
 	}
 
-}
+}

+ 105 - 0
hxd/res/FontBuilder.hx

@@ -3,6 +3,7 @@ package hxd.res;
 typedef FontBuildOptions = {
 	?antiAliasing : Bool,
 	?chars : String,
+	?kerning : Bool,
 };
 
 /**
@@ -217,6 +218,110 @@ class FontBuilder {
 		return font;
 	}
 
+	#elseif lime
+
+	function build() : h2d.Font {
+		var f = lime.text.Font.fromBytes( hxd.Res.load(font.name).entry.getBytes() );
+		var surf = 0;
+		var bh = 0;
+		var tmp = [];
+		var gcode = new Map<lime.text.Glyph,Int>();
+		for( i in 0...haxe.Utf8.length(options.chars) ) {
+			var c = haxe.Utf8.sub(options.chars, i,1);
+			var code = haxe.Utf8.charCodeAt(options.chars, i);
+			var g = f.getGlyph(c);
+			gcode.set(g, code);
+			var img = f.renderGlyph(g,font.size);
+			var m = f.getGlyphMetrics(g);
+			if( img == null ){
+				tmp[i] = { i: null, w:0, h:0, x:0, y:0, adv:Std.int(m.advance.x)>>6 };
+				continue;
+			}
+			var w = img.width;
+			var h = img.height;
+			var x = Std.int(img.x);
+			if( x < 0 )
+				x = 0;
+			var y = Std.int(img.y); // baseline y pos
+			surf += (w + 2) * (h + 2);
+			if( h+1 > font.lineHeight )
+				font.lineHeight = h + 1;
+			if( h - y > bh )
+				bh = h - y;
+			tmp[i] = { i: img, w:w, h:h, x: x, y:y, adv:Std.int(m.advance.x)>>6 };
+		}
+		var baseline = font.lineHeight - bh;
+
+		var side = Math.ceil( Math.sqrt(surf) );
+		var width = 1;
+		while( side > width )
+			width <<= 1;
+		var height = width;
+		while( width * height >> 1 > surf )
+			height >>= 1;
+
+		var all, px;
+		do {
+			font.glyphs = new Map();
+			all = [];
+			var x = 0, y = 0, lineH = font.lineHeight;
+			px = haxe.io.Bytes.alloc( width * height  );
+			for( i in 0...haxe.Utf8.length(options.chars) ) {
+				var size = tmp[i];
+				var w = size.x + size.w + 1;
+				if( x + w > width ) {
+					x = 0;
+					y += lineH + 1;
+				}
+				// no space, resize
+				if( y + lineH + 1 > height ) {
+					px = null;
+					height <<= 1;
+					break;
+				}
+				var gy = baseline-size.y;
+				var gx = size.x;
+				if( size.w > 0 && size.h > 0 ){
+					var ib = size.i.buffer.data.toBytes();
+					for( ty in 0...size.h )
+						px.blit( (gx+x+(y+gy+ty)*width), ib, ty*size.w, size.w );
+				}
+				var t = new h2d.Tile(innerTex, x, y, gx+size.w, gy+size.h);
+				all.push(t);
+				font.glyphs.set(haxe.Utf8.charCodeAt(options.chars,i), new h2d.Font.FontChar(t,size.adv-1));
+				// next element
+				x += w + 1;
+			}
+		} while( px == null );
+
+		// Kerning
+		// lime font.decompose() currently force size to 320*64 (= 20*1024)
+		if( options.kerning ){
+			var kernratio = font.size / (320 * 64);
+			var kerning = f.decompose().kerning;
+			for( k in kerning ){
+				var v = Math.round(k.x * kernratio);
+				if( v == 0 || !gcode.exists(k.right_glyph) || !gcode.exists(k.left_glyph) )
+					continue;
+				var c = font.glyphs.get( gcode.get(k.right_glyph) );
+				c.addKerning( gcode.get(k.left_glyph), v );
+			}
+		}
+
+		var pixels = new hxd.Pixels( width, height, px, ALPHA );
+		if( innerTex == null ) {
+			innerTex = new h3d.mat.Texture(pixels.width, pixels.height, h3d.mat.Data.TextureFormat.ALPHA);
+			innerTex.uploadPixels(pixels);
+			font.tile = h2d.Tile.fromTexture(innerTex);
+			for( t in all )
+				t.setTexture(innerTex);
+			innerTex.realloc = build;
+		} else
+			innerTex.uploadPixels(pixels);
+		pixels.dispose();
+
+		return font;
+	}
 
 	#else