Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ add_library(xwa_remaster STATIC
src/xwa_remaster/original_2d.c
src/xwa_remaster/sky_stars.c
src/xwa_remaster/assets.c
src/xwa_remaster/frontend_font_aa.c
src/xwa_remaster/text.c
)
if(XWA_ENABLE_DEBUG_UI)
Expand Down
16 changes: 10 additions & 6 deletions src/xwa_remaster/assets.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include "xwa_remaster/assets.h"
#include "xwa_remaster/frontend_font_aa.h"

#include "aeron/aeron.h"
#include "aeron/image.h"
Expand Down Expand Up @@ -908,7 +909,7 @@ static AeronFontGlyph* assets_copy_font_glyphs(const Xwa2dFontAtlas* source, int
}

static int assets_init_original_font(AeronCommandBuffer* cmd,
const Xwa2dFontAtlas* font, int atlas_scale, int generate_mips,
const Xwa2dFontAtlas* font, int atlas_scale, int generate_mips, int frontend_aa,
const char* debug_name, AeronFontAtlas* out) {
if (!cmd || !font || !out || atlas_scale <= 0 || font->cell_width <= 0 ||
font->cell_height <= 0 || font->baseline < 0 ||
Expand All @@ -918,9 +919,12 @@ static int assets_init_original_font(AeronCommandBuffer* cmd,
return 0;
AeronFontGlyph* glyphs = assets_copy_font_glyphs(font, atlas_scale);
int atlas_width = 0, atlas_height = 0;
uint8_t* atlas_rgba = glyphs ? Aeron_ImageUpscaleNearestRgba8(font->rgba, font->width, font->height,
atlas_scale, &atlas_width, &atlas_height)
: NULL;
uint8_t* atlas_rgba = glyphs ? (frontend_aa
? XwaFrontendFontAA_Upscale(font->rgba, font->width, font->height,
atlas_scale, &atlas_width, &atlas_height)
: Aeron_ImageUpscaleNearestRgba8(font->rgba, font->width, font->height,
atlas_scale, &atlas_width, &atlas_height))
: NULL;
const int initialized = atlas_rgba && AeronFontAtlas_InitRgba8(
out, cmd,
&(AeronFontAtlasRgba8Desc) {
Expand Down Expand Up @@ -965,7 +969,7 @@ static AssetLoadStatus assets_load_original_flight_font(XwaRemasterAssets* a, Ae
return ASSET_LOAD_FAILED;
}
Xwa2dFrameSet_Free(&group);
if (!assets_init_original_font(cmd, &font, XWA_ORIGINAL_FONT_SCALE, 1,
if (!assets_init_original_font(cmd, &font, XWA_ORIGINAL_FONT_SCALE, 1, 0,
"XWA original flight font", &slot->atlas)) {
Xwa2dFontAtlas_Free(&font);
return ASSET_LOAD_FAILED;
Expand Down Expand Up @@ -1068,7 +1072,7 @@ static AssetLoadStatus assets_load_original_frontend_font(XwaRemasterAssets* a,
Aeron_LogWarn("xwa.remaster", "frontend font %d: original load failed: %s", font_size, error);
return status;
}
if (!assets_init_original_font(cmd, &font, XWA_ORIGINAL_FONT_SCALE, 0,
if (!assets_init_original_font(cmd, &font, XWA_ORIGINAL_FONT_SCALE, 0, 1,
"XWA original frontend font", &slot->atlas)) {
Xwa2dFontAtlas_Free(&font);
return ASSET_LOAD_FAILED;
Expand Down
61 changes: 61 additions & 0 deletions src/xwa_remaster/frontend_font_aa.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "xwa_remaster/frontend_font_aa.h"

#include <math.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

/* Mitchell-Netravali (B=C=1/3) reconstructs the 4x enlarged original glyph
* coverage without nearest-neighbour's flat pixel steps. The original ABP
* decoder packs glyphs with gutters; neighbouring shapes cannot bleed into
* one another over this 2-original-pixel support radius. */
static float aa_kernel(float x) {
x = fabsf(x);
if (x < 1.0f)
return ((7.0f*x - 12.0f)*x*x + (16.0f / 3.0f)) / 6.0f;
if (x < 2.0f)
return (((-7.0f / 3.0f)*x + 12.0f)*x*x - 20.0f*x + (32.0f/3.0f)) / 6.0f;
return 0.0f;
}

uint8_t* XwaFrontendFontAA_Upscale(const uint8_t* rgba, int width, int height,
int scale, int* out_width, int* out_height) {
if (!rgba || !out_width || !out_height || width < 1 || height < 1 ||
scale < 1 || width > INT32_MAX / scale || height > INT32_MAX / scale)
return NULL;
const int w = width * scale, h = height * scale;
if ((size_t)w > SIZE_MAX / (size_t)h / 4u)
return NULL;
uint8_t* out = (uint8_t*)malloc((size_t)w * (size_t)h * 4u);
if (!out) return NULL;
for (int y = 0; y < h; ++y) {
const float sy = ((float)y + 0.5f) / (float)scale - 0.5f;
const int cy = (int)floorf(sy);
float wy[4];
for (int j = 0; j < 4; ++j)
wy[j] = aa_kernel(sy - (float)(cy + j - 1));
for (int x = 0; x < w; ++x) {
const float sx = ((float)x + 0.5f) / (float)scale - 0.5f;
const int cx = (int)floorf(sx);
float weighted_alpha = 0.0f;
for (int j = 0; j < 4; ++j) {
const int yy = cy + j - 1;
if (yy < 0 || yy >= height) continue;
for (int i = 0; i < 4; ++i) {
const int xx = cx + i - 1;
if (xx < 0 || xx >= width) continue;
weighted_alpha += wy[j] * aa_kernel(sx - (float)xx) *
(float)rgba[((size_t)yy * (size_t)width + (size_t)xx) * 4u + 3u];
}
}
if (weighted_alpha < 0.0f) weighted_alpha = 0.0f;
if (weighted_alpha > 255.0f) weighted_alpha = 255.0f;
uint8_t* pixel = out + ((size_t)y * (size_t)w + (size_t)x) * 4u;
pixel[0] = pixel[1] = pixel[2] = 255u;
pixel[3] = (uint8_t)(weighted_alpha + 0.5f);
}
}
*out_width = w;
*out_height = h;
return out;
}
12 changes: 12 additions & 0 deletions src/xwa_remaster/frontend_font_aa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef XWA_FRONTEND_FONT_AA_H
#define XWA_FRONTEND_FONT_AA_H

#include <stdint.h>

/* High-quality 4x reconstruction of decoded *frontend* ABP glyph coverage.
* Returns straight-alpha white ink. The atlas loader premultiplies it once.
* Caller owns the result; flight HUD fonts never use this function. */
uint8_t* XwaFrontendFontAA_Upscale(const uint8_t* rgba, int width, int height,
int scale, int* out_width, int* out_height);

#endif