Merge branch 'develop' into 8.3.0-Dev

This commit is contained in:
Josh Tynjala
2024-11-05 13:57:08 -08:00
31 changed files with 548 additions and 247 deletions

View File

@@ -149,7 +149,7 @@ class NativeCFFI
@:cffi private static function lime_font_render_glyphs(handle:Dynamic, indices:Dynamic, data:Dynamic):Dynamic;
@:cffi private static function lime_font_set_size(handle:Dynamic, size:Int):Void;
@:cffi private static function lime_font_set_size(handle:Dynamic, size:Int, dpi:Int):Void;
@:cffi private static function lime_gamepad_add_mappings(mappings:Dynamic):Void;
@@ -439,7 +439,7 @@ class NativeCFFI
"lime_font_render_glyph", "oioo", false));
private static var lime_font_render_glyphs = new cpp.Callable<cpp.Object->cpp.Object->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime",
"lime_font_render_glyphs", "oooo", false));
private static var lime_font_set_size = new cpp.Callable<cpp.Object->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_font_set_size", "oiv", false));
private static var lime_font_set_size = new cpp.Callable<cpp.Object->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_font_set_size", "oiiv", false));
private static var lime_gamepad_add_mappings = new cpp.Callable<cpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_gamepad_add_mappings", "ov",
false));
private static var lime_gamepad_get_device_guid = new cpp.Callable<Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_gamepad_get_device_guid", "io",
@@ -672,7 +672,7 @@ class NativeCFFI
private static var lime_font_outline_decompose = CFFI.load("lime", "lime_font_outline_decompose", 2);
private static var lime_font_render_glyph = CFFI.load("lime", "lime_font_render_glyph", 3);
private static var lime_font_render_glyphs = CFFI.load("lime", "lime_font_render_glyphs", 3);
private static var lime_font_set_size = CFFI.load("lime", "lime_font_set_size", 2);
private static var lime_font_set_size = CFFI.load("lime", "lime_font_set_size", 3);
private static var lime_gamepad_add_mappings = CFFI.load("lime", "lime_gamepad_add_mappings", 1);
private static var lime_gamepad_get_device_guid = CFFI.load("lime", "lime_gamepad_get_device_guid", 1);
private static var lime_gamepad_get_device_name = CFFI.load("lime", "lime_gamepad_get_device_name", 1);
@@ -993,7 +993,7 @@ class NativeCFFI
return null;
}
@:hlNative("lime", "hl_font_set_size") private static function lime_font_set_size(handle:CFFIPointer, size:Int):Void {}
@:hlNative("lime", "hl_font_set_size") private static function lime_font_set_size(handle:CFFIPointer, size:Int, dpi:Int):Void {}
@:hlNative("lime", "hl_gamepad_add_mappings") private static function lime_gamepad_add_mappings(mappings:hl.NativeArray<String>):Void {}

View File

@@ -27,7 +27,7 @@ class LZMA
#end
#elseif js
var data = untyped #if haxe4 js.Syntax.code #else __js__ #end ("LZMA.compress")(new UInt8Array(bytes.getData()), 5);
if (data is String)
if ((data is String))
{
return Bytes.ofString(data);
}
@@ -60,7 +60,7 @@ class LZMA
#end
#elseif js
var data = untyped #if haxe4 js.Syntax.code #else __js__ #end ("LZMA.decompress")(new UInt8Array(bytes.getData()));
if (data is String)
if ((data is String))
{
return Bytes.ofString(data);
}

View File

@@ -69,7 +69,7 @@ class BackgroundWorker
public var onProgress = new Event<Dynamic->Void>();
@:noCompletion private var __runMessage:Dynamic;
#if (cpp || neko)
#if (cpp || neko || (haxe4 && hl))
@:noCompletion private var __messageQueue:Deque<Dynamic>;
@:noCompletion private var __workerThread:Thread;
#end
@@ -87,7 +87,7 @@ class BackgroundWorker
{
canceled = true;
#if (cpp || neko)
#if (cpp || neko || (haxe4 && hl))
__workerThread = null;
#end
}
@@ -102,7 +102,7 @@ class BackgroundWorker
completed = false;
__runMessage = message;
#if (cpp || neko)
#if (cpp || neko || (haxe4 && hl))
__messageQueue = new Deque<Dynamic>();
__workerThread = Thread.create(__doWork);
@@ -125,7 +125,7 @@ class BackgroundWorker
{
completed = true;
#if (cpp || neko)
#if (cpp || neko || (haxe4 && hl))
__messageQueue.add(MESSAGE_COMPLETE);
__messageQueue.add(message);
#else
@@ -143,7 +143,7 @@ class BackgroundWorker
**/
public function sendError(message:Dynamic = null):Void
{
#if (cpp || neko)
#if (cpp || neko || (haxe4 && hl))
__messageQueue.add(MESSAGE_ERROR);
__messageQueue.add(message);
#else
@@ -161,7 +161,7 @@ class BackgroundWorker
**/
public function sendProgress(message:Dynamic = null):Void
{
#if (cpp || neko)
#if (cpp || neko || (haxe4 && hl))
__messageQueue.add(message);
#else
if (!canceled)
@@ -193,7 +193,7 @@ class BackgroundWorker
@:noCompletion private function __update(deltaTime:Int):Void
{
#if (cpp || neko)
#if (cpp || neko || (haxe4 && hl))
var message = __messageQueue.pop(false);
if (message != null)

View File

@@ -191,7 +191,18 @@ class System
#if (!lime_doc_gen || sys)
/**
Attempts to exit the application. Dispatches `onExit`, and will not
exit if the event is canceled.
exit if the event is canceled. When exiting using this method, Lime will
gracefully shut down a number of subsystems, including (but not limited
to) audio, graphics, timers, and game controllers.
To properly exit a Lime application, it's best to call Lime's
`System.exit()` instead of calling Haxe's built-in `Sys.exit()`. When
targeting native platforms especially, Lime's is built on C++ libraries
that expose functions to clean up resources properly on exit. Haxe's
`Sys.exit()` exits immediately without giving Lime a chance to clean
things up. With that in mind, the proper and correct way to exit a Lime
app is by calling `lime.system.System.exit()`, and to avoid using
`Sys.exit()`.
**/
public static function exit(code:Int):Void
{

View File

@@ -425,7 +425,7 @@ class ThreadPool extends WorkOutput
{
while (!output.__jobComplete.value && (interruption = Thread.readMessage(false)) == null)
{
output.workIterations.value++;
output.workIterations.value = output.workIterations.value + 1;
event.job.doWork.dispatch(event.job.state, output);
}
}
@@ -521,7 +521,7 @@ class ThreadPool extends WorkOutput
{
do
{
workIterations.value++;
workIterations.value = workIterations.value + 1;
activeJob.doWork.dispatch(state, this);
timeElapsed = timestamp() - startTime;
}

View File

@@ -34,14 +34,47 @@ import haxe.io.Path;
@:access(lime.text.Glyph)
class Font
{
/**
* The ascender value of the font.
*/
public var ascender:Int;
/**
* The descender value of the font.
*/
public var descender:Int;
/**
* The height of the font.
*/
public var height:Int;
/**
* The name of the font.
*/
public var name(default, null):String;
/**
* The number of glyphs in the font.
*/
public var numGlyphs:Int;
public var src:Dynamic;
/**
* The underline position of the font.
*/
public var underlinePosition:Int;
/**
* The underline thickness of the font.
*/
public var underlineThickness:Int;
/**
* The units per EM of the font.
*/
public var unitsPerEM:Int;
@:noCompletion private var __fontID:String;
@@ -51,6 +84,11 @@ class Font
#end
@:noCompletion private var __init:Bool;
/**
* Creates a new instance of a Font object.
*
* @param name Optional name of the font.
*/
public function new(name:String = null)
{
if (name != null)
@@ -100,6 +138,11 @@ class Font
}
}
/**
* Decomposes the font into outline data.
*
* @return An instance of `NativeFontData` that contains decomposed font outline information.
*/
public function decompose():NativeFontData
{
#if (lime_cffi && !macro)
@@ -118,6 +161,12 @@ class Font
#end
}
/**
* Creates a Font instance from byte data.
*
* @param bytes The byte data containing the font.
* @return A `Font` instance.
*/
public static function fromBytes(bytes:Bytes):Font
{
if (bytes == null) return null;
@@ -132,6 +181,12 @@ class Font
#end
}
/**
* Creates a Font instance from a file path.
*
* @param path The file path of the font.
* @return A `Font` instance.
*/
public static function fromFile(path:String):Font
{
if (path == null) return null;
@@ -146,11 +201,23 @@ class Font
#end
}
/**
* Loads a Font from byte data asynchronously.
*
* @param bytes The byte data containing the font.
* @return A `Future` containing a `Font` instance.
*/
public static function loadFromBytes(bytes:Bytes):Future<Font>
{
return Future.withValue(fromBytes(bytes));
}
/**
* Loads a Font from a file path asynchronously.
*
* @param path The file path of the font.
* @return A `Future` containing a `Font` instance.
*/
public static function loadFromFile(path:String):Future<Font>
{
var request = new HTTPRequest<Font>();
@@ -167,6 +234,12 @@ class Font
});
}
/**
* Loads a Font by its name asynchronously.
*
* @param path The name of the font.
* @return A `Future` containing a `Font` instance.
*/
public static function loadFromName(path:String):Future<Font>
{
#if (js && html5)
@@ -177,6 +250,12 @@ class Font
#end
}
/**
* Retrieves a glyph from the font by a character.
*
* @param character The character whose glyph to retrieve.
* @return A `Glyph` instance representing the glyph of the character.
*/
public function getGlyph(character:String):Glyph
{
#if (lime_cffi && !macro)
@@ -186,6 +265,12 @@ class Font
#end
}
/**
* Retrieves an array of glyphs for a set of characters.
*
* @param characters The string containing characters to retrieve glyphs for.
* @return An array of `Glyph` instances representing the glyphs of the characters.
*/
public function getGlyphs(characters:String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^`'\"/\\&*()[]{}<>|:;_-+=?,. "):Array<Glyph>
{
#if (lime_cffi && !macro)
@@ -199,6 +284,12 @@ class Font
#end
}
/**
* Retrieves metrics for a given glyph.
*
* @param glyph The glyph whose metrics to retrieve.
* @return A `GlyphMetrics` instance containing the metrics of the glyph.
*/
public function getGlyphMetrics(glyph:Glyph):GlyphMetrics
{
#if (lime_cffi && !macro)
@@ -216,34 +307,64 @@ class Font
#end
}
/**
* Renders a specific glyph to an image.
*
* @param glyph The glyph to render.
* @param fontSize The size to render the glyph at.
* @return An `Image` instance representing the rendered glyph.
*/
public function renderGlyph(glyph:Glyph, fontSize:Int):Image
{
#if (lime_cffi && !macro)
__setSize(fontSize);
__setSize(fontSize, 96);
var bytes = Bytes.alloc(0);
// bytes.endian = (System.endianness == BIG_ENDIAN ? "bigEndian" : "littleEndian");
// Allocate an estimated buffer size - adjust if necessary
var bytes:Bytes = Bytes.alloc(0); // Allocate some reasonable initial size
var dataPosition = 0;
// Call native function to render glyph and get byte data
bytes = NativeCFFI.lime_font_render_glyph(src, glyph, bytes);
if (bytes != null && bytes.length > 0)
{
var index = bytes.getInt32(dataPosition);
dataPosition += 4;
var width = bytes.getInt32(dataPosition);
dataPosition += 4;
var height = bytes.getInt32(dataPosition);
dataPosition += 4;
var x = bytes.getInt32(dataPosition);
dataPosition += 4;
var y = bytes.getInt32(dataPosition);
var dataPosition = 0;
// Extract glyph information from the byte array
var index:Int = bytes.getInt32(dataPosition);
dataPosition += 4;
var data = bytes.sub(dataPosition, width * height);
dataPosition += (width * height);
var width:Int = bytes.getInt32(dataPosition);
dataPosition += 4;
var buffer = new ImageBuffer(new UInt8Array(data), width, height, 8);
var height:Int = bytes.getInt32(dataPosition);
dataPosition += 4;
var x:Int = bytes.getInt32(dataPosition);
dataPosition += 4;
var y:Int = bytes.getInt32(dataPosition);
dataPosition += 4;
// Check if width and height are valid before proceeding
if (width <= 0 || height <= 0)
{
return null;
}
// Extract pixel data from the byte array, accounting for 32-bit RGBA data
var pitch = width * 4; // 32-bit color data
// Create a new Bytes array to store the extracted bitmap data without padding
var dataBytes = Bytes.alloc(width * height * 4);
// Extract row by row to handle RGBA data
for (i in 0...height)
{
dataBytes.blit(i * width * 4, bytes, dataPosition + (i * pitch), width * 4);
}
// Create ImageBuffer and Image from the extracted data
var buffer = new ImageBuffer(new UInt8Array(dataBytes), width, height, 32);
var image = new Image(buffer, 0, 0, width, height);
image.x = x;
image.y = y;
@@ -254,7 +375,13 @@ class Font
return null;
}
/**
* Renders a set of glyphs to images.
*
* @param glyphs The glyphs to render.
* @param fontSize The size to render the glyphs at.
* @return A `Map` containing glyphs mapped to their corresponding images.
*/
public function renderGlyphs(glyphs:Array<Glyph>, fontSize:Int):Map<Glyph, Image>
{
#if (lime_cffi && !macro)
@@ -283,7 +410,7 @@ class Font
var glyphList = _glyphList;
#end
NativeCFFI.lime_font_set_size(src, fontSize);
__setSize(fontSize, 96);
var bytes = Bytes.alloc(0);
bytes = NativeCFFI.lime_font_render_glyphs(src, glyphList, bytes);
@@ -587,14 +714,17 @@ class Font
}
#end
@:noCompletion private function __setSize(size:Int):Void
@:noCompletion private function __setSize(size:Int, dpi:Int = 72):Void
{
#if (lime_cffi && !macro)
NativeCFFI.lime_font_set_size(src, size);
NativeCFFI.lime_font_set_size(src, size, dpi);
#end
}
}
/**
* Represents decomposed font data, containing kerning information, glyphs, and other properties.
*/
typedef NativeFontData =
{
var has_kerning:Bool;
@@ -613,6 +743,9 @@ typedef NativeFontData =
var kerning:Array<NativeKerningData>;
}
/**
* Represents data for an individual glyph, including dimensions and control points.
*/
typedef NativeGlyphData =
{
var char_code:Int;
@@ -624,6 +757,9 @@ typedef NativeGlyphData =
var points:Array<Int>;
}
/**
* Represents kerning information between two glyphs.
*/
typedef NativeKerningData =
{
var left_glyph:Int;

View File

@@ -135,6 +135,12 @@ class AIRHelper
signingOptions.push("samplePassword");
}
if (project.config.exists("air.tsa"))
{
signingOptions.push("-tsa");
signingOptions.push(project.config.getString("air.tsa"));
}
var args = ["-package"];
// TODO: Is this an old workaround fixed in newer AIR SDK?

View File

@@ -107,6 +107,14 @@ class HTML5Helper
{
suffix += "32";
}
else if( System.hostArchitecture == ARMV7)
{
suffix += "Arm";
}
else if( System.hostArchitecture == ARM64)
{
suffix += "Arm64";
}
else
{
suffix += "64";

View File

@@ -99,7 +99,7 @@ class FileDialog
if (type == null) type = FileDialogType.OPEN;
#if desktop
var worker = new ThreadPool();
var worker = new ThreadPool(#if (windows && hl) SINGLE_THREADED #end);
worker.onComplete.add(function(result)
{
@@ -224,7 +224,7 @@ class FileDialog
public function open(filter:String = null, defaultPath:String = null, title:String = null):Bool
{
#if (desktop && sys)
var worker = new ThreadPool();
var worker = new ThreadPool(#if (windows && hl) SINGLE_THREADED #end);
worker.onComplete.add(function(path:String)
{
@@ -287,7 +287,7 @@ class FileDialog
}
#if (desktop && sys)
var worker = new ThreadPool();
var worker = new ThreadPool(#if (windows && hl) SINGLE_THREADED #end);
worker.onComplete.add(function(path:String)
{