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");
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,8 +537,8 @@ 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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -7,10 +7,6 @@ struct platform_font_info
s32 MaxCharWidth;
s32 CodepointStart;
s32 CodepointOnePastLast;
HDC DrawingDC;
HBITMAP Bitmap;
HFONT Font;
};
#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 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++;

View File

@ -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