Switched over to rendering fonts from Windows directly (can now get rid of stb_truetype), and got textures rendering in OpenGL again

This commit is contained in:
Peter Slattery 2019-07-28 14:31:05 -07:00
parent 0f220c608d
commit 7a10f4066f
7 changed files with 162 additions and 79 deletions

View File

@ -414,54 +414,55 @@ INITIALIZE_APPLICATION(InitializeApplication)
platform_memory_result FontFile = Context.PlatformReadEntireFile("Anonymous Pro.ttf"); platform_memory_result FontFile = Context.PlatformReadEntireFile("Anonymous Pro.ttf");
if (FontFile.Size) if (FontFile.Size)
{ {
stbtt_fontinfo StbFont; bitmap_font* Font = PushStruct(State->Permanent, bitmap_font);
if (stbtt_InitFont(&StbFont, FontFile.Base, stbtt_GetFontOffsetForIndex(FontFile.Base, 0)))
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; u32 CodepointW, CodepointH;
Font->BitmapHeight = 512; Context.PlatformDrawFontCodepoint(
Font->BitmapBytesPerPixel = 4; Font->BitmapMemory,
Font->BitmapMemory = PushArray(State->Permanent, u8, Font->BitmapWidth * Font->BitmapHeight * Font->BitmapBytesPerPixel);; Font->BitmapWidth,
Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel; Font->BitmapHeight,
CodepointX, CodepointY,
Codepoint, FontInfo,
&CodepointW, &CodepointH);
platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", 14); AddCodepointToFont(Font, Codepoint, 0, 0, CodepointW, CodepointH, CodepointX, CodepointY);
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);
} }
State->Interface.Font = Font;
State->Font = Font;
Font->BitmapTextureHandle = Context.PlatformGetGPUTextureHandle(Font->BitmapMemory,
Font->BitmapWidth, Font->BitmapHeight);
} else {} } else {}
} }
@ -536,9 +537,9 @@ UPDATE_AND_RENDER(UpdateAndRender)
/* /*
patterns_update_list Temp_PatternsNeedUpdate = UpdateAllChannels(&State->ChannelSystem, patterns_update_list Temp_PatternsNeedUpdate = UpdateAllChannels(&State->ChannelSystem,
Context.DeltaTime, Context.DeltaTime,
State->Transient); State->Transient);
UpdateAllPatterns(&Temp_PatternsNeedUpdate, &State->PatternSystem, State->LEDBufferList, 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); 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); ClearArena(State->Transient);
EndDebugFrame(GlobalDebugServices); EndDebugFrame(GlobalDebugServices);
} }

View File

@ -5,6 +5,7 @@ struct codepoint_bitmap
s32 XOffset, YOffset; s32 XOffset, YOffset;
s32 Width, Height; s32 Width, Height;
s32 BitmapX, BitmapY; s32 BitmapX, BitmapY;
v2 UVMin, UVMax;
}; };
struct bitmap_font struct bitmap_font
@ -49,13 +50,18 @@ GetNextCodepointOffset (bitmap_font* Font, u32* X, u32* Y)
if (LastCodepointIndex >= 0) if (LastCodepointIndex >= 0)
{ {
codepoint_bitmap BitmapInfo = Font->CodepointValues[LastCodepointIndex]; 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) if (TempX + Font->MaxCharWidth > Font->BitmapWidth)
{ {
TempX = 0; 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; *X = TempX;
*Y = TempY; *Y = TempY;
} }
@ -78,7 +84,15 @@ AddCodepointToFont (bitmap_font* Font, char Codepoint,
Font->CodepointDictionaryCount++; Font->CodepointDictionaryCount++;
*Key = Codepoint; *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 internal s32

View File

@ -212,7 +212,7 @@ SwapInputBuffers (input* Input)
Input->New = Input->Old; Input->New = Input->Old;
Input->Old = NowOld; 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; Input->New->StringInputUsed = 0;
} }

View File

@ -960,7 +960,22 @@ SubmitTexture (u8* Memory, s32 Width, s32 Height)
{ {
s32 TextureHandle = NextTextureHandle++; s32 TextureHandle = NextTextureHandle++;
glBindTexture(GL_TEXTURE_2D, TextureHandle); 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; return TextureHandle;
} }

View File

@ -7,10 +7,6 @@ struct platform_font_info
s32 MaxCharWidth; s32 MaxCharWidth;
s32 CodepointStart; s32 CodepointStart;
s32 CodepointOnePastLast; s32 CodepointOnePastLast;
HDC DrawingDC;
HBITMAP Bitmap;
HFONT Font;
}; };
#define GS_WIN32_H #define GS_WIN32_H

View File

@ -130,9 +130,11 @@ DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Fon
r32 MaxX = MinX + (CodepointInfo.Width) * FontScale; r32 MaxX = MinX + (CodepointInfo.Width) * FontScale;
r32 MaxY = MinY + (CodepointInfo.Height) * FontScale; r32 MaxY = MinY + (CodepointInfo.Height) * FontScale;
v2 MinUV = v2{(r32)CodepointInfo.BitmapX, (r32)CodepointInfo.BitmapY}; PushQuad2DOnBatch(&BatchConstructor,
v2 MaxUV = MinUV + v2{(r32)CodepointInfo.Width, (r32)CodepointInfo.Height}; v2{MinX, MinY}, v2{MaxX, MinY},
PushQuad2DOnBatch(&BatchConstructor, v2{MinX, MinY}, v2{MaxX, MinY}, v2{MaxX, MaxY}, v2{MinX, MaxY}, MinUV, MaxUV, Color); v2{MaxX, MaxY}, v2{MinX, MaxY},
CodepointInfo.UVMin, CodepointInfo.UVMax,
Color);
RegisterPosition.x += CodepointInfo.Width * FontScale; RegisterPosition.x += CodepointInfo.Width * FontScale;
C++; C++;

View File

@ -233,32 +233,37 @@ PLATFORM_CLOSE_SOCKET(Win32CloseSocket)
closesocket(SocketValues[SocketIndex].Socket); closesocket(SocketValues[SocketIndex].Socket);
} }
HDC FontDrawingDC;
HBITMAP FontBitmap;
HFONT CurrentFont;
GET_FONT_INFO(Win32GetFontInfo) GET_FONT_INFO(Win32GetFontInfo)
{ {
platform_font_info Result = {}; platform_font_info Result = {};
Result.DrawingDC = CreateCompatibleDC(NULL); FontDrawingDC = CreateCompatibleDC(NULL);
SetBkColor(Result.DrawingDC, RGB(0, 0, 0)); SetBkColor(FontDrawingDC, RGB(0, 0, 0));
SetTextColor(Result.DrawingDC, RGB(255, 255, 255)); SetTextColor(FontDrawingDC, RGB(255, 255, 255));
Result.Bitmap = CreateCompatibleBitmap(NULL, PixelHeight * 2, PixelHeight * 2); FontBitmap = CreateCompatibleBitmap(FontDrawingDC, PixelHeight * 2, PixelHeight * 2);
SelectObject(Result.DrawingDC, Result.Bitmap); HGDIOBJ SelectObjectResult = SelectObject(FontDrawingDC, FontBitmap);
Result.Font= CreateFont(PixelHeight, 0, 0, 0, CurrentFont = CreateFont(PixelHeight, 0, 0, 0,
// TODO(Peter): Font weight, need a platform way to request others // TODO(Peter): Font weight, need a platform way to request others
FW_NORMAL, FW_NORMAL,
FALSE, // Italic FALSE, // Italic
FALSE, // Underling FALSE, // Underling
FALSE, // Strikeout, FALSE, // Strikeout,
ANSI_CHARSET, ANSI_CHARSET,
OUT_OUTLINE_PRECIS, OUT_OUTLINE_PRECIS,
CLIP_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
PROOF_QUALITY, PROOF_QUALITY,
FIXED_PITCH, FIXED_PITCH,
FontName); FontName);
SelectFont(Result.DrawingDC, Result.Font); SelectFont(FontDrawingDC, CurrentFont);
TEXTMETRIC WindowsFontMetrics = {}; TEXTMETRIC WindowsFontMetrics = {};
if (GetTextMetrics(Result.DrawingDC, &WindowsFontMetrics)) if (GetTextMetrics(FontDrawingDC, &WindowsFontMetrics))
{ {
Result.PixelHeight = WindowsFontMetrics.tmHeight; Result.PixelHeight = WindowsFontMetrics.tmHeight;
Result.Ascent = WindowsFontMetrics.tmAscent; Result.Ascent = WindowsFontMetrics.tmAscent;
@ -272,9 +277,47 @@ GET_FONT_INFO(Win32GetFontInfo)
return Result; 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) 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 LRESULT CALLBACK