fix macos renderer

This commit is contained in:
2026-03-03 10:17:20 -05:00
parent ad30ca8cb7
commit 9bf5131d27
2 changed files with 15 additions and 18 deletions

2
.vscode/launch.json vendored
View File

@@ -3,7 +3,7 @@
"configurations": [
{
"name": "Debug autosample (macOS)",
"type": "lldb",
"type": "lldb-dap",
"request": "launch",
"program": "${workspaceFolder}/build_debug/autosample.app/Contents/MacOS/autosample",
"args": [],

View File

@@ -203,6 +203,14 @@ static bool create_font_atlas(Renderer *r, F32 font_size) {
// White text
CGContextSetGrayFillColor(ctx, 1.0, 1.0);
// Flip CG context so (0,0) is top-left, matching our pen_y convention
CGContextTranslateCTM(ctx, 0, render_h);
CGContextScaleCTM(ctx, 1.0, -1.0);
// In the flipped context, Core Text draws upside down unless we undo the
// text matrix flip. Set the text matrix to flip Y back for glyph rendering.
CGContextSetTextMatrix(ctx, CGAffineTransformMake(1, 0, 0, -1, 0, 0));
// Render each glyph
int pen_x = SS, pen_y = SS;
int row_height = 0;
@@ -230,9 +238,10 @@ static bool create_font_atlas(Renderer *r, F32 font_size) {
if (pen_y + gh >= render_h) { CFRelease(line); break; }
// CoreGraphics has bottom-left origin; draw relative to pen position
// Context is flipped to top-left origin. Position baseline:
// pen_y + SS is the top of the glyph cell, baseline is ascent below that.
F32 draw_x = (F32)(pen_x + SS) - (F32)bounds.origin.x;
F32 draw_y = (F32)(render_h - pen_y - SS) - ascent;
F32 draw_y = (F32)(pen_y + SS) + ascent;
CGContextSetTextPosition(ctx, draw_x, draw_y);
CTLineDraw(line, ctx);
@@ -252,18 +261,16 @@ static bool create_font_atlas(Renderer *r, F32 font_size) {
CFRelease(line);
}
// Box-filter downsample
// Box-filter downsample (context is flipped, so bitmap is already top-down)
uint8_t *src = (uint8_t *)CGBitmapContextGetData(ctx);
uint8_t *atlas_data = (uint8_t *)malloc(FONT_ATLAS_W * FONT_ATLAS_H);
// CoreGraphics bitmap has bottom-left origin — flip Y during downsample
for (int y = 0; y < FONT_ATLAS_H; y++) {
for (int x = 0; x < FONT_ATLAS_W; x++) {
int sum = 0;
for (int sy = 0; sy < SS; sy++) {
for (int sx = 0; sx < SS; sx++) {
int src_y = render_h - 1 - (y * SS + sy); // flip Y
int src_idx = src_y * render_w + (x * SS + sx);
int src_idx = (y * SS + sy) * render_w + (x * SS + sx);
sum += src[src_idx];
}
}
@@ -620,17 +627,7 @@ void renderer_destroy(Renderer *r) {
}
bool renderer_begin_frame(Renderer *r) {
dispatch_semaphore_wait(r->frame_semaphore, DISPATCH_TIME_FOREVER);
id<CAMetalDrawable> drawable = [r->metal_layer nextDrawable];
if (!drawable) {
dispatch_semaphore_signal(r->frame_semaphore);
return false;
}
// Store drawable for end_frame (use a thread-local or just re-acquire)
// We'll re-acquire in end_frame — nextDrawable is fast if we just called it
dispatch_semaphore_signal(r->frame_semaphore);
if (r->width <= 0 || r->height <= 0) return false;
return true;
}