From 7a10f4066f910c129e8b45d51d6ccd189d0d4b41 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sun, 28 Jul 2019 14:31:05 -0700 Subject: [PATCH] Switched over to rendering fonts from Windows directly (can now get rid of stb_truetype), and got textures rendering in OpenGL again --- foldhaus_app.cpp | 105 +++++++++++++++++++++++++-------------------- gs_font.h | 22 ++++++++-- gs_platform.h | 2 +- gs_win32.cpp | 17 +++++++- gs_win32.h | 4 -- interface.h | 8 ++-- win32_foldhaus.cpp | 83 ++++++++++++++++++++++++++--------- 7 files changed, 162 insertions(+), 79 deletions(-) diff --git a/foldhaus_app.cpp b/foldhaus_app.cpp index 02124bb..12b1e6d 100644 --- a/foldhaus_app.cpp +++ b/foldhaus_app.cpp @@ -414,54 +414,55 @@ INITIALIZE_APPLICATION(InitializeApplication) platform_memory_result FontFile = Context.PlatformReadEntireFile("Anonymous Pro.ttf"); if (FontFile.Size) { - stbtt_fontinfo StbFont; - if (stbtt_InitFont(&StbFont, FontFile.Base, stbtt_GetFontOffsetForIndex(FontFile.Base, 0))) + bitmap_font* Font = PushStruct(State->Permanent, bitmap_font); + + Font->BitmapWidth = 512; + Font->BitmapHeight = 512; + Font->BitmapBytesPerPixel = 4; + Font->BitmapMemory = PushArray(State->Permanent, u8, Font->BitmapWidth * Font->BitmapHeight * Font->BitmapBytesPerPixel); + Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel; + GSMemSet(Font->BitmapMemory, 0, Font->BitmapStride * Font->BitmapHeight); + + platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", 14); + Font->PixelHeight = FontInfo.PixelHeight; + Font->Ascent = FontInfo.Ascent; + Font->Descent = FontInfo.Descent; + Font->Leading = FontInfo.Leading; + Font->MaxCharWidth = FontInfo.MaxCharWidth; + + Font->CodepointDictionarySize = (FontInfo.CodepointOnePastLast - FontInfo.CodepointStart); + Font->CodepointDictionaryCount = 0; + Font->CodepointKeys = PushArray(State->Permanent, char, Font->CodepointDictionarySize); + Font->CodepointValues = PushArray(State->Permanent, codepoint_bitmap, Font->CodepointDictionarySize); + + char CodepointValues[] = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-_=+{}[];':\",./<>?`~"; + for (s32 CodepointIdx = 0; //FontInfo.CodepointStart; + CodepointIdx < sizeof(CodepointValues) / sizeof(CodepointValues[0]); //FontInfo.CodepointOnePastLast; + CodepointIdx++) { - bitmap_font* Font = PushStruct(State->Permanent, bitmap_font); + char Codepoint = CodepointValues[CodepointIdx]; + u32 CodepointX, CodepointY; + GetNextCodepointOffset(Font, &CodepointX, &CodepointY); - Font->BitmapWidth = 512; - Font->BitmapHeight = 512; - Font->BitmapBytesPerPixel = 4; - Font->BitmapMemory = PushArray(State->Permanent, u8, Font->BitmapWidth * Font->BitmapHeight * Font->BitmapBytesPerPixel);; - Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel; + u32 CodepointW, CodepointH; + Context.PlatformDrawFontCodepoint( + Font->BitmapMemory, + Font->BitmapWidth, + Font->BitmapHeight, + CodepointX, CodepointY, + Codepoint, FontInfo, + &CodepointW, &CodepointH); - platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", 14); - Font->PixelHeight = FontInfo.PixelHeight; - Font->Ascent = FontInfo.Ascent; - Font->Descent = FontInfo.Descent; - Font->Leading = FontInfo.Leading; - Font->MaxCharWidth = FontInfo.MaxCharWidth; - - Font->CodepointDictionarySize = (FontInfo.CodepointOnePastLast - FontInfo.CodepointStart); - Font->CodepointDictionaryCount = 0; - Font->CodepointKeys = PushArray(State->Permanent, char, Font->CodepointDictionarySize); - Font->CodepointValues = PushArray(State->Permanent, codepoint_bitmap, Font->CodepointDictionarySize); - - for (s32 Codepoint = FontInfo.CodepointStart; - Codepoint < FontInfo.CodepointOnePastLast; - Codepoint++) - { - u32 CodepointX, CodepointY; - GetNextCodepointOffset(Font, &CodepointX, &CodepointY); - - u32 CodepointW, CodepointH; - Context.PlatformDrawFontCodepoint( - Font->BitmapMemory, - Font->BitmapWidth, - Font->BitmapHeight, - CodepointX, CodepointY, - (char)Codepoint, FontInfo, - &CodepointW, &CodepointH); - - AddCodepointToFont(Font, Codepoint, 0, 0, CodepointW, CodepointH, CodepointX, CodepointY); - } - - State->Interface.Font = Font; - State->Font = Font; - Font->BitmapTextureHandle = Context.PlatformGetGPUTextureHandle(Font->BitmapMemory, - Font->BitmapWidth, Font->BitmapHeight); + AddCodepointToFont(Font, Codepoint, 0, 0, CodepointW, CodepointH, CodepointX, CodepointY); } + + State->Interface.Font = Font; + State->Font = Font; + + Font->BitmapTextureHandle = Context.PlatformGetGPUTextureHandle(Font->BitmapMemory, + Font->BitmapWidth, Font->BitmapHeight); + } else {} } @@ -536,9 +537,9 @@ UPDATE_AND_RENDER(UpdateAndRender) /* patterns_update_list Temp_PatternsNeedUpdate = UpdateAllChannels(&State->ChannelSystem, - Context.DeltaTime, - State->Transient); - + Context.DeltaTime, + State->Transient); + UpdateAllPatterns(&Temp_PatternsNeedUpdate, &State->PatternSystem, State->LEDBufferList, Context.DeltaTime, State->Transient); */ @@ -908,6 +909,18 @@ UPDATE_AND_RENDER(UpdateAndRender) Context.DeltaTime, State->Camera, Input, State->Transient); } + render_texture FontTexture = {}; + FontTexture.Memory = State->Font->BitmapMemory; + FontTexture.Handle = State->Font->BitmapTextureHandle; + FontTexture.Width = State->Font->BitmapWidth; + FontTexture.Height = State->Font->BitmapHeight; + FontTexture.BytesPerPixel = State->Font->BitmapBytesPerPixel; + FontTexture.Stride = State->Font->BitmapStride; + + PushRenderTexture2D(RenderBuffer, v2{200, 200}, + v2{200 + (r32)FontTexture.Width, 200 + (r32)FontTexture.Height}, + v4{1, 1, 1, 1}, v2{0, 0}, v2{1, 1}, &FontTexture); + ClearArena(State->Transient); EndDebugFrame(GlobalDebugServices); } diff --git a/gs_font.h b/gs_font.h index 3d175af..7a8c3b4 100644 --- a/gs_font.h +++ b/gs_font.h @@ -5,6 +5,7 @@ struct codepoint_bitmap s32 XOffset, YOffset; s32 Width, Height; s32 BitmapX, BitmapY; + v2 UVMin, UVMax; }; struct bitmap_font @@ -49,13 +50,18 @@ GetNextCodepointOffset (bitmap_font* Font, u32* X, u32* Y) if (LastCodepointIndex >= 0) { codepoint_bitmap BitmapInfo = Font->CodepointValues[LastCodepointIndex]; - u32 TempX = BitmapInfo.XOffset + BitmapInfo.Width + GLYPH_SKIRT; - u32 TempY = BitmapInfo.YOffset; + + u32 TempX = BitmapInfo.BitmapX + BitmapInfo.Width + GLYPH_SKIRT; + u32 TempY = BitmapInfo.BitmapY; if (TempX + Font->MaxCharWidth > Font->BitmapWidth) { TempX = 0; - TempY -= BitmapInfo.Height + GLYPH_SKIRT; + TempY += BitmapInfo.Height + GLYPH_SKIRT; } + + Assert(TempX >= 0 && TempX < (u32)Font->BitmapWidth); + Assert(TempY >= 0 && TempY < (u32)Font->BitmapHeight); + *X = TempX; *Y = TempY; } @@ -78,7 +84,15 @@ AddCodepointToFont (bitmap_font* Font, char Codepoint, Font->CodepointDictionaryCount++; *Key = Codepoint; - *Value = {XOffset, YOffset, Width, Height, BitmapX, BitmapY}; + Value->XOffset = XOffset; + Value->YOffset = YOffset; + Value->Width = Width; + Value->Height = Height; + Value->BitmapX = BitmapX; + Value->BitmapY = BitmapY; + Value->UVMin = v2{(r32)BitmapX / (r32)Font->BitmapWidth, (r32)BitmapY / (r32)Font->BitmapHeight}; + Value->UVMax = + Value->UVMin + v2{(r32)Width / (r32)Font->BitmapWidth, (r32)Height / (r32)Font->BitmapHeight}; } internal s32 diff --git a/gs_platform.h b/gs_platform.h index 80538c0..97295db 100644 --- a/gs_platform.h +++ b/gs_platform.h @@ -212,7 +212,7 @@ SwapInputBuffers (input* Input) Input->New = Input->Old; Input->Old = NowOld; - for (s32 Key = 0; Key < KeyCode_Count; Key++) { Input->New->KeysDown[Key] = false; } + for (s32 Key = 0; Key < KeyCode_Count; Key++) { Input->New->KeysDown[Key] = Input->Old->KeysDown[Key]; } Input->New->StringInputUsed = 0; } diff --git a/gs_win32.cpp b/gs_win32.cpp index 8874683..ae29243 100644 --- a/gs_win32.cpp +++ b/gs_win32.cpp @@ -960,7 +960,22 @@ SubmitTexture (u8* Memory, s32 Width, s32 Height) { s32 TextureHandle = NextTextureHandle++; glBindTexture(GL_TEXTURE_2D, TextureHandle); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Memory); + glTexImage2D(GL_TEXTURE_2D, + 0, // mip map level + GL_RGBA8, + Width, + Height, + 0, // border + GL_RGBA, + GL_UNSIGNED_BYTE, + Memory); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + return TextureHandle; } diff --git a/gs_win32.h b/gs_win32.h index 347d2c8..4ec8bb3 100644 --- a/gs_win32.h +++ b/gs_win32.h @@ -7,10 +7,6 @@ struct platform_font_info s32 MaxCharWidth; s32 CodepointStart; s32 CodepointOnePastLast; - - HDC DrawingDC; - HBITMAP Bitmap; - HFONT Font; }; #define GS_WIN32_H diff --git a/interface.h b/interface.h index 752e3bf..3d52358 100644 --- a/interface.h +++ b/interface.h @@ -130,9 +130,11 @@ DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Fon r32 MaxX = MinX + (CodepointInfo.Width) * FontScale; r32 MaxY = MinY + (CodepointInfo.Height) * FontScale; - v2 MinUV = v2{(r32)CodepointInfo.BitmapX, (r32)CodepointInfo.BitmapY}; - v2 MaxUV = MinUV + v2{(r32)CodepointInfo.Width, (r32)CodepointInfo.Height}; - PushQuad2DOnBatch(&BatchConstructor, v2{MinX, MinY}, v2{MaxX, MinY}, v2{MaxX, MaxY}, v2{MinX, MaxY}, MinUV, MaxUV, Color); + PushQuad2DOnBatch(&BatchConstructor, + v2{MinX, MinY}, v2{MaxX, MinY}, + v2{MaxX, MaxY}, v2{MinX, MaxY}, + CodepointInfo.UVMin, CodepointInfo.UVMax, + Color); RegisterPosition.x += CodepointInfo.Width * FontScale; C++; diff --git a/win32_foldhaus.cpp b/win32_foldhaus.cpp index f20bded..5c04e2b 100644 --- a/win32_foldhaus.cpp +++ b/win32_foldhaus.cpp @@ -233,32 +233,37 @@ PLATFORM_CLOSE_SOCKET(Win32CloseSocket) closesocket(SocketValues[SocketIndex].Socket); } + +HDC FontDrawingDC; +HBITMAP FontBitmap; +HFONT CurrentFont; + GET_FONT_INFO(Win32GetFontInfo) { platform_font_info Result = {}; - Result.DrawingDC = CreateCompatibleDC(NULL); - SetBkColor(Result.DrawingDC, RGB(0, 0, 0)); - SetTextColor(Result.DrawingDC, RGB(255, 255, 255)); - Result.Bitmap = CreateCompatibleBitmap(NULL, PixelHeight * 2, PixelHeight * 2); - SelectObject(Result.DrawingDC, Result.Bitmap); + FontDrawingDC = CreateCompatibleDC(NULL); + SetBkColor(FontDrawingDC, RGB(0, 0, 0)); + SetTextColor(FontDrawingDC, RGB(255, 255, 255)); + FontBitmap = CreateCompatibleBitmap(FontDrawingDC, PixelHeight * 2, PixelHeight * 2); + HGDIOBJ SelectObjectResult = SelectObject(FontDrawingDC, FontBitmap); - Result.Font= CreateFont(PixelHeight, 0, 0, 0, - // TODO(Peter): Font weight, need a platform way to request others - FW_NORMAL, - FALSE, // Italic - FALSE, // Underling - FALSE, // Strikeout, - ANSI_CHARSET, - OUT_OUTLINE_PRECIS, - CLIP_DEFAULT_PRECIS, - PROOF_QUALITY, - FIXED_PITCH, - FontName); - SelectFont(Result.DrawingDC, Result.Font); + CurrentFont = CreateFont(PixelHeight, 0, 0, 0, + // TODO(Peter): Font weight, need a platform way to request others + FW_NORMAL, + FALSE, // Italic + FALSE, // Underling + FALSE, // Strikeout, + ANSI_CHARSET, + OUT_OUTLINE_PRECIS, + CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, + FIXED_PITCH, + FontName); + SelectFont(FontDrawingDC, CurrentFont); TEXTMETRIC WindowsFontMetrics = {}; - if (GetTextMetrics(Result.DrawingDC, &WindowsFontMetrics)) + if (GetTextMetrics(FontDrawingDC, &WindowsFontMetrics)) { Result.PixelHeight = WindowsFontMetrics.tmHeight; Result.Ascent = WindowsFontMetrics.tmAscent; @@ -272,9 +277,47 @@ GET_FONT_INFO(Win32GetFontInfo) return Result; } +/* +u8* DestBuffer, s32 DestBufferWidth, s32 DestBufferHeight, u32 XOffset, u32 YOffset, char Codepoint, platform_font_info FontInfo, u32* OutWidth, u32* OutHeight +*/ + DRAW_FONT_CODEPOINT(Win32DrawFontCodepoint) { - + SIZE CodepointSize = {}; + if (GetTextExtentPoint32(FontDrawingDC, &Codepoint, 1, &CodepointSize)) + { + *OutWidth = CodepointSize.cx; + *OutHeight = CodepointSize.cy; + + RECT TextRect = {}; + TextRect.left = 0; + TextRect.right = *OutWidth; + TextRect.top = 0; + TextRect.bottom = *OutHeight; + + int Error = DrawText(FontDrawingDC, &Codepoint, 1, &TextRect, DT_LEFT | DT_NOCLIP | DT_TOP); + + u8* Row = DestBuffer + (YOffset * (DestBufferWidth * 4)); + COLORREF PixelColor; + for (u32 Y = 0; Y < *OutHeight; Y++) + { + // TODO(Peter): * 4 b/c its 4 bytes per pixel. Switch to our bitmap_texture struct for clarity + // and fewer fields to this function + u8* Channel = (u8*)Row + (XOffset * 4); + for (u32 X = 0; X < *OutWidth; X++) + { + PixelColor = GetPixel(FontDrawingDC, X + TextRect.left, TextRect.bottom - Y); + Assert(PixelColor != CLR_INVALID); + u8 RValue = GetRValue(PixelColor); + *Channel++ = RValue; + *Channel++ = RValue; + *Channel++ = RValue; + *Channel++ = RValue; + } + Row += DestBufferWidth * 4; + } + + } } LRESULT CALLBACK