diff --git a/.vscode/launch.json b/.vscode/launch.json index 5ea80f1..f6a7815 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -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": [], diff --git a/src/renderer/renderer_metal.mm b/src/renderer/renderer_metal.mm index bc03bdf..c97fd29 100644 --- a/src/renderer/renderer_metal.mm +++ b/src/renderer/renderer_metal.mm @@ -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 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; }