diff --git a/VisualC/demo/Demo.vcxproj.filters b/VisualC/demo/Demo.vcxproj.filters new file mode 100644 index 0000000..5c66dd8 --- /dev/null +++ b/VisualC/demo/Demo.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + {daa19be2-a3d5-40c0-aaff-83bf3bca32d9} + + + + + SourceFiles + + + \ No newline at end of file diff --git a/VisualC/demo/demo.vcxproj b/VisualC/demo/demo.vcxproj new file mode 100644 index 0000000..44985f1 --- /dev/null +++ b/VisualC/demo/demo.vcxproj @@ -0,0 +1,186 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {AF97B7A7-FA7A-40FC-8E16-AE23F5D136E9} + HelloWorld + Win32Proj + demo + + + + Application + v143 + Unicode + true + + + Application + v143 + Unicode + true + + + Application + v143 + Unicode + + + Application + v143 + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>16.0.29103.76 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + MinimumRecommendedRules.ruleset + + + + + true + MinimumRecommendedRules.ruleset + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + MinimumRecommendedRules.ruleset + + + + + false + MinimumRecommendedRules.ruleset + + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + $(SolutionDir)\.. + + + true + Windows + MachineX86 + $(CoreLibraryDependencies);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + $(SolutionDir)\.. + + + true + Windows + $(CoreLibraryDependencies);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + MaxSpeed + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + $(SolutionDir)\.. + + + true + Windows + true + true + MachineX86 + %(AdditionalLibraryDirectories) + + + + + MaxSpeed + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + $(SolutionDir)\.. + + + true + Windows + true + true + %(AdditionalLibraryDirectories) + + + + + + + + {65d14e02-ec19-49eb-8e43-f33b4b0f8286} + + + + + + \ No newline at end of file diff --git a/VisualC/demo/main.cpp b/VisualC/demo/main.cpp new file mode 100644 index 0000000..8e90c01 --- /dev/null +++ b/VisualC/demo/main.cpp @@ -0,0 +1,190 @@ +#ifndef UNICODE +#define UNICODE +#endif + +#include +#include +#include +#include + +#include + +#include "util/arg.h" + +LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +static HWND sHwnd; +static COLORREF redColor = RGB(255, 0, 0); +static COLORREF blueColor = RGB(0, 0, 255); +static COLORREF greenColor = RGB(0, 255, 0); +SFT sft; + +int width; +int height; + +void SetWindowHandle(HWND hwnd) +{ + sHwnd = hwnd; +} + +void SetPixel(int x, int y, COLORREF& color) +{ + if (sHwnd == NULL) + { + exit(0); + } + + HDC hdc = GetDC(sHwnd); + SetPixel(hdc, x, y, color); + ReleaseDC(sHwnd, hdc); + return; +} + +void RenderText() +{ + unsigned long cp; + SFT_Glyph gid, prevGid = 0; + SFT_Image image; + SFT_GMetrics mtx; + SFT_Kerning kerning; + + // Text start position in pixels + int xOffset = 10; + int yOffet = 100; + + // TODO: use stored text to dispaly + for (cp = 32; cp < 127; ++cp) + { + if (sft_lookup(&sft, cp, &gid) < 0) + continue; + if (sft_gmetrics(&sft, gid, &mtx) < 0) + continue; + + image.width = mtx.minWidth; + image.height = mtx.minHeight; + image.pixels = malloc((size_t)image.width * (size_t)image.height); + + sft_render(&sft, gid, image); + + sft_kerning(&sft, prevGid, gid, &kerning); + + xOffset += (int)(mtx.leftSideBearing + kerning.xShift); + + for (int h = 0; h < image.height; h++) + { + for (int w = 0; w < image.width; w++) + { + char pixelWeight = 255 - ((char*)image.pixels)[image.width * h + w]; + COLORREF grayColor = RGB(pixelWeight, pixelWeight, pixelWeight); + SetPixel(xOffset + w, yOffet + (int)mtx.yOffset + h, grayColor); + } + } + + xOffset += (int)mtx.advanceWidth; + + free(image.pixels); + + prevGid = gid; + } +} + +static void Die(const char* msg) +{ + fprintf(stderr, "%s\n", msg); + exit(1); +} + +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow) +{ + // Load and setup font + SFT_Font* font; + const char* filename; + double size; + + filename = "../../resources/FiraGO-Regular.ttf"; + size = 20.0; + + if (!(font = sft_loadfile(filename))) + Die("Can't load font file."); + + memset(&sft, 0, sizeof sft); + sft.font = font; + sft.xScale = size; + sft.yScale = size; + sft.flags = SFT_DOWNWARD_Y; + + // Register the window class. + const wchar_t CLASS_NAME[] = L"Sample Window Class"; + + WNDCLASS wc = { }; + + wc.lpfnWndProc = WindowProc; + wc.lpszClassName = CLASS_NAME; + wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + + RegisterClass(&wc); + + // Create the window. + HWND hwnd = CreateWindowEx( + 0, // Optional window styles. + CLASS_NAME, // Window class + L"Font rendering program", // Window text + WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME, // Window style, To prevent maximing ~WS_MAXIMIZEBOX AND window resizing ~WS_THICKFRAME + + // Size and position + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + + NULL, // Parent window + NULL, // Menu + hInstance, // Instance handle + NULL // Additional application data + ); + + if (hwnd == NULL) + { + return 0; + } + + ShowWindow(hwnd, nCmdShow); + UpdateWindow(hwnd); + + // TODO: use window size to render text inside window dimensions + RECT rect; + if (GetWindowRect(hwnd, &rect)) + { + width = rect.right - rect.left; + height = rect.bottom - rect.top; + } + + // Run the message loop. + MSG msg = { }; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + sft_freefont(font); + + return 0; +} + +LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_DESTROY: + PostQuitMessage(0); + return 0; + + case WM_PAINT: + SetWindowHandle(hwnd); + RenderText(); + + return 0; + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +