Compare commits
8
Commits
f652106ec3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
548d51a756
|
||
|
|
d3c6610eea
|
||
|
|
9da95a8f27 | ||
|
|
a9c82c406d
|
||
|
|
07395f7777
|
||
|
|
02eb8fc160
|
||
|
|
6e79035cc3
|
||
|
|
5181f163e8
|
No files matched your search
+2
-2
@@ -3,7 +3,7 @@ include_directories(../font)
|
|||||||
|
|
||||||
set(TTF_SOURCES allegro_schrift.c schrift.c)
|
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})
|
#set_our_header_properties(${TTF_INCLUDE_FILES})
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ add_our_addon_library(allegro_ttf
|
|||||||
AllegroTTF-${ALLEGRO_SOVERSION}
|
AllegroTTF-${ALLEGRO_SOVERSION}
|
||||||
"${TTF_SOURCES};${TTF_INCLUDE_FILES}"
|
"${TTF_SOURCES};${TTF_INCLUDE_FILES}"
|
||||||
"-DALLEGRO_TTF_SRC"
|
"-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")
|
#target_compile_options(allegro_ttf PRIVATE "-fsanitize=undefined" "-lasan")
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -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`.
|
It is 100% API compatible with the vanilla TrueType addon. Compile Allegro with these files inside of `/addons/ttf`.
|
||||||
|
|
||||||
Pros:
|
Requires the primitives addon.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Pros
|
||||||
- It doesn't require NT 6 kernel calls
|
- 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
|
- 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.
|
- 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).
|
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.
|
- 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.
|
- 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.
|
||||||
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 `cache_text` setting in allegro5.cfg is now reused to determine what glyphs can be rendered at all. `skip_cache_misses` has no effect.
|
- 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.
|
||||||
|
|
||||||
|

|
||||||
@@ -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
|
#ifndef __al_included_allegro5_allegro_ttf_h
|
||||||
#define __al_included_allegro5_allegro_ttf_h
|
#define __al_included_allegro5_allegro_ttf_h
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
#cmakedefine ALLEGRO_CFG_TTF_FREETYPE
|
|
||||||
+26
-14
@@ -4,7 +4,7 @@
|
|||||||
#include "allegro5/internal/aintern.h"
|
#include "allegro5/internal/aintern.h"
|
||||||
#include "allegro5/internal/aintern_vector.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_font.h"
|
||||||
#include "allegro5/internal/aintern_dtor.h"
|
#include "allegro5/internal/aintern_dtor.h"
|
||||||
#include "allegro5/internal/aintern_system.h"
|
#include "allegro5/internal/aintern_system.h"
|
||||||
@@ -13,16 +13,20 @@
|
|||||||
#include "schrift.h"
|
#include "schrift.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "../primitives/allegro5/allegro_primitives.h"
|
#include "../primitives/allegro5/allegro_primitives.h"
|
||||||
|
|
||||||
ALLEGRO_DEBUG_CHANNEL("font")
|
ALLEGRO_DEBUG_CHANNEL("font")
|
||||||
#define CANI_ALLEGRO_SCHRIFT_VER 1
|
#define CANI_ALLEGRO_SCHRIFT_VER 1
|
||||||
#define delimit_red 0
|
#define delimit_red (unsigned)0 // shut up i know what i'm doing
|
||||||
#define delimit_green 0
|
#define delimit_green (unsigned)0
|
||||||
#define delimit_blue 255
|
#define delimit_blue (unsigned)255
|
||||||
#define delimit_alpha 255
|
#define delimit_alpha (unsigned)255
|
||||||
#define delimit_color al_map_rgba(delimit_red, delimit_green, delimit_blue, delimit_alpha)
|
#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 */
|
/* globals */
|
||||||
static bool ttf_inited;
|
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,
|
ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
|
||||||
char const *filename, int size, int flags)
|
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 CLEANUP free(filebuf); if (gtex) al_destroy_bitmap(gtex); al_set_target_bitmap(tgt)
|
||||||
#define FAIL CLEANUP; return NULL
|
#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");
|
al_get_config_value(system_cfg, "ttf", "cache_text");
|
||||||
if (!cache_text_str) {
|
if (!cache_text_str) {
|
||||||
ALLEGRO_ERROR("No characters defined in cache_text! Using defaults\n");
|
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
|
// read font file
|
||||||
@@ -88,11 +98,10 @@ ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convert glyphs into textures
|
// convert glyphs into textures
|
||||||
#define wmax (int32_t)1024
|
|
||||||
int32_t woff = 1, hoff = 1, hmax = 128; // signed to calculate difference at texture edges
|
int32_t woff = 1, hoff = 1, hmax = 128; // signed to calculate difference at texture edges
|
||||||
gtex = al_create_bitmap(wmax, hmax);
|
gtex = al_create_bitmap(wmax, hmax);
|
||||||
al_set_target_bitmap(gtex);
|
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;
|
unsigned int i = 0;
|
||||||
const unsigned int len = strlen(cache_text_str);
|
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_lookup(&sft, cache_text_str[i], &glyph)) goto glyph_lookup_fail;
|
||||||
if (0 > sft_gmetrics(&sft, glyph, &geom)) 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;
|
hoff += rh + 1;
|
||||||
woff = 1;
|
woff = 1;
|
||||||
}
|
}
|
||||||
@@ -139,16 +149,18 @@ ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
|
|||||||
img.pixels = malloc(img.width * img.height);
|
img.pixels = malloc(img.width * img.height);
|
||||||
if (!img.pixels) goto glyph_lookup_oom;
|
if (!img.pixels) goto glyph_lookup_oom;
|
||||||
if (0 > sft_render(&sft, glyph, img)) goto glyph_lookup_fail;
|
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(
|
al_draw_filled_rectangle(
|
||||||
woff,
|
woff,
|
||||||
hoff,
|
hoff,
|
||||||
woff + geom.minWidth,
|
woff + rectw,
|
||||||
hoff + rh,
|
hoff + rh,
|
||||||
al_map_rgba(0, 0, 0, 255)
|
al_map_rgba(0, 0, 0, 255)
|
||||||
);
|
);
|
||||||
|
int padding = (int)(geom.advanceWidth - (double)geom.minWidth)/2;
|
||||||
|
if (padding < 0) padding = 0;
|
||||||
block =
|
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);
|
ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8, ALLEGRO_LOCK_WRITEONLY);
|
||||||
assert(block->pixel_size == 1);
|
assert(block->pixel_size == 1);
|
||||||
ALLEGRO_INFO("got vram lock\n");
|
ALLEGRO_INFO("got vram lock\n");
|
||||||
@@ -165,7 +177,7 @@ ALLEGRO_FONT *al_load_ttf_font_f(ALLEGRO_FILE *file,
|
|||||||
al_unlock_bitmap(gtex);
|
al_unlock_bitmap(gtex);
|
||||||
ALLEGRO_INFO("blit raster to vram\n");
|
ALLEGRO_INFO("blit raster to vram\n");
|
||||||
|
|
||||||
woff += geom.minWidth + 1;
|
woff += rectw + 1;
|
||||||
i++; continue;
|
i++; continue;
|
||||||
|
|
||||||
glyph_lookup_oom:
|
glyph_lookup_oom:
|
||||||
@@ -267,7 +279,7 @@ void al_shutdown_ttf_addon(void)
|
|||||||
|
|
||||||
uint32_t al_get_allegro_ttf_version(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) {
|
ALLEGRO_FONT *al_load_ttf_font_stretch(char const *filename, int w, int h, int flags) {
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
Reference in new issue
Block a user