diff --git a/src/base/base_math.c b/src/base/base_math.c index c9db9954..c7d2ee89 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -1020,11 +1020,6 @@ Vec2 RoundVec2(Vec2 a) return VEC2(RoundF32(a.x), RoundF32(a.y)); } -Vec2I32 RoundVec2ToVec2I32(Vec2 a) -{ - return VEC2I32(RoundF32ToI32(a.x), RoundF32ToI32(a.y)); -} - Vec2 FloorVec2(Vec2 a) { return VEC2(FloorF32(a.x), FloorF32(a.y)); @@ -1035,6 +1030,21 @@ Vec2 CeilVec2(Vec2 a) return VEC2(CeilF32(a.x), CeilF32(a.y)); } +Vec2I32 RoundVec2ToI32(Vec2 a) +{ + return VEC2I32(RoundF32ToI32(a.x), RoundF32ToI32(a.y)); +} + +Vec2I32 FloorVec2ToI32(Vec2 a) +{ + return VEC2I32(FloorF32ToI32(a.x), FloorF32ToI32(a.y)); +} + +Vec2I32 CeilVec2ToI32(Vec2 a) +{ + return VEC2I32(CeilF32ToI32(a.x), CeilF32ToI32(a.y)); +} + //- Angle /* Returns 1 if winding between vectors a & b is clockwise or straight, -1 if counter-clockwise */ @@ -1184,16 +1194,16 @@ Rng2 UnionRng2(Rng2 a, Rng2 b) Rng2 AddRng2Vec2(Rng2 r, Vec2 v) { Rng2 result = ZI; - result.p0 = AddVec2(result.p0, v); - result.p1 = AddVec2(result.p1, v); + result.p0 = AddVec2(r.p0, v); + result.p1 = AddVec2(r.p1, v); return result; } Rng2 DivRng2Vec2(Rng2 r, Vec2 v) { Rng2 result = ZI; - result.p0 = DivVec2Vec2(result.p0, v); - result.p1 = DivVec2Vec2(result.p1, v); + result.p0 = DivVec2Vec2(r.p0, v); + result.p1 = DivVec2Vec2(r.p1, v); return result; } @@ -1220,16 +1230,16 @@ Rng2I32 UnionRng2I32(Rng2I32 a, Rng2I32 b) Rng2I32 AddRng2I32Vec2I32(Rng2I32 r, Vec2I32 v) { Rng2I32 result = ZI; - result.p0 = AddVec2I32(result.p0, v); - result.p1 = AddVec2I32(result.p1, v); + result.p0 = AddVec2I32(r.p0, v); + result.p1 = AddVec2I32(r.p1, v); return result; } Rng2I32 DivRng2I32Vec2I32(Rng2I32 r, Vec2I32 v) { Rng2I32 result = ZI; - result.p0 = DivVec2I32Vec2I32(result.p0, v); - result.p1 = DivVec2I32Vec2I32(result.p1, v); + result.p0 = DivVec2I32Vec2I32(r.p0, v); + result.p1 = DivVec2I32Vec2I32(r.p1, v); return result; } diff --git a/src/base/base_math.h b/src/base/base_math.h index 56510d19..201ba97c 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -349,9 +349,11 @@ Vec2 PerpVec2TowardsDir(Vec2 v, Vec2 dir); //- Round / floor / ceil Vec2 RoundVec2(Vec2 a); -Vec2I32 RoundVec2ToVec2I32(Vec2 a); Vec2 FloorVec2(Vec2 a); Vec2 CeilVec2(Vec2 a); +Vec2I32 RoundVec2ToI32(Vec2 a); +Vec2I32 FloorVec2ToI32(Vec2 a); +Vec2I32 CeilVec2ToI32(Vec2 a); //- Angle i32 WindingFromVec2(Vec2 a, Vec2 b); diff --git a/src/config.h b/src/config.h index 960b7842..6329442a 100644 --- a/src/config.h +++ b/src/config.h @@ -69,8 +69,8 @@ #define FLOOD_DEBUG 0 -#define GPU_DEBUG 1 -#define GPU_DEBUG_VALIDATION 1 +#define GPU_DEBUG 0 +#define GPU_DEBUG_VALIDATION 0 #define GPU_SHADER_PRINT 1 #define GPU_SHADER_PRINT_BUFFER_SIZE Kibi(64); diff --git a/src/glyph_cache/glyph_cache.c b/src/glyph_cache/glyph_cache.c index a1705927..c89c0eb9 100644 --- a/src/glyph_cache/glyph_cache.c +++ b/src/glyph_cache/glyph_cache.c @@ -172,8 +172,8 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size GC_RunRect *rect = &result.rects[glyph_idx]; rect->tex = glyph->tex_ref; - rect->tex_uv = glyph->tex_uv; - rect->tex_rect = glyph->tex_rect; + rect->tex_slice = glyph->tex_slice; + rect->tex_slice_uv = glyph->tex_slice_uv; rect->baseline_pos = baseline_pos; rect->advance = glyph->advance; @@ -202,7 +202,7 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size result.font_cap = glyph->font_cap; } - result.ready = uncached_codepoints_count == 0 && pending_glyphs_count; + result.ready = uncached_codepoints_count == 0 && pending_glyphs_count == 0; EndScratch(scratch); return result; @@ -251,17 +251,22 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick) { /* TODO: Remove this */ /* Create atlas */ - Vec2I32 atlas_size = VEC2I32(8192, 8192); + Vec2I32 atlas_dims = VEC2I32(1024, 1024); if (G_IsResourceNil(GC.atlas)) { - G_ArenaHandle gpu_arena = G_PermArena(); + G_ArenaHandle gpu_perm = G_PermArena(); GC.atlas = G_PushTexture2D( - gpu_arena, + gpu_perm, G_Format_R8G8B8A8_Unorm_Srgb, - atlas_size, + atlas_dims, /* FIXME: We may need simultaneous access? */ - G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present, + // G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present, + + + G_Layout_Simultaneous, + .flags = G_ResourceFlag_HostMemory, ); + GC.atlas_ref = G_PushTexture2DRef(gpu_perm, GC.atlas); } for (u64 cmd_idx = 0; cmd_idx < async->cmds.count; ++cmd_idx) @@ -275,52 +280,51 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick) GC_GlyphDesc desc = glyph->desc; - TTF_GlyphDesc ttf_desc = TTF_GlyphDescFromCodepoint(desc.codepoint, resource, desc.font_size); - glyph->font_size = ttf_desc.font_size; - glyph->font_ascent = ttf_desc.font_ascent; - glyph->font_descent = ttf_desc.font_descent; - glyph->font_cap = ttf_desc.font_cap; + TTF_GlyphResult ttf_info = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size); + glyph->font_size = desc.font_size; + glyph->font_ascent = ttf_info.font_ascent; + glyph->font_descent = ttf_info.font_descent; + glyph->font_cap = ttf_info.font_cap; + glyph->advance = ttf_info.advance; + glyph->bounds = ttf_info.bounds; + + + + u32 *image_pixels = ttf_info.image_pixels; + Vec2I32 image_dims = ttf_info.image_dims; + - glyph->advance = ttf_desc.advance; - glyph->bounds = ttf_desc.bounds; - Vec2 dims = DimsFromRng2(glyph->bounds); Vec2I32 atlas_offset = GC.atlas_pos; - GC.atlas_row_height = MaxI32(GC.atlas_row_height, dims.y); - if (atlas_offset.x + dims.x > atlas_size.x); + GC.atlas_row_height = MaxI32(GC.atlas_row_height, image_dims.y); + if (atlas_offset.x + image_dims.x > atlas_dims.x); { GC.atlas_pos.x = 0; GC.atlas_pos.y += GC.atlas_row_height; - GC.atlas_row_height = dims.y; + GC.atlas_row_height = image_dims.y; } - GC.atlas_pos.x += dims.x; + GC.atlas_pos.x += image_dims.x; - Rng2I32 src_slice = ZI; - src_slice.p0.x = 0; - src_slice.p0.y = 0; - src_slice.p1.x = RoundF32ToI32(dims.x); - src_slice.p1.y = RoundF32ToI32(dims.y); + /* Atlas info */ + glyph->tex_ref = GC.atlas_ref; + glyph->tex_slice = RNG2I32(atlas_offset, AddVec2I32(atlas_offset, image_dims)); + glyph->tex_slice_uv.p0.x = (f32)glyph->tex_slice.p0.x / (f32)atlas_dims.x; + glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas_dims.x; + glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas_dims.x; + glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas_dims.x; - Vec2I32 src_dims = DimsFromRng2I32(src_slice); - if (src_dims.x > 0 && src_dims.y > 0) + if (image_dims.x > 0 && image_dims.y > 0) { - u64 src_pixels_count = src_dims.x * src_dims.y; - u32 *src_pixels = PushStructsNoZero(tick->arena, u32, src_pixels_count); - TTF_RasterizeGlyph(src_pixels, src_dims, src_slice, ttf_desc); - - DEBUGBREAKABLE; - - // G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy); G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct); { G_CopyCpuToTexture( cl, GC.atlas, VEC3I32(atlas_offset.x, atlas_offset.y, 0), - src_pixels, VEC3I32(src_dims.x, src_dims.y, 0), + image_pixels, VEC3I32(image_dims.x, image_dims.y, 0), RNG3I32( - VEC3I32(src_slice.p0.x, src_slice.p0.y, 0), - VEC3I32(src_slice.p1.x, src_slice.p1.y, 1) + VEC3I32(0, 0, 0), + VEC3I32(image_dims.x, image_dims.y, 1) ) ); } @@ -330,14 +334,105 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick) } Atomic32Set(&glyph->ready, 1); - - // ResourceKey resource = desc.font.r; - // String resource_data = DataFromResource(resource); } } WaveSync(lane); + // ////////////////////////////// + // //- Allocate atlas rects + + // if (lane->idx == 0) + // { + // /* TODO: Remove this */ + // /* Create atlas */ + // Vec2I32 atlas_dims = VEC2I32(8192, 8192); + // if (G_IsResourceNil(GC.atlas)) + // { + // G_ArenaHandle gpu_perm = G_PermArena(); + // GC.atlas = G_PushTexture2D( + // gpu_perm, + // G_Format_R8G8B8A8_Unorm_Srgb, + // atlas_dims, + // /* FIXME: We may need simultaneous access? */ + // G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present, + // ); + // } + + // for (u64 cmd_idx = 0; cmd_idx < async->cmds.count; ++cmd_idx) + // { + // GC_Cmd *cmd = &async->cmds.v[cmd_idx]; + // GC_Glyph *glyph = cmd->glyph; + + // ResourceKey resource = glyph->desc.font.r; + // String resource_data = DataFromResource(resource); + // String resource_name = NameFromResource(resource); + + // GC_GlyphDesc desc = glyph->desc; + + // TTF_GlyphDesc ttf_desc = TTF_GlyphDescFromCodepoint(desc.codepoint, resource, desc.font_size); + // glyph->font_size = ttf_desc.font_size; + // glyph->font_ascent = ttf_desc.font_ascent; + // glyph->font_descent = ttf_desc.font_descent; + // glyph->font_cap = ttf_desc.font_cap; + + // glyph->advance = ttf_desc.advance; + // glyph->bounds = ttf_desc.bounds; + // Vec2 dims = DimsFromRng2(glyph->bounds); + + // Vec2I32 atlas_offset = GC.atlas_pos; + // GC.atlas_row_height = MaxI32(GC.atlas_row_height, dims.y); + // if (atlas_offset.x + dims.x > atlas_dims.x); + // { + // GC.atlas_pos.x = 0; + // GC.atlas_pos.y += GC.atlas_row_height; + // GC.atlas_row_height = dims.y; + // } + // GC.atlas_pos.x += dims.x; + + // Rng2I32 src_slice = ZI; + // src_slice.p0.x = 0; + // src_slice.p0.y = 0; + // src_slice.p1.x = RoundF32ToI32(dims.x); + // src_slice.p1.y = RoundF32ToI32(dims.y); + + // Vec2I32 src_dims = DimsFromRng2I32(src_slice); + // if (src_dims.x > 0 && src_dims.y > 0) + // { + // u64 src_pixels_count = src_dims.x * src_dims.y; + // u32 *src_pixels = PushStructsNoZero(tick->arena, u32, src_pixels_count); + // TTF_RasterizeGlyph(src_pixels, src_dims, src_slice, ttf_desc); + + // DEBUGBREAKABLE; + + + // // G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy); + // G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct); + // { + // G_CopyCpuToTexture( + // cl, + // GC.atlas, VEC3I32(atlas_offset.x, atlas_offset.y, 0), + // src_pixels, VEC3I32(src_dims.x, src_dims.y, 0), + // RNG3I32( + // VEC3I32(src_slice.p0.x, src_slice.p0.y, 0), + // VEC3I32(src_slice.p1.x, src_slice.p1.y, 1) + // ) + // ); + // } + // G_CommitCommandList(cl); + + // G_SyncCpu(G_QueueMask_All); + // } + + // Atomic32Set(&glyph->ready, 1); + + // // ResourceKey resource = desc.font.r; + // // String resource_data = DataFromResource(resource); + // } + // } + + // WaveSync(lane); + ////////////////////////////// //- Process cmds @@ -365,253 +460,3 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick) WaveSync(lane); } - - - -////////////////////////////////////////////////////////// -// //~ Font load job - -// JobImpl(F_Load, sig, _) -// { -// TempArena scratch = BeginScratchNoConflict(); - -// PERSIST Readonly u32 font_codes[] = { -// 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D, -// 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, -// 0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49, -// 0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, -// 0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65, -// 0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73, -// 0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x80,0x81, -// 0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, -// 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D, -// 0x9E,0x9F,0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB, -// 0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9, -// 0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7, -// 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5, -// 0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,0xE2,0xE3, -// 0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1, -// 0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF -// }; - -// ResourceKey resource = sig->resource; -// String name = NameFromResource(resource); -// f32 font_size = sig->size; -// f32 em_size = font_size * (3.0 / 4.0); -// AC_Asset *asset = sig->asset; - -// LogInfoF("Loading font \"%F\" (font size: %F, em size: %F)", FmtString(name), FmtFloat((f64)font_size), FmtFloat((f64)em_size)); -// i64 start_ns = TimeNs(); - -// Assert(StringEndsWith(name, Lit(".ttf"))); -// Assert(countof(font_codes) < F_LookupTableSize); - -// /* Decode */ -// String resource_data = DataFromResource(resource); -// if (resource_data.len == 0) -// { -// /* FIME: Load baked font instead of panicking */ -// Panic(StringF(scratch.arena, -// "Font \"%F\" not found", -// FmtString(name))); -// } -// TTF_Decoded decoded = TTF_Decode(scratch.arena, resource_data, em_size, font_codes, countof(font_codes)); - -// /* Upload texture to GPU */ -// Fence completion_fence = ZI; -// { -// GPU_CommandList *cl = GPU_BeginCommandList(GPU_QueueKind_BackgroundCopy); -// GPU_Arena *gpu_temp = GPU_AcquireArena(); -// { -// GpuTexture gpu_texture = ZI; -// { -// GPU_Arena *gpu_perm = GPU_Perm(); -// GPU_ResourceDesc desc = ZI; -// desc.texture.format = GPU_Format_R8G8B8A8_Unorm_Srgb; -// desc.texture.size = VEC3I32(decoded.image_width, decoded.image_height, 1); -// gpu_texture = GPU_PushTexture(gpu_perm, GPU_TextureKind_2D, desc); -// } -// texture->gpu_texture = gpu_texture; -// texture->width = decoded.width; -// texture->height = decoded.height; -// GpuBuffer src_buff = GPU_PushBuffer(gpu_temp, GPU_GetFootprintSize(gpu_texture), GPU_BufferFlag_CpuWritable); -// GpuAddress src_addr = ZI; -// { -// u32 *p = GPU_PushStructsNoZero(src_buff, u32, decoded.width * decoded.height); -// CopyStructs(p, decoded.pixels, decoded.width * decoded.heigth); -// GPU_TransitionBufferToCopySrc(src_buff); -// GPU_TransitionTextureToCopyDst(gpu_texture); -// GPU_CopyBytesToFootprint(gpu_texture, src_buff, src_addr, decoded.width * decoded.height * 4); -// GPU_TransitionTextureToReadonly(gpu_texture); -// } -// GPU_SetFence(&completion_fence, 1); -// } -// GPU_ReleaseArena(gpu_temp); -// GPU_EndCommandList(cl); -// } - -// /* Acquire store memory */ -// F_Font *font = 0; -// { -// AC_Store store = AC_OpenStore(); -// font = PushStruct(store.arena, F_Font); -// font->glyphs = PushStructsNoZero(store.arena, F_Glyph, decoded.glyphs_count); -// font->lookup = PushStructs(store.arena, u16, F_LookupTableSize); -// AC_CloseStore(&store); -// } - -// /* Set font data */ -// font->texture = texture; -// font->image_width = decoded.image_width; -// font->image_height = decoded.image_height; -// font->glyphs_count = decoded.glyphs_count; -// font->size = font_size; -// font->ascent = decoded.ascent; -// font->descent = decoded.descent; -// font->cap = decoded.cap; - -// /* FIXME: Load baked font instead of panicking */ -// if (font->glyphs_count <= 0) -// { -// Panic(StringF(scratch.arena, -// "Parsed 0 glyphs from font \"%F\"!", -// FmtString(name))); -// } - -// /* Copy glyphs from decode decoded */ -// /* NOTE: Font glyph size must match TTF glyph size for memcpy */ -// StaticAssert(sizeof(*font->glyphs) == sizeof(*decoded.glyphs)); -// CopyBytes(font->glyphs, decoded.glyphs, sizeof(*font->glyphs) * decoded.glyphs_count); - -// /* Build lookup table */ -// for (u64 i = 0; i < countof(font_codes); ++i) -// { -// u32 codepoint = font_codes[i]; -// font->lookup[codepoint] = decoded.cache_indices[i]; -// } - -// YieldOnFence(&completion_fence, 1); - -// LogSuccessF("Loaded font \"%F\" (font size: %F, em size: %F) in %F seconds", FmtString(name), FmtFloat((f64)font_size), FmtFloat((f64)em_size), FmtFloat(SecondsFromNs(TimeNs() - start_ns))); -// AC_MarkReady(asset, font); - -// EndScratch(scratch); -// } - -// //////////////////////////////////////////////////////////// -// //~ Font load - -// /* Returns the asset from the asset cache */ -// AC_Asset *F_LoadAsset(ResourceKey resource, f32 size, b32 wait) -// { -// TempArena scratch = BeginScratchNoConflict(); -// String name = NameFromResource(resource); - -// /* Concatenate size to name for key */ -// String key = StringF(scratch.arena, -// "%F%F_font", -// FmtString(name), -// FmtFloatP((f64)size, 1)); -// u64 hash = AC_HashFromKey(key); -// b32 is_first_touch; -// AC_Asset *asset = AC_TouchCache(key, hash, &is_first_touch); - -// if (is_first_touch) -// { -// AC_MarkLoading(asset); -// { -// Job *job = OpenJob(F_Load, AsyncPool()); -// F_Load_Sig *sig = PushStruct(job->arena, F_Load_Sig); -// job->sig = sig; -// sig->asset = asset; -// sig->resource = resource; -// sig->size = size; -// CloseJob(job); -// } -// if (wait) -// { -// AC_YieldOnAssetReady(asset); -// } -// } - -// EndScratch(scratch); -// return asset; -// } - -// F_Font *F_LoadFontAsync(ResourceKey resource, f32 point_size) -// { -// AC_Asset *asset = F_LoadAsset(resource, point_size, 0); -// F_Font *f = (F_Font *)AC_DataFromStore(asset); -// return f; -// } - -// F_Font *F_LoadFontWait(ResourceKey resource, f32 point_size) -// { -// AC_Asset *asset = F_LoadAsset(resource, point_size, 1); -// AC_YieldOnAssetReady(asset); -// F_Font *f = (F_Font *)AC_DataFromStore(asset); -// return f; -// } - -// //////////////////////////////////////////////////////////// -// //~ Font data - -// F_Glyph F_GlyphFromCodepoint(F_Font *font, u32 codepoint) -// { -// if (codepoint < F_LookupTableSize) -// { -// u16 index = font->lookup[codepoint]; -// if (index < font->glyphs_count) -// { -// return font->glyphs[index]; -// } -// } -// if (codepoint == '?') -// { -// return font->glyphs[font->lookup[0]]; -// } -// else -// { -// return font->glyphs[font->lookup['?']]; -// } -// } - -// F_Run F_RunFromString(Arena *arena, F_Font *font, String str) -// { -// F_Run result = ZI; -// result.rects = ArenaNext(arena, F_RunRect); - -// f32 baseline_length = 0; -// for (CodepointIter it = InitCodepointIter(str); NextCodepoint(&it);) -// { -// u32 codepoint = it.codepoint; -// if (font->glyphs_count <= codepoint) -// { -// codepoint = '?'; -// } -// if (codepoint < font->glyphs_count) -// { -// u16 index = font->lookup[codepoint]; -// F_Glyph glyph = font->glyphs[index]; -// F_RunRect *rect = PushStruct(arena, F_RunRect); -// ++result.count; - -// rect->atlas_p0 = glyph.atlas_p0; -// rect->atlas_p1 = glyph.atlas_p1; -// Vec2I32 size = SubVec2I32(glyph.atlas_p1, glyph.atlas_p0); - -// rect->pos = baseline_length; -// rect->offset = glyph.baseline_offset; -// rect->advance = glyph.advance; - -// result.p0.x = MinF32(result.p0.x, rect->offset.x + rect->pos); /* Left run bounds */ -// result.p1.x = MaxF32(result.p1.x, rect->offset.x + rect->pos + size.x); /* Right run bounds */ -// result.p0.y = MinF32(result.p0.y, rect->offset.y); /* Top run bounds */ -// result.p1.y = MaxF32(result.p1.y, rect->offset.y + size.y); /* Bottom run bounds */ - -// baseline_length += rect->advance; -// } -// } - -// return result; -// } diff --git a/src/glyph_cache/glyph_cache.h b/src/glyph_cache/glyph_cache.h index 75c25802..740250c4 100644 --- a/src/glyph_cache/glyph_cache.h +++ b/src/glyph_cache/glyph_cache.h @@ -33,12 +33,12 @@ Struct(GC_Glyph) /* Layout info */ f32 advance; - Rng2 bounds; /* Bounds relative to baseline position */ + Rng2 bounds; /* Atlas info */ G_Texture2DRef tex_ref; - Rng2 tex_uv; - Rng2 tex_rect; + Rng2I32 tex_slice; + Rng2 tex_slice_uv; }; Struct(GC_GlyphBin) @@ -63,8 +63,8 @@ Struct(GC_RunRect) f32 advance; G_Texture2DRef tex; - Rng2 tex_uv; - Rng2 tex_rect; + Rng2I32 tex_slice; + Rng2 tex_slice_uv; }; Struct(GC_Run) @@ -161,77 +161,3 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size //~ Async void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *ctx); - - - - - -// //////////////////////////////////////////////////////////// -// //~ Font types - -// Struct(GC_FontKey) -// { -// u64 v; -// }; - -// Struct(GC_Glyph) -// { -// i32 advance; -// Vec2 baseline_offset; -// Vec2I32 atlas_p0; -// Vec2I32 atlas_p1; -// }; - -// Struct(GC_Font) -// { -// GPU_Resource *texture; -// u32 image_width; -// u32 image_height; -// u16 glyphs_count; -// F_Glyph *glyphs; -// u16 *lookup; - -// /* Metrics */ -// f32 size; -// f32 ascent; -// f32 descent; -// f32 cap; -// }; - -// //////////////////////////////////////////////////////////// -// //~ Run types - -// Struct(F_RunRect) -// { -// Vec2 offset; /* Vector from baseline offset to top left of glyph rect */ -// f32 pos; /* Horizontal distance from start of baseline */ -// f32 advance; -// Vec2I32 atlas_p0; -// Vec2I32 atlas_p1; -// }; - -// Struct(F_Run) -// { -// Vec2 p0; /* Start of baseline to top-left-most rect */ -// Vec2 p1; /* Start of baseline to bottom-right-most rect corner */ -// u32 count; -// F_RunRect *rects; -// }; - -// //////////////////////////////////////////////////////////// -// //~ Font load job - -// JobDecl(F_Load, { AC_Asset *asset; f32 size; ResourceKey resource; }); - -// //////////////////////////////////////////////////////////// -// //~ Font load - -// AC_Asset *F_LoadAsset(ResourceKey resource, f32 size, b32 wait); -// F_Font *F_LoadFontAsync(ResourceKey resource, f32 size); -// F_Font *F_LoadFontWait(ResourceKey resource, f32 size); - -// //////////////////////////////////////////////////////////// -// //~ Run - -// F_Glyph F_GlyphFromCodepoint(F_Font *font, u32 codepoint); -// F_Run F_RunFromString(Arena *arena, F_Font *font, String str); diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index 0a04a386..1ff93942 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -2319,9 +2319,9 @@ void G_CopyCpuToTexture(G_CommandListHandle cl_handle, G_ResourceHandle dst_hand } G_CopyBufferToTexture(cl_handle, - dst_handle, dst_offset, - G_D12_MakeHandle(G_ResourceHandle, ®ion->heap->resource), staged_dims, - RNG3I32(VEC3I32(0, 0, 0), staged_dims)); + dst_handle, dst_offset, + G_D12_MakeHandle(G_ResourceHandle, ®ion->heap->resource), staged_dims, + RNG3I32(VEC3I32(0, 0, 0), staged_dims)); } //- Gpu <-> Gpu copy @@ -2331,8 +2331,8 @@ void G_CopyBufferToBuffer(G_CommandListHandle cl_handle, G_ResourceHandle dst_ha G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); G_D12_Cmd *cmd = G_D12_PushCmd(cl); cmd->kind = G_D12_CmdKind_CopyBytes; - cmd->copy_bytes.dst = G_D12_ResourceFromHandle(dst_handle); cmd->copy_bytes.src = G_D12_ResourceFromHandle(src_handle); + cmd->copy_bytes.dst = G_D12_ResourceFromHandle(dst_handle); cmd->copy_bytes.dst_offset = dst_offset; cmd->copy_bytes.src_copy_range = src_copy_range; } @@ -2341,13 +2341,13 @@ void G_CopyBufferToTexture(G_CommandListHandle cl_handle, G_ResourceHandle dst_h { G_D12_SharedState *g = &G_D12_shared_state; G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); - G_D12_Resource *dst = G_D12_ResourceFromHandle(dst_handle); G_D12_Resource *src = G_D12_ResourceFromHandle(src_handle); - Assert(dst->is_texture); + G_D12_Resource *dst = G_D12_ResourceFromHandle(dst_handle); Assert(!src->is_texture); + Assert(dst->is_texture); /* Grab footprint info */ - D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint = ZI; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT src_footprint = ZI; { D3D12_RESOURCE_DESC src_desc = ZI; { @@ -2356,21 +2356,21 @@ void G_CopyBufferToTexture(G_CommandListHandle cl_handle, G_ResourceHandle dst_h src_desc.Height = src_dims.y; src_desc.DepthOrArraySize = src_dims.z; } - ID3D12Device_GetCopyableFootprints(g->device, &src_desc, 0, 1, 0, &footprint, 0, 0, 0); + ID3D12Device_GetCopyableFootprints(g->device, &src_desc, 0, 1, 0, &src_footprint, 0, 0, 0); } - D3D12_TEXTURE_COPY_LOCATION dst_loc = ZI; D3D12_TEXTURE_COPY_LOCATION src_loc = ZI; + D3D12_TEXTURE_COPY_LOCATION dst_loc = ZI; + { + src_loc.pResource = src->d3d_resource; + src_loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + src_loc.PlacedFootprint = src_footprint; + } { dst_loc.pResource = dst->d3d_resource; dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; dst_loc.SubresourceIndex = 0; } - { - src_loc.pResource = src->d3d_resource; - src_loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - src_loc.PlacedFootprint = footprint; - } G_D12_Cmd *cmd = G_D12_PushCmd(cl); cmd->kind = G_D12_CmdKind_CopyTexels; @@ -2386,23 +2386,23 @@ void G_CopyTextureToTexture(G_CommandListHandle cl_handle, G_ResourceHandle dst_ { G_D12_SharedState *g = &G_D12_shared_state; G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); - G_D12_Resource *dst = G_D12_ResourceFromHandle(dst_handle); G_D12_Resource *src = G_D12_ResourceFromHandle(src_handle); - Assert(dst->is_texture); + G_D12_Resource *dst = G_D12_ResourceFromHandle(dst_handle); Assert(src->is_texture); + Assert(dst->is_texture); - D3D12_TEXTURE_COPY_LOCATION dst_loc = ZI; D3D12_TEXTURE_COPY_LOCATION src_loc = ZI; - { - dst_loc.pResource = dst->d3d_resource; - dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - dst_loc.SubresourceIndex = 0; - } + D3D12_TEXTURE_COPY_LOCATION dst_loc = ZI; { src_loc.pResource = dst->d3d_resource; src_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; src_loc.SubresourceIndex = 0; } + { + dst_loc.pResource = dst->d3d_resource; + dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dst_loc.SubresourceIndex = 0; + } G_D12_Cmd *cmd = G_D12_PushCmd(cl); cmd->kind = G_D12_CmdKind_CopyTexels; @@ -2900,7 +2900,7 @@ void G_D12_CollectionWorkerEntryPoint(WaveLaneCtx *lane) TempArena scratch = BeginScratchNoConflict(); u8 *at = start; { - for (u32 print_num = 1; print_num <= prints_count; ++print_num) + for (u32 print_idx = 0; print_idx < prints_count; ++print_idx) { u32 chars_count = 0; u32 args_count = 0; diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index d77ec7b4..e0deb429 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -249,7 +249,7 @@ void V_TickForever(WaveLaneCtx *lane) { /* TODO: Don't rely on ui report for draw size since it introduces one frame of delay when resizing */ UI_Report vis_rep = UI_ReportFromKey(vis_box); - draw_size = RoundVec2ToVec2I32(DimsFromRng2(vis_rep.screen_rect)); + draw_size = RoundVec2ToI32(DimsFromRng2(vis_rep.screen_rect)); } draw_size.x = MaxI32(draw_size.x, 1); draw_size.y = MaxI32(draw_size.y, 1); diff --git a/src/ttf/ttf.h b/src/ttf/ttf.h index 23b31138..0c219d37 100644 --- a/src/ttf/ttf.h +++ b/src/ttf/ttf.h @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// //~ Glyph types -Struct(TTF_GlyphDesc) +Struct(TTF_GlyphResult) { ResourceKey ttf; u32 codepoint; @@ -13,15 +13,18 @@ Struct(TTF_GlyphDesc) f32 font_ascent; f32 font_descent; f32 font_cap; + + /* Rasterization output */ + Vec2I32 image_dims; + u32 *image_pixels; }; //////////////////////////////////////////////////////////// -//~ Bootstrap +//~ @hookdecl Bootstrap void TTF_Bootstrap(void); //////////////////////////////////////////////////////////// -//~ Decode +//~ @hookdecl Rasterize -TTF_GlyphDesc TTF_GlyphDescFromCodepoint(u32 codepoint, ResourceKey ttf, f32 font_size); -void TTF_RasterizeGlyph(u32 *dst, Vec2I32 dst_size, Rng2I32 dst_slice, TTF_GlyphDesc glyph_desc); +TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, ResourceKey ttf, f32 font_size); diff --git a/src/ttf/ttf_dwrite/ttf_dwrite.c b/src/ttf/ttf_dwrite/ttf_dwrite.c index 3f901714..42bcb249 100644 --- a/src/ttf/ttf_dwrite/ttf_dwrite.c +++ b/src/ttf/ttf_dwrite/ttf_dwrite.c @@ -24,23 +24,21 @@ void TTF_Bootstrap(void) } //////////////////////////////////////////////////////////// -//~ @hookimpl Decode +//~ @hookimpl Rasterize -TTF_GlyphDesc TTF_GlyphDescFromCodepoint(u32 codepoint, ResourceKey ttf, f32 font_size) +TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, ResourceKey ttf, f32 font_size) { - String encoded = DataFromResource(ttf); - - /* TODO: Handle errors */ - HRESULT hr = 0; - - TTF_GlyphDesc result = ZI; - result.font_size = font_size; - result.ttf = ttf; - result.codepoint = codepoint; + COLORREF bg_color = 0xFF000000; + COLORREF fg_color = 0xFFFFFFFF; f32 em_size = font_size * (3.0 / 4.0); f32 pixel_per_em = em_size * (TTF_DW_Dpi / 72.0f); + /* TODO: handle errors */ + HRESULT hr = 0; + + String encoded = DataFromResource(ttf); + /* File */ IDWriteFontFile *font_file = 0; { @@ -61,88 +59,39 @@ TTF_GlyphDesc TTF_GlyphDescFromCodepoint(u32 codepoint, ResourceKey ttf, f32 fon hr = IDWriteFactory5_CreateFontFace(TTF_DW.factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &font_file, 0, DWRITE_FONT_SIMULATIONS_NONE, &font_face); } + /* Glyph idx */ + u16 glyph_idx = 0; + { + hr = IDWriteFontFace_GetGlyphIndices(font_face, &codepoint, 1, &glyph_idx); + } + /* Font metrics */ DWRITE_FONT_METRICS font_metrics = ZI; { IDWriteFontFace_GetMetrics(font_face, &font_metrics); } f32 pixel_per_design_unit = pixel_per_em / ((f32)font_metrics.designUnitsPerEm); - result.font_ascent = font_metrics.ascent * pixel_per_design_unit; - result.font_descent = font_metrics.descent * pixel_per_design_unit; - result.font_cap = font_metrics.capHeight * pixel_per_design_unit; - - /* Glyph idx */ - u16 glyph_idx = 0; - { - hr = IDWriteFontFace_GetGlyphIndices(font_face, &codepoint, 1, &glyph_idx); - } - + f32 font_ascent = font_metrics.ascent * pixel_per_design_unit; + f32 font_descent = font_metrics.descent * pixel_per_design_unit; + f32 font_cap = font_metrics.capHeight * pixel_per_design_unit; /* Glyph metrics */ + DWRITE_GLYPH_METRICS m = ZI; { - DWRITE_GLYPH_METRICS m = ZI; - { - hr = IDWriteFontFace_GetDesignGlyphMetrics(font_face, &glyph_idx, 1, &m, 0); - } - Rng2 bounds = ZI; - { - bounds.p0.x = (f32)m.leftSideBearing; - bounds.p1.x = (f32)m.advanceWidth - (f32)m.rightSideBearing; - bounds.p0.y = (f32)m.verticalOriginY - (f32)m.advanceHeight + m.bottomSideBearing; - bounds.p1.y = (f32)m.verticalOriginY - (f32)m.topSideBearing; - } - result.bounds.p0.x = bounds.p0.x * pixel_per_design_unit; - result.bounds.p0.y = bounds.p0.y * pixel_per_design_unit; - result.bounds.p1.x = bounds.p1.x * pixel_per_design_unit; - result.bounds.p1.y = bounds.p1.y * pixel_per_design_unit; - result.advance = (f32)m.advanceWidth * pixel_per_design_unit; + hr = IDWriteFontFace_GetDesignGlyphMetrics(font_face, &glyph_idx, 1, &m, 0); } + f32 advance = (f32)m.advanceWidth * pixel_per_design_unit; - return result; -} -void TTF_RasterizeGlyph(u32 *dst, Vec2I32 dst_size, Rng2I32 dst_slice, TTF_GlyphDesc glyph_desc) -{ - COLORREF bg_color = 0xFF000000; - COLORREF fg_color = 0xFFFFFFFF; - f32 em_size = glyph_desc.font_size * (3.0 / 4.0); - f32 pixel_per_em = em_size * (TTF_DW_Dpi / 72.0f); - /* TODO: handle errors */ - HRESULT hr = 0; - String encoded = DataFromResource(glyph_desc.ttf); - /* File */ - IDWriteFontFile *font_file = 0; - { - /* Create in memory loader */ - IDWriteInMemoryFontFileLoader *loader = 0; - hr = IDWriteFactory5_CreateInMemoryFontFileLoader(TTF_DW.factory, &loader); - hr = IDWriteFactory5_RegisterFontFileLoader(TTF_DW.factory, (IDWriteFontFileLoader *)loader); - IDWriteFontSetBuilder1 *builder = 0; - hr = IDWriteFactory5_CreateFontSetBuilder1(TTF_DW.factory, &builder); - hr = IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(loader, (IDWriteFactory *)TTF_DW.factory, encoded.text, (u32)encoded.len, 0, &font_file); - hr = IDWriteFontSetBuilder1_AddFontFile(builder, font_file); - } - - /* Face */ - IDWriteFontFace *font_face = 0; - { - hr = IDWriteFactory5_CreateFontFace(TTF_DW.factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &font_file, 0, DWRITE_FONT_SIMULATIONS_NONE, &font_face); - } - - /* Glyph idx */ - u16 glyph_idx = 0; - { - hr = IDWriteFontFace_GetGlyphIndices(font_face, &glyph_desc.codepoint, 1, &glyph_idx); - } @@ -159,8 +108,10 @@ void TTF_RasterizeGlyph(u32 *dst, Vec2I32 dst_size, Rng2I32 dst_slice, TTF_Glyph /* FIXME: Dynamic render target */ i32 render_target_w = 256; i32 render_target_h = 256; - i32 render_target_baseline_x = (render_target_w / 2) - DimsFromRng2I32(dst_slice).x; - i32 render_target_baseline_y = (render_target_h / 2) - DimsFromRng2I32(dst_slice).y; + + /* Best-guess a position in the middle of the render target based on metrics */ + i32 render_target_baseline_x = (render_target_w / 2) - (advance / 2); + i32 render_target_baseline_y = (render_target_h / 2) - (font_cap / 2); /* Create render target */ IDWriteBitmapRenderTarget *render_target = 0; @@ -222,7 +173,7 @@ void TTF_RasterizeGlyph(u32 *dst, Vec2I32 dst_size, Rng2I32 dst_slice, TTF_Glyph } /* Render glyph to target */ - Rng2I32 src_slice = ZI; + Rng2I32 rt_slice = ZI; { DWRITE_GLYPH_RUN glyph_run = ZI; { @@ -242,563 +193,54 @@ void TTF_RasterizeGlyph(u32 *dst, Vec2I32 dst_size, Rng2I32 dst_slice, TTF_Glyph fg_color, &bounding_box ); - src_slice.p0.x = bounding_box.left; - src_slice.p0.y = bounding_box.top; - src_slice.p1.x = bounding_box.right; - src_slice.p1.y = bounding_box.bottom; + rt_slice.p0.x = bounding_box.left; + rt_slice.p0.y = bounding_box.top; + rt_slice.p1.x = bounding_box.right; + rt_slice.p1.y = bounding_box.bottom; } + rt_slice.p0.x = MaxI32(rt_slice.p0.x, 0); + rt_slice.p0.y = MaxI32(rt_slice.p0.y, 0); + rt_slice.p1.x = MinI32(rt_slice.p1.x, render_target_w); + rt_slice.p1.y = MinI32(rt_slice.p1.y, render_target_h); - Vec2I32 src_slice_dims = DimsFromRng2I32(src_slice); - Vec2I32 dst_slice_dims = DimsFromRng2I32(dst_slice); + Vec2I32 dst_dims = DimsFromRng2I32(rt_slice); + u32 *dst_pixels = PushStructsNoZero(arena, u32, dst_dims.x * dst_dims.y); - /* FIXME: Handle gracefully */ - Assert(src_slice_dims.x <= dst_slice_dims.x); - Assert(src_slice_dims.y <= dst_slice_dims.y); - - /* FIXME: Account for render target overrun */ - /* Copy result from target */ + /* Copy from target to result */ { u64 src_pitch = (u64)dib.dsBm.bmWidthBytes / 4; u32 *src_pixels = (u32 *)dib.dsBm.bmBits; - for (i32 y = 0; y < src_slice_dims.y; ++y) + for (i32 y = 0; y < dst_dims.y; ++y) { - u64 src_y = src_slice.p0.y + y; - u64 dst_y = dst_slice.p0.y + y; - for (i32 x = 0; x < src_slice_dims.x; ++x) + u64 src_y = rt_slice.p0.y + y; + u64 dst_y = y; + for (i32 x = 0; x < dst_dims.x; ++x) { - u64 src_x = src_slice.p0.x + x; - u64 dst_x = dst_slice.p0.x + x; + u64 src_x = rt_slice.p0.x + x; + u64 dst_x = x; u32 *src_pixel = src_pixels + (src_x + (src_y * src_pitch)); - u32 *dst_pixel = dst + (dst_x + (dst_y * dst_size.x)); + u32 *dst_pixel = dst_pixels + (dst_x + (dst_y * dst_dims.x)); *dst_pixel = 0x00FFFFFF | ((*src_pixel & 0xFF) << 24); } } } + TTF_GlyphResult result = ZI; + { + result.ttf = ttf; + result.codepoint = codepoint; + result.advance = advance; + result.bounds.p0 = VEC2(0, 0); + result.bounds.p1 = Vec2FromVec(dst_dims); + result.font_size = font_size; + result.font_ascent = font_ascent; + result.font_descent = font_descent; + result.font_cap = font_cap; - - // //- Create face - // IDWriteFontFace *font_face = 0; - // error = IDWriteFactory5_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &font_file, 0, DWRITE_FONT_SIMULATIONS_NONE, &font_face); - - // //- Setup rendering params - // IDWriteRenderingParams *default_rendering_params = 0; - // error = IDWriteFactory5_CreateRenderingParams(factory, &default_rendering_params); - // IDWriteRenderingParams *rendering_params = 0; - // FLOAT gamma = IDWriteRenderingParams_GetGamma(default_rendering_params); - // FLOAT enhanced_contrast = IDWriteRenderingParams_GetEnhancedContrast(default_rendering_params); - // FLOAT clear_type_level = IDWriteRenderingParams_GetClearTypeLevel(default_rendering_params); - // error = IDWriteFactory5_CreateCustomRenderingParams(factory, gamma, - // enhanced_contrast, - // clear_type_level, - // DWRITE_PIXEL_GEOMETRY_FLAT, - // DWRITE_RENDERING_MODE_DEFAULT, - // &rendering_params); - - // //- Setup interop - // IDWriteGdiInterop *dwrite_gdi_interop = 0; - // error = IDWriteFactory5_GetGdiInterop(factory, &dwrite_gdi_interop); - - // //- Get metrics - // DWRITE_FONT_METRICS metrics = ZI; - // IDWriteFontFace_GetMetrics(font_face, &metrics); - - // u16 glyph_count = IDWriteFontFace_GetGlyphCount(font_face); - - // f32 pixel_per_em = em_size * (TTF_DW_Dpi / 72.0f); - // f32 pixel_per_design_unit = pixel_per_em / ((f32)metrics.designUnitsPerEm); - - // i32 raster_target_w = (i32)(8.0f * ((f32)metrics.capHeight) * pixel_per_design_unit); - // i32 raster_target_h = raster_target_w; - - // f32 raster_target_x = (f32)(raster_target_w / 2); - // f32 raster_target_y = raster_target_x; - - // Assert((f32)((i32)raster_target_x) == raster_target_x); - // Assert((f32)((i32)raster_target_y) == raster_target_y); - - // //- Setup render target - // IDWriteBitmapRenderTarget *render_target = 0; - // /* FIXME: errors when em_size too high */ - // error = IDWriteGdiInterop_CreateBitmapRenderTarget(dwrite_gdi_interop, 0, (UINT32)raster_target_w, (UINT32)raster_target_h, &render_target); - // IDWriteBitmapRenderTarget_SetPixelsPerDip(render_target, 1.0); - - // /* Clear the render target */ - // HDC dc = 0; - // { - // dc = IDWriteBitmapRenderTarget_GetMemoryDC(render_target); - // HGDIOBJ original = SelectObject(dc, GetStockObject(DC_PEN)); - // SetDCPenColor(dc, bg_color); - // SelectObject(dc, GetStockObject(DC_BRUSH)); - // SetDCBrushColor(dc, bg_color); - // Rectangle(dc, 0, 0, raster_target_w, raster_target_h); - // SelectObject(dc, original); - // } - - // //- Setup atlas - // /* Acquire font memory */ - // TTF_Glyph *glyphs = (TTF_Glyph *)PushStructs(arena, TTF_Glyph, glyph_count); - - // /* Acquire (starting) atlas memory - // * NOTE: This is unnecessary since atlas memory will grow anyway. Could - // * just start w/ atlas height 0. - // */ - // u64 atlas_w = 1024; - // u64 atlas_h = 1; - // u32 *atlas_memory = PushStructs(arena, u32, atlas_w * atlas_h); - - // i32 ascent = 0; - // i32 descent = 0; - // i32 cap = 0; - - // //- Fill atlas & metric data - // u32 out_offset_x = 0; - // u32 out_offset_y = 0; - // u32 row_height = 0; - // { - // for (u16 i = 0; i < glyph_count; ++i) - // { - // //- Render glyph to render target - // DWRITE_GLYPH_RUN glyph_run = ZI; - // glyph_run.fontFace = font_face; - // glyph_run.fontEmSize = pixel_per_em; - // glyph_run.glyphCount = 1; - // glyph_run.glyphIndices = &i; - - // RECT bounding_box = ZI; - // error = IDWriteBitmapRenderTarget_DrawGlyphRun(render_target, - // raster_target_x, - // raster_target_y, - // DWRITE_MEASURING_MODE_NATURAL, - // &glyph_run, - // rendering_params, - // fg_color, - // &bounding_box - // ); - - // if (bounding_box.left < 0 - // || bounding_box.top < 0 - // || bounding_box.right > raster_target_w - // || bounding_box.bottom > raster_target_h) - // { - // /* Skip */ - // continue; - // } - - // //- Compute glyph metrics - // DWRITE_GLYPH_METRICS glyph_metrics = ZI; - // error = IDWriteFontFace_GetDesignGlyphMetrics(font_face, &i, 1, &glyph_metrics, 0); - // ascent = metrics.ascent * pixel_per_design_unit; - // descent = metrics.descent * pixel_per_design_unit; - // cap = metrics.capHeight * pixel_per_design_unit; - - // f32 off_x = (f32)bounding_box.left - raster_target_x; - // f32 off_y = (f32)bounding_box.top - raster_target_y; - // i32 tex_w = bounding_box.right - bounding_box.left; - // i32 tex_h = bounding_box.bottom - bounding_box.top; - // f32 advance = CeilF32ToI32((f32)glyph_metrics.advanceWidth * pixel_per_design_unit); - - // TTF_Glyph *glyph = &glyphs[i]; - // glyph->baseline_offset = VEC2(off_x, off_y); - // glyph->advance = advance; - - // /* Get the bitmap */ - // HBITMAP bitmap = (HBITMAP)GetCurrentObject(dc, OBJ_BITMAP); - // DIBSECTION dib = ZI; - // GetObject(bitmap, sizeof(dib), &dib); - - // /* Start new row if necessary */ - // if ((out_offset_x + tex_w) >= atlas_w) - // { - // out_offset_y += row_height; - // out_offset_x = 0; - // row_height = 0; - // } - - // /* Grow atlas height */ - // if ((out_offset_y + tex_h) > atlas_h) - // { - // u64 diff = (out_offset_y + tex_h) - atlas_h; - // /* NOTE: This allocation must be contiguous with the initial atlas - // * allocation (IE: No non-atlas arena PUSHes) */ - // PushStructs(arena, u32, diff * atlas_w); - // atlas_h += diff; - // } - - // /* Set bounding box metrics (now that we know atlas x & y) */ - // glyph->atlas_p0 = VEC2I32(out_offset_x, out_offset_y); - // glyph->atlas_p1 = VEC2I32(out_offset_x + tex_w, out_offset_y + tex_h); - - // //- Fill atlas - // u64 in_pitch = (u64)dib.dsBm.bmWidthBytes / 4; - // u32 *in_data = (u32 *)dib.dsBm.bmBits; - // u32 *out_data = atlas_memory; - // for (i32 y = 0; y < tex_h; ++y) - // { - // u64 out_y = out_offset_y + y; - // u64 in_y = (u64)bounding_box.top + y; - // for (i32 x = 0; x < tex_w; ++x) - // { - // u64 out_x = out_offset_x + x; - // u64 in_x = (u64)bounding_box.left + x; - // u32 *out_pixel = out_data + (out_x + (out_y * atlas_w)); - // u32 *in_pixel = in_data + (in_x + (in_y * in_pitch)); - // *out_pixel = 0x00FFFFFF | ((*in_pixel & 0xFF) << 24); - // } - // } - // out_offset_x += tex_w; - - // /* Grow row height */ - // if ((u32)tex_h > row_height) - // { - // row_height = (u32)tex_h; - // } - - // //- Clear render target - // { - // HGDIOBJ original = SelectObject(dc, GetStockObject(DC_PEN)); - // SetDCPenColor(dc, bg_color); - // SelectObject(dc, GetStockObject(DC_BRUSH)); - // SetDCBrushColor(dc, bg_color); - // Rectangle(dc, bounding_box.left, bounding_box.top, bounding_box.right, bounding_box.bottom); - // SelectObject(dc, original); - // } - // } - // } - - // //- Construct indices - // u16 *cache_indices = 0; - // if (cache_codes_count > 0) - // { - // cache_indices = PushStructs(arena, u16, cache_codes_count); - // IDWriteFontFace_GetGlyphIndices(font_face, cache_codes, cache_codes_count, cache_indices); - // } - - // //- Release - // /* FIXME: Check for leaks */ - // IDWriteGdiInterop_Release(dwrite_gdi_interop); - // IDWriteRenderingParams_Release(rendering_params); - // IDWriteRenderingParams_Release(default_rendering_params); - // // NOTE FROM ALLEN: We don't release font face because we intend to keep the font face around after the baking process - // // IDWriteFontFace_Release(font_face); - // IDWriteFontFile_Release(font_file); - // //loader->Release(); - // IDWriteFactory5_Release(factory); - - // /* Return */ - // TTF_Decoded result = ZI; - // result.glyphs = glyphs; - // result.glyphs_count = glyph_count; - // result.cache_indices = cache_indices; - // result.image_width = (u32)atlas_w; - // result.image_height = (u32)atlas_h; - // result.image_pixels = (u32 *)atlas_memory; - // result.ascent = ascent; - // result.descent = descent; - // result.cap = cap; - // return result; + result.image_dims = dst_dims; + result.image_pixels = dst_pixels; + } + return result; } - - - - - - - - - - - - - - - - - - - - - - - - - -// /* Based on Allen Webster's dwrite rasterizer example - -// * https://github.com/4th-dimention/examps */ - -// extern TTF_DW_Ctx TTF_DW = ZI; - -// //////////////////////////////////////////////////////////// -// //~ @hookimpl Bootstrap - -// void TTF_Bootstrap(void) -// { -// TTF_DW_SharedState *g = &TTF_DW_shared_state; -// Assert(!g->factory); -// /* FIXME: I think IDWriteFactory5 only exists on later updates of windows -// * 10? Need to verify. Maybe should just use a custom loader. (We're only -// * using a factory5 since I think WriteInMemoryFileLoader wasn't -// * implemented until then) */ -// HRESULT error = DWriteCreateFactory( -// DWRITE_FACTORY_TYPE_SHARED, -// &IID_IDWriteFactory5, -// (void **)&g->factory -// ); -// if (!SUCCEEDED(error)) -// { -// Panic(Lit("Error creating DWrite factory")); -// (*(volatile int *)0) = 0; -// } -// } - -// //////////////////////////////////////////////////////////// -// //~ @hookimpl Decode - -// TTF_Decoded TTF_Decode(Arena *arena, String encoded, f32 em_size, u32 *cache_codes, u32 cache_codes_count) -// { -// TTF_DW_SharedState *g = &TTF_DW_shared_state; -// COLORREF bg_color = 0xFF000000; -// COLORREF fg_color = 0xFFFFFFFF; - -// IDWriteFactory5 *factory = g->factory; - -// /* TODO: handle errors */ -// HRESULT error = 0; - -// /* File */ -// IDWriteFontFile *font_file = 0; -// { -// /* Create in memory loader */ -// IDWriteInMemoryFontFileLoader *loader = 0; -// error = IDWriteFactory5_CreateInMemoryFontFileLoader(factory, &loader); -// error = IDWriteFactory5_RegisterFontFileLoader(factory, (IDWriteFontFileLoader *)loader); - -// IDWriteFontSetBuilder1 *builder = 0; -// error = IDWriteFactory5_CreateFontSetBuilder1(factory, &builder); -// error = IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(loader, (IDWriteFactory *)factory, encoded.text, (u32)encoded.len, 0, &font_file); -// error = IDWriteFontSetBuilder1_AddFontFile(builder, font_file); -// } - -// //- Create face -// IDWriteFontFace *font_face = 0; -// error = IDWriteFactory5_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &font_file, 0, DWRITE_FONT_SIMULATIONS_NONE, &font_face); - -// //- Setup rendering params -// IDWriteRenderingParams *default_rendering_params = 0; -// error = IDWriteFactory5_CreateRenderingParams(factory, &default_rendering_params); -// IDWriteRenderingParams *rendering_params = 0; -// FLOAT gamma = IDWriteRenderingParams_GetGamma(default_rendering_params); -// FLOAT enhanced_contrast = IDWriteRenderingParams_GetEnhancedContrast(default_rendering_params); -// FLOAT clear_type_level = IDWriteRenderingParams_GetClearTypeLevel(default_rendering_params); -// error = IDWriteFactory5_CreateCustomRenderingParams(factory, gamma, -// enhanced_contrast, -// clear_type_level, -// DWRITE_PIXEL_GEOMETRY_FLAT, -// DWRITE_RENDERING_MODE_DEFAULT, -// &rendering_params); - -// //- Setup interop -// IDWriteGdiInterop *dwrite_gdi_interop = 0; -// error = IDWriteFactory5_GetGdiInterop(factory, &dwrite_gdi_interop); - -// //- Get metrics -// DWRITE_FONT_METRICS metrics = ZI; -// IDWriteFontFace_GetMetrics(font_face, &metrics); - -// u16 glyph_count = IDWriteFontFace_GetGlyphCount(font_face); - -// f32 pixel_per_em = em_size * (TTF_DW_Dpi / 72.0f); -// f32 pixel_per_design_unit = pixel_per_em / ((f32)metrics.designUnitsPerEm); - -// i32 raster_target_w = (i32)(8.0f * ((f32)metrics.capHeight) * pixel_per_design_unit); -// i32 raster_target_h = raster_target_w; - -// f32 raster_target_x = (f32)(raster_target_w / 2); -// f32 raster_target_y = raster_target_x; - -// Assert((f32)((i32)raster_target_x) == raster_target_x); -// Assert((f32)((i32)raster_target_y) == raster_target_y); - -// //- Setup render target -// IDWriteBitmapRenderTarget *render_target = 0; -// /* FIXME: errors when em_size too high */ -// error = IDWriteGdiInterop_CreateBitmapRenderTarget(dwrite_gdi_interop, 0, (UINT32)raster_target_w, (UINT32)raster_target_h, &render_target); -// IDWriteBitmapRenderTarget_SetPixelsPerDip(render_target, 1.0); - -// /* Clear the render target */ -// HDC dc = 0; -// { -// dc = IDWriteBitmapRenderTarget_GetMemoryDC(render_target); -// HGDIOBJ original = SelectObject(dc, GetStockObject(DC_PEN)); -// SetDCPenColor(dc, bg_color); -// SelectObject(dc, GetStockObject(DC_BRUSH)); -// SetDCBrushColor(dc, bg_color); -// Rectangle(dc, 0, 0, raster_target_w, raster_target_h); -// SelectObject(dc, original); -// } - -// //- Setup atlas -// /* Acquire font memory */ -// TTF_Glyph *glyphs = (TTF_Glyph *)PushStructs(arena, TTF_Glyph, glyph_count); - -// /* Acquire (starting) atlas memory -// * NOTE: This is unnecessary since atlas memory will grow anyway. Could -// * just start w/ atlas height 0. -// */ -// u64 atlas_w = 1024; -// u64 atlas_h = 1; -// u32 *atlas_memory = PushStructs(arena, u32, atlas_w * atlas_h); - -// i32 ascent = 0; -// i32 descent = 0; -// i32 cap = 0; - -// //- Fill atlas & metric data -// u32 out_offset_x = 0; -// u32 out_offset_y = 0; -// u32 row_height = 0; -// { -// for (u16 i = 0; i < glyph_count; ++i) -// { -// //- Render glyph to render target -// DWRITE_GLYPH_RUN glyph_run = ZI; -// glyph_run.fontFace = font_face; -// glyph_run.fontEmSize = pixel_per_em; -// glyph_run.glyphCount = 1; -// glyph_run.glyphIndices = &i; - -// RECT bounding_box = ZI; -// error = IDWriteBitmapRenderTarget_DrawGlyphRun(render_target, -// raster_target_x, -// raster_target_y, -// DWRITE_MEASURING_MODE_NATURAL, -// &glyph_run, -// rendering_params, -// fg_color, -// &bounding_box -// ); - -// if (bounding_box.left < 0 -// || bounding_box.top < 0 -// || bounding_box.right > raster_target_w -// || bounding_box.bottom > raster_target_h) -// { -// /* Skip */ -// continue; -// } - -// //- Compute glyph metrics -// DWRITE_GLYPH_METRICS glyph_metrics = ZI; -// error = IDWriteFontFace_GetDesignGlyphMetrics(font_face, &i, 1, &glyph_metrics, 0); -// ascent = metrics.ascent * pixel_per_design_unit; -// descent = metrics.descent * pixel_per_design_unit; -// cap = metrics.capHeight * pixel_per_design_unit; - -// f32 off_x = (f32)bounding_box.left - raster_target_x; -// f32 off_y = (f32)bounding_box.top - raster_target_y; -// i32 tex_w = bounding_box.right - bounding_box.left; -// i32 tex_h = bounding_box.bottom - bounding_box.top; -// f32 advance = CeilF32ToI32((f32)glyph_metrics.advanceWidth * pixel_per_design_unit); - -// TTF_Glyph *glyph = &glyphs[i]; -// glyph->baseline_offset = VEC2(off_x, off_y); -// glyph->advance = advance; - -// /* Get the bitmap */ -// HBITMAP bitmap = (HBITMAP)GetCurrentObject(dc, OBJ_BITMAP); -// DIBSECTION dib = ZI; -// GetObject(bitmap, sizeof(dib), &dib); - -// /* Start new row if necessary */ -// if ((out_offset_x + tex_w) >= atlas_w) -// { -// out_offset_y += row_height; -// out_offset_x = 0; -// row_height = 0; -// } - -// /* Grow atlas height */ -// if ((out_offset_y + tex_h) > atlas_h) -// { -// u64 diff = (out_offset_y + tex_h) - atlas_h; -// /* NOTE: This allocation must be contiguous with the initial atlas -// * allocation (IE: No non-atlas arena PUSHes) */ -// PushStructs(arena, u32, diff * atlas_w); -// atlas_h += diff; -// } - -// /* Set bounding box metrics (now that we know atlas x & y) */ -// glyph->atlas_p0 = VEC2I32(out_offset_x, out_offset_y); -// glyph->atlas_p1 = VEC2I32(out_offset_x + tex_w, out_offset_y + tex_h); - -// //- Fill atlas -// u64 in_pitch = (u64)dib.dsBm.bmWidthBytes / 4; -// u32 *in_data = (u32 *)dib.dsBm.bmBits; -// u32 *out_data = atlas_memory; -// for (i32 y = 0; y < tex_h; ++y) -// { -// u64 out_y = out_offset_y + y; -// u64 in_y = (u64)bounding_box.top + y; -// for (i32 x = 0; x < tex_w; ++x) -// { -// u64 out_x = out_offset_x + x; -// u64 in_x = (u64)bounding_box.left + x; -// u32 *out_pixel = out_data + (out_x + (out_y * atlas_w)); -// u32 *in_pixel = in_data + (in_x + (in_y * in_pitch)); -// *out_pixel = 0x00FFFFFF | ((*in_pixel & 0xFF) << 24); -// } -// } -// out_offset_x += tex_w; - -// /* Grow row height */ -// if ((u32)tex_h > row_height) -// { -// row_height = (u32)tex_h; -// } - -// //- Clear render target -// { -// HGDIOBJ original = SelectObject(dc, GetStockObject(DC_PEN)); -// SetDCPenColor(dc, bg_color); -// SelectObject(dc, GetStockObject(DC_BRUSH)); -// SetDCBrushColor(dc, bg_color); -// Rectangle(dc, bounding_box.left, bounding_box.top, bounding_box.right, bounding_box.bottom); -// SelectObject(dc, original); -// } -// } -// } - -// //- Construct indices -// u16 *cache_indices = 0; -// if (cache_codes_count > 0) -// { -// cache_indices = PushStructs(arena, u16, cache_codes_count); -// IDWriteFontFace_GetGlyphIndices(font_face, cache_codes, cache_codes_count, cache_indices); -// } - -// //- Release -// /* FIXME: Check for leaks */ -// IDWriteGdiInterop_Release(dwrite_gdi_interop); -// IDWriteRenderingParams_Release(rendering_params); -// IDWriteRenderingParams_Release(default_rendering_params); -// // NOTE FROM ALLEN: We don't release font face because we intend to keep the font face around after the baking process -// // IDWriteFontFace_Release(font_face); -// IDWriteFontFile_Release(font_file); -// //loader->Release(); -// IDWriteFactory5_Release(factory); - -// /* Return */ -// TTF_Decoded result = ZI; -// result.glyphs = glyphs; -// result.glyphs_count = glyph_count; -// result.cache_indices = cache_indices; -// result.image_width = (u32)atlas_w; -// result.image_height = (u32)atlas_h; -// result.image_pixels = (u32 *)atlas_memory; -// result.ascent = ascent; -// result.descent = descent; -// result.cap = cap; -// return result; -// } diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 52f8a2f9..be973f9f 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -1350,11 +1350,13 @@ void UI_EndFrame(UI_Frame *frame) if (glyph_dims.x != 0 || glyph_dims.y != 0) { UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect); - rect->bounds = AddRng2Vec2(rr.bounds, baseline); rect->debug_lin = LinearFromSrgb(box->desc.debug_color); rect->tint_lin = LinearFromSrgb(box->desc.tint); rect->tex = rr.tex; - rect->tex_slice_uv = rr.tex_uv; + rect->tex_slice_uv = rr.tex_slice_uv; + rect->bounds = rr.bounds; + rect->bounds = AddRng2Vec2(rect->bounds, baseline); + rect->bounds = AddRng2Vec2(rect->bounds, VEC2(rr.baseline_pos, 0)); } } }