mini-arcade-native-backend 0.4.3__tar.gz → 0.4.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/CHANGELOG.md +16 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/PKG-INFO +1 -1
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/cpp/bindings.cpp +7 -1
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/cpp/engine.cpp +24 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/cpp/engine.h +5 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/pyproject.toml +1 -1
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/src/mini_arcade_native_backend/__init__.py +44 -5
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/.github/workflows/ci.yml +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/.github/workflows/create-release-branch.yml +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/.github/workflows/release-finalize.yml +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/.github/workflows/release-publish.yml +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/.gitignore +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/.vscode/settings.json +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/CMakeLists.txt +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/LICENSE +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/README.md +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/examples/native_backend_demo.py +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/poetry.lock +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/poetry.toml +0 -0
- {mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/tests/test_init.py +0 -0
|
@@ -6,6 +6,22 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.4.5] - 2025-12-16
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- implement font caching and update draw_text and measure_text methods to support dynamic font sizes
|
|
13
|
+
|
|
14
|
+
## [0.4.4] - 2025-12-16
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- add measure_text method to Engine and expose it in NativeBackend
|
|
18
|
+
- add alpha handling methods and refactor color extraction in NativeBackend
|
|
19
|
+
- update draw_rect and draw_text methods to support alpha channel in color
|
|
20
|
+
|
|
21
|
+
### Other
|
|
22
|
+
- Merge branch 'release/0.4' of https://github.com/alexsc6955/mini-arcade-native-backend into release/0.4
|
|
23
|
+
- Merge branch 'release/0.4' of https://github.com/alexsc6955/mini-arcade-native-backend into release/0.4
|
|
24
|
+
|
|
9
25
|
## [0.4.3] - 2025-12-16
|
|
10
26
|
|
|
11
27
|
### Added
|
|
@@ -79,5 +79,11 @@ PYBIND11_MODULE(_native, m) {
|
|
|
79
79
|
.def("poll_events", &mini::Engine::poll_events)
|
|
80
80
|
|
|
81
81
|
.def("capture_frame", &mini::Engine::capture_frame,
|
|
82
|
-
py::arg("path"))
|
|
82
|
+
py::arg("path"))
|
|
83
|
+
.def(
|
|
84
|
+
"measure_text",
|
|
85
|
+
&mini::Engine::measure_text,
|
|
86
|
+
py::arg("text"),
|
|
87
|
+
py::arg("font_id") = -1
|
|
88
|
+
);
|
|
83
89
|
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
#include <stdexcept>
|
|
4
4
|
#include <iostream>
|
|
5
|
+
#include <utility>
|
|
6
|
+
#include <cstring>
|
|
5
7
|
|
|
6
8
|
namespace mini {
|
|
7
9
|
|
|
@@ -381,4 +383,26 @@ namespace mini {
|
|
|
381
383
|
return events;
|
|
382
384
|
}
|
|
383
385
|
|
|
386
|
+
std::pair<int, int> Engine::measure_text(const char* text, int font_id)
|
|
387
|
+
{
|
|
388
|
+
if (!initialized_) return {0, 0};
|
|
389
|
+
|
|
390
|
+
int idx = (font_id >= 0) ? font_id : default_font_id_;
|
|
391
|
+
if (idx < 0 || idx >= (int)fonts_.size() || fonts_[idx] == nullptr) return {0, 0};
|
|
392
|
+
|
|
393
|
+
if (text == nullptr || text[0] == '\0') return {0, 0};
|
|
394
|
+
|
|
395
|
+
int w = 0;
|
|
396
|
+
int h = 0;
|
|
397
|
+
|
|
398
|
+
// TTF_SizeUTF8 returns 0 on success, -1 on error
|
|
399
|
+
if (TTF_SizeUTF8(fonts_[idx], text, &w, &h) != 0) {
|
|
400
|
+
// Optional: log error
|
|
401
|
+
// std::cerr << "TTF_SizeUTF8 Error: " << TTF_GetError() << std::endl;
|
|
402
|
+
return {0, 0};
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return {w, h};
|
|
406
|
+
}
|
|
407
|
+
|
|
384
408
|
} // namespace mini
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <SDL_ttf.h>
|
|
5
5
|
#include <vector>
|
|
6
6
|
#include <string>
|
|
7
|
+
#include <utility>
|
|
7
8
|
|
|
8
9
|
// A minimal 2D graphics engine binding for Python using SDL.
|
|
9
10
|
namespace mini {
|
|
@@ -89,6 +90,10 @@ namespace mini {
|
|
|
89
90
|
// Returns true on success, false on failure.
|
|
90
91
|
bool capture_frame(const char* path);
|
|
91
92
|
|
|
93
|
+
// Measure text (UTF-8) using a loaded font.
|
|
94
|
+
// Returns (width, height) in pixels. Returns (0,0) if no valid font or error.
|
|
95
|
+
std::pair<int, int> measure_text(const char* text, int font_id = -1);
|
|
96
|
+
|
|
92
97
|
private:
|
|
93
98
|
SDL_Window* window_; // The main application window.
|
|
94
99
|
SDL_Renderer* renderer_; // The renderer for drawing.
|
|
@@ -8,7 +8,7 @@ build-backend = "scikit_build_core.build"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "mini-arcade-native-backend"
|
|
11
|
-
version = "0.4.
|
|
11
|
+
version = "0.4.5"
|
|
12
12
|
description = "Native SDL2 backend for mini-arcade-core using SDL2 + pybind11."
|
|
13
13
|
authors = [
|
|
14
14
|
{ name = "Santiago Rincon", email = "rincores@gmail.com" },
|
|
@@ -80,6 +80,33 @@ class NativeBackend(Backend):
|
|
|
80
80
|
self._font_path = font_path
|
|
81
81
|
self._font_size = font_size
|
|
82
82
|
self._default_font_id: int | None = None
|
|
83
|
+
self._fonts_by_size: dict[int, int] = {}
|
|
84
|
+
|
|
85
|
+
def _get_font_id(self, font_size: int | None) -> int:
|
|
86
|
+
# No font loaded -> keep current “no-op” behavior
|
|
87
|
+
if self._font_path is None:
|
|
88
|
+
return -1
|
|
89
|
+
|
|
90
|
+
# Default font
|
|
91
|
+
if font_size is None:
|
|
92
|
+
return (
|
|
93
|
+
self._default_font_id
|
|
94
|
+
if self._default_font_id is not None
|
|
95
|
+
else -1
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
if font_size <= 0:
|
|
99
|
+
raise ValueError(f"font_size must be > 0, got {font_size}")
|
|
100
|
+
|
|
101
|
+
# Cached
|
|
102
|
+
cached = self._fonts_by_size.get(font_size)
|
|
103
|
+
if cached is not None:
|
|
104
|
+
return cached
|
|
105
|
+
|
|
106
|
+
# Lazily load and cache
|
|
107
|
+
font_id = self._engine.load_font(self._font_path, int(font_size))
|
|
108
|
+
self._fonts_by_size[font_size] = font_id
|
|
109
|
+
return font_id
|
|
83
110
|
|
|
84
111
|
def init(self, width: int, height: int, title: str):
|
|
85
112
|
"""
|
|
@@ -101,6 +128,7 @@ class NativeBackend(Backend):
|
|
|
101
128
|
self._default_font_id = self._engine.load_font(
|
|
102
129
|
self._font_path, self._font_size
|
|
103
130
|
)
|
|
131
|
+
self._fonts_by_size[self._font_size] = self._default_font_id
|
|
104
132
|
|
|
105
133
|
def set_clear_color(self, r: int, g: int, b: int):
|
|
106
134
|
"""
|
|
@@ -277,14 +305,13 @@ class NativeBackend(Backend):
|
|
|
277
305
|
r, g, b, a = self._get_color_values(color)
|
|
278
306
|
self._engine.draw_rect(x, y, w, h, r, g, b, a)
|
|
279
307
|
|
|
280
|
-
# pylint: enable=too-many-arguments,too-many-positional-arguments
|
|
281
|
-
|
|
282
308
|
def draw_text(
|
|
283
309
|
self,
|
|
284
310
|
x: int,
|
|
285
311
|
y: int,
|
|
286
312
|
text: str,
|
|
287
313
|
color: tuple[int, int, int] = (255, 255, 255),
|
|
314
|
+
font_size: int | None = None,
|
|
288
315
|
):
|
|
289
316
|
"""
|
|
290
317
|
Draw text at the given position using the loaded font.
|
|
@@ -303,13 +330,13 @@ class NativeBackend(Backend):
|
|
|
303
330
|
:type color: tuple[int, int, int]
|
|
304
331
|
"""
|
|
305
332
|
r, g, b, a = self._get_color_values(color)
|
|
306
|
-
font_id = (
|
|
307
|
-
self._default_font_id if self._default_font_id is not None else -1
|
|
308
|
-
)
|
|
333
|
+
font_id = self._get_font_id(font_size)
|
|
309
334
|
self._engine.draw_text(
|
|
310
335
|
text, x, y, int(r), int(g), int(b), int(a), font_id
|
|
311
336
|
)
|
|
312
337
|
|
|
338
|
+
# pylint: enable=too-many-arguments,too-many-positional-arguments
|
|
339
|
+
|
|
313
340
|
def capture_frame(self, path: str | None = None) -> bool:
|
|
314
341
|
"""
|
|
315
342
|
Capture the current frame.
|
|
@@ -324,3 +351,15 @@ class NativeBackend(Backend):
|
|
|
324
351
|
if path is None:
|
|
325
352
|
raise ValueError("Path must be provided to capture frame.")
|
|
326
353
|
return self._engine.capture_frame(path)
|
|
354
|
+
|
|
355
|
+
def measure_text(
|
|
356
|
+
self, text: str, font_size: int | None = None
|
|
357
|
+
) -> tuple[int, int]:
|
|
358
|
+
"""
|
|
359
|
+
Measure text size (width, height) in pixels for the active font.
|
|
360
|
+
|
|
361
|
+
Returns (0,0) if no font is loaded (matches draw_text no-op behavior).
|
|
362
|
+
"""
|
|
363
|
+
font_id = self._get_font_id(font_size)
|
|
364
|
+
w, h = self._engine.measure_text(text, font_id)
|
|
365
|
+
return int(w), int(h)
|
{mini_arcade_native_backend-0.4.3 → mini_arcade_native_backend-0.4.5}/.github/workflows/ci.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|