Compare commits

..
8 Commits
Author SHA1 Message Date
bonkmaykr 548d51a756 Encode sentinel value inside version number so user can identify this is the schrift version of the addon, without changing the available exports 2026-10-05 17:32:28 -05:00
bonkmaykr d3c6610eea oops 2026-09-22 22:24:52 -05:00
bonkmaykr 9da95a8f27 Add license 2026-09-23 00:16:37 +00:00
bonkmaykr a9c82c406d fix linking with allegro primitives, fix header name when installed, update readme 2026-09-22 19:08:40 -05:00
bonkmaykr 07395f7777 update wmax, update README.md 2026-09-22 18:43:20 -05:00
bonkmaykr 02eb8fc160 Fix glyph advance, also fixes rasterization of empty characters in the process 2026-09-22 18:07:55 -05:00
bonkmaykr 6e79035cc3 signing off. todo in commit description
todo:
fix 0-wide chars
  minimum of 1px, minimum of some other px for spaces. chars with no width cause the base allegro_font addon to fail.
new optional param in load call to specify ranges from within the game
2026-09-22 14:37:56 -05:00
bonkmaykr 5181f163e8 fix bullshit clangd error when operating on single bytes inside an unsigned int 2026-09-22 14:26:02 -05:00
8 changed files with 68 additions and 22 deletions

No files matched your search

+2 -2
View File
@@ -3,7 +3,7 @@ include_directories(../font)
set(TTF_SOURCES allegro_schrift.c schrift.c)
set(TTF_INCLUDE_FILES allegro5/allegro_schrift.h)
set(TTF_INCLUDE_FILES allegro5/allegro_ttf.h)
#set_our_header_properties(${TTF_INCLUDE_FILES})
@@ -16,7 +16,7 @@ add_our_addon_library(allegro_ttf
AllegroTTF-${ALLEGRO_SOVERSION}
"${TTF_SOURCES};${TTF_INCLUDE_FILES}"
"-DALLEGRO_TTF_SRC"
"${FONT_LINK_WITH};${TTF_LIBRARIES}"
"${FONT_LINK_WITH};${PRIMITIVES_LINK_WITH};${TTF_LIBRARIES}"
)
#target_compile_options(allegro_ttf PRIVATE "-fsanitize=undefined" "-lasan")
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Canithesis Interactive
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+17 -5
View File
@@ -3,15 +3,27 @@ Drop-in replacement for Allegro_TTF that contains libschrift, instead of using F
It is 100% API compatible with the vanilla TrueType addon. Compile Allegro with these files inside of `/addons/ttf`.
Pros:
Requires the primitives addon.
![Comparison between FreeType2 and schrift when running Allegro's ex_ttf demo](comparison.png)
## Pros
- It doesn't require NT 6 kernel calls
- It doesn't dynamically link against hundreds of thousands of lines of ugly corporate-backed C code you can't read
- Our addon is only a couple or few hundred lines, and libschrift is less than 2,000. They're compiled together.
The original Allegro_TTF is over 1,000 lines (for a good reason) and has a relatively massive dependency weight (for a stupid reason).
Caveats:
## Caveats
- Pre-stretching is not implemented.
- The entire caching system is gone, fonts are baked to textures immediately and no further. This makes supporting some languages with this add-on inconvenient, or impossible.
If your usecase doesn't need every fancy rendering feature and can use schrift, you probably aren't supporting enough characters and languages to need on-the-fly caching, so we consider this an acceptable tradeoff.
- The entire caching system is gone, fonts are baked to textures immediately and no further. This makes supporting some languages with this add-on inconvenient, and increases load times. For many users this an acceptable tradeoff.
- The `cache_text` setting in allegro5.cfg is now reused to determine what glyphs can be rendered at all. `skip_cache_misses` has no effect.
When `cache_text` is undefined, the English and Romance alphabets will be generated by default.
When `cache_text` is undefined, the [Latin](https://en.wikipedia.org/wiki/ASCII), [Germanic, and Romance](https://en.wikipedia.org/wiki/Latin_Extended-A) alphabets will be generated by default. (not necessarily 32 - 255)
- **TODO** Alternatively, the developer can force a custom range of unicode characters to be generated using a new parameter in the `al_load_ttf_font` function.
- Kerning, per-character advance and offsets, and other features which are exposed by libschrift are not currently implemented, but doing so is possible. See the above comparison screenshot.
## In Practice (WIP)
You can see here some of the flaws with this implementation. Line heights are taller than they should be. Not visible in the below example is the atlas size to hold glyph data, which is quite large by default.
The garbage the end of strings is not an issue with allegro_schrift, but a bug in the below example. It does not appear with the vanilla addon because it automatically generates an empty glyph for newlines. You may need to account for how your game handles strings.
![Time Falcon main menu with the allegro_schrift plugin, work in progress](schrift_demo_wip.png)
@@ -1,3 +1,5 @@
// this header needs to be named allegro_ttf.h so it replaces the FreeType header
#ifndef __al_included_allegro5_allegro_ttf_h
#define __al_included_allegro5_allegro_ttf_h
@@ -1 +0,0 @@
#cmakedefine ALLEGRO_CFG_TTF_FREETYPE
+26 -14
View File
@@ -4,7 +4,7 @@
#include "allegro5/internal/aintern.h"
#include "allegro5/internal/aintern_vector.h"
#include "allegro5/allegro_schrift.h"
#include "allegro5/allegro_ttf.h"
#include "allegro5/internal/aintern_font.h"
#include "allegro5/internal/aintern_dtor.h"
#include "allegro5/internal/aintern_system.h"
@@ -13,16 +13,20 @@
#include "schrift.h"
#include <stdlib.h>
#include <math.h>
#include "../primitives/allegro5/allegro_primitives.h"
ALLEGRO_DEBUG_CHANNEL("font")
#define CANI_ALLEGRO_SCHRIFT_VER 1
#define delimit_red 0
#define delimit_green 0
#define delimit_blue 255
#define delimit_alpha 255
#define delimit_red (unsigned)0 // shut up i know what i'm doing
#define delimit_green (unsigned)0
#define delimit_blue (unsigned)255
#define delimit_alpha (unsigned)255
#define delimit_color al_map_rgba(delimit_red, delimit_green, delimit_blue, delimit_alpha)
#define wmax (int32_t)2048 // fixed atlas width - 1024 or 2048 are ideal depending on font size
// height is automatically adjusted in powers of two
// todo we should expand this less when the card supports npot textures
/* globals */
static bool ttf_inited;
@@ -44,6 +48,11 @@ ALLEGRO_BITMAP *grow_bitmap(ALLEGRO_BITMAP *bmp, uint16_t add) {
ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
char const *filename, int size, int flags)
{
if (!al_is_primitives_addon_initialized() && !al_init_primitives_addon()) {
ALLEGRO_ERROR("Can't load font %s: primitives couldn't be set up\n", filename);
return NULL;
}
#define CLEANUP free(filebuf); if (gtex) al_destroy_bitmap(gtex); al_set_target_bitmap(tgt)
#define FAIL CLEANUP; return NULL
@@ -65,7 +74,8 @@ ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
al_get_config_value(system_cfg, "ttf", "cache_text");
if (!cache_text_str) {
ALLEGRO_ERROR("No characters defined in cache_text! Using defaults\n");
cache_text_str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ";
// todo probably should just store a list of ranges instead, maybe even ditch the config var entirely
cache_text_str = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:;\"'.,!?/\\|{}()<>@#$%^&*-_=+~`\u007FĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſ";
}
// read font file
@@ -88,11 +98,10 @@ ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
}
// convert glyphs into textures
#define wmax (int32_t)1024
int32_t woff = 1, hoff = 1, hmax = 128; // signed to calculate difference at texture edges
gtex = al_create_bitmap(wmax, hmax);
al_set_target_bitmap(gtex);
al_clear_to_color(delimit_color); // todo invert alpha at final pass
al_clear_to_color(delimit_color);
unsigned int i = 0;
const unsigned int len = strlen(cache_text_str);
@@ -124,7 +133,8 @@ ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
if (0 > sft_lookup(&sft, cache_text_str[i], &glyph)) goto glyph_lookup_fail;
if (0 > sft_gmetrics(&sft, glyph, &geom)) goto glyph_lookup_fail;
if ((wmax - woff) < geom.minWidth + 1) {
const unsigned int rectw = (floor(geom.advanceWidth) > geom.minWidth) ? floor(geom.advanceWidth) : geom.minWidth;
if ((wmax - woff) < rectw + 1) {
hoff += rh + 1;
woff = 1;
}
@@ -139,16 +149,18 @@ ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
img.pixels = malloc(img.width * img.height);
if (!img.pixels) goto glyph_lookup_oom;
if (0 > sft_render(&sft, glyph, img)) goto glyph_lookup_fail;
ALLEGRO_INFO("got raster\n");
ALLEGRO_INFO("got raster\n"); // i want to use ceiling, it seems more correct? but it still looks too crooked
al_draw_filled_rectangle(
woff,
hoff,
woff + geom.minWidth,
woff + rectw,
hoff + rh,
al_map_rgba(0, 0, 0, 255)
);
int padding = (int)(geom.advanceWidth - (double)geom.minWidth)/2;
if (padding < 0) padding = 0;
block =
al_lock_bitmap_region(gtex, woff, hoff + (geom.yOffset + lh), geom.minWidth, geom.minHeight,
al_lock_bitmap_region(gtex, woff + padding, hoff + (geom.yOffset + lh), geom.minWidth, geom.minHeight,
ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8, ALLEGRO_LOCK_WRITEONLY);
assert(block->pixel_size == 1);
ALLEGRO_INFO("got vram lock\n");
@@ -165,7 +177,7 @@ ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
al_unlock_bitmap(gtex);
ALLEGRO_INFO("blit raster to vram\n");
woff += geom.minWidth + 1;
woff += rectw + 1;
i++; continue;
glyph_lookup_oom:
@@ -267,7 +279,7 @@ void al_shutdown_ttf_addon(void)
uint32_t al_get_allegro_ttf_version(void)
{
return CANI_ALLEGRO_SCHRIFT_VER;
return CANI_ALLEGRO_SCHRIFT_VER & 0x000000FF | 'MKR'<<8;
}
ALLEGRO_FONT *al_load_ttf_font_stretch(char const *filename, int w, int h, int flags) {
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB