Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add new advanced text api (D2D1 + DWrite back-end only) #17

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ target_link_libraries("draw-simple" "windrawlib")
add_executable("draw-string" WIN32 "draw-string.c")
target_link_libraries("draw-string" "windrawlib")

add_executable("draw-text" WIN32 "draw-text.c")
target_link_libraries("draw-text" "windrawlib")

add_executable("draw-styled" WIN32 "draw-styled.c")
target_link_libraries("draw-styled" "windrawlib")

Expand Down
85 changes: 62 additions & 23 deletions examples/draw-cached.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@


static HWND hwndMain = NULL;

/* The cached canvas (if not NULL).
*
* Note that if the caching is enabled, it remembers all its painted contents
* across all the WM_PAINT messages so as long as we do not need to paint it
* with different contents, we may just call wdBeginPaint() + wdEndPaint() to
* make it blit into the window.
*
* If only some sub-region needs to be painted differently, then only that
* part of it needs to be repainted.
*/
static WD_HCANVAS hCachedCanvas = NULL;


Expand All @@ -21,32 +32,44 @@ MainWinPaintToCanvas(WD_HCANVAS hCanvas, BOOL* pCanCache)
int i;

wdBeginPaint(hCanvas);
wdClear(hCanvas, WD_RGB(255,255,255));
hBrush = wdCreateSolidBrush(hCanvas, 0);

for(i = 0; i < 3; i++) {
float x = 10.0f + i * 20.0f;
float y = 10.0f + i * 20.0f;

wdSetSolidBrushColor(hBrush, fillColors[i]);
wdFillRect(hCanvas, hBrush, x, y, x + 100.0f, y + 100.0f);
/* This very simple example never changes what it paints; i.e. if we
* already cached the completely painted canvas, we may skip the paint
* code altogether.
*
* In real applications, we would have to paint only parts of the canvas
* which needs to be painted differently since the last time; e.g. to
* reflect a change in the application's state.
*/
if(hCanvas != hCachedCanvas) {
wdClear(hCanvas, WD_RGB(255,255,255));
hBrush = wdCreateSolidBrush(hCanvas, 0);

for(i = 0; i < 3; i++) {
float x = 10.0f + i * 20.0f;
float y = 10.0f + i * 20.0f;

wdSetSolidBrushColor(hBrush, fillColors[i]);
wdFillRect(hCanvas, hBrush, x, y, x + 100.0f, y + 100.0f);

wdSetSolidBrushColor(hBrush, drawColors[i]);
wdDrawRect(hCanvas, hBrush, x, y, x + 100.0f, y + 100.0f, 3.0f);
}

wdSetSolidBrushColor(hBrush, drawColors[i]);
wdDrawRect(hCanvas, hBrush, x, y, x + 100.0f, y + 100.0f, 3.0f);
}
for(i = 0; i < 3; i++) {
float x = 250.0f + i * 20.0f;
float y = 60.0f + i * 20.0f;

for(i = 0; i < 3; i++) {
float x = 250.0f + i * 20.0f;
float y = 60.0f + i * 20.0f;
wdSetSolidBrushColor(hBrush, fillColors[i]);
wdFillCircle(hCanvas, hBrush, x, y, 55.0f);

wdSetSolidBrushColor(hBrush, fillColors[i]);
wdFillCircle(hCanvas, hBrush, x, y, 55.0f);
wdSetSolidBrushColor(hBrush, drawColors[i]);
wdDrawCircle(hCanvas, hBrush, x, y, 55.0f, 3.0f);
}

wdSetSolidBrushColor(hBrush, drawColors[i]);
wdDrawCircle(hCanvas, hBrush, x, y, 55.0f, 3.0f);
wdDestroyBrush(hBrush);
}

wdDestroyBrush(hBrush);
*pCanCache = wdEndPaint(hCanvas);
}

Expand All @@ -68,13 +91,15 @@ MainWinPaint(void)

MainWinPaintToCanvas(hCanvas, &bCanCache);

/* Cache the completely painted canvas if we are allowed to. */
if(bCanCache) {
hCachedCanvas = hCanvas;
} else {
wdDestroyCanvas(hCanvas);
hCachedCanvas = NULL;
}
}
EndPaint(hwndMain, &ps);
}

/* Main window procedure */
Expand All @@ -87,14 +112,28 @@ MainWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
break;

case WM_SIZE:
/* If we are caching the canvas for WM_PAINT, we need to resize it. */
if(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED) {
if(hCachedCanvas != NULL)
wdResizeCanvas(hCachedCanvas, LOWORD(lParam), HIWORD(lParam));
if(hCachedCanvas != NULL) {
/* We could call wdResizeCanvas() here. But that would
* loose the painted stuff on the canvas anyway, and save
* us "only" the reallocation of the canvas.
*
* For the sake of simplicity, we just destroy it all. */
wdDestroyCanvas(hCachedCanvas);
hCachedCanvas = NULL;
}
InvalidateRect(hwndMain, NULL, FALSE);
}
return 0;

case WM_LBUTTONDOWN:
InvalidateRect(hwnd, NULL, FALSE);
return 0;

case WM_DISPLAYCHANGE:
/* Some relevant graphics settings has been changed and we cannot
* use the cached canvas as it can use incompatible pixel format,
* so discard it. */
if(hCachedCanvas != NULL) {
wdDestroyCanvas(hCachedCanvas);
hCachedCanvas = NULL;
Expand Down Expand Up @@ -130,7 +169,7 @@ _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nC
/* Create main window */
hwndMain = CreateWindow(
_T("main_window"), _T("LibWinDraw Example"),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 550, 350,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 150, 350,
NULL, NULL, hInstance, NULL
);
SendMessage(hwndMain, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT),
Expand Down
180 changes: 180 additions & 0 deletions examples/draw-text.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@

#include <tchar.h>
#include <windows.h>

#include <wdl.h>


static HWND hwndMain = NULL;



static WCHAR pszTitle[] = L"Lorem Ipsum";
static WCHAR pszText[] =
L"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam dui "
L"sem, fermentum vitae, sagittis id, malesuada in, quam. Morbi imperdiet, "
L"mauris ac auctor dictum, nisl ligula egestas nulla, et sollicitudin "
L"sem purus in lacus. Fusce aliquam vestibulum ipsum. Excepteur sint "
L"occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
L"mollit anim id est laborum. Morbi imperdiet, mauris ac auctor dictum, "
L"nisl ligula egestas nulla, et sollicitudin sem purus in lacus. "
L"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui "
L"officia deserunt mollit anim id est laborum. Et harum quidem rerum "
L"facilis est et expedita distinctio. Ut enim ad minim veniam, quis "
L"nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo "
L"consequat. Donec vitae arcu. Vivamus ac leo pretium faucibus.\n"
L"\n"
L"In dapibus augue non sapien. Aenean id metus id velit ullamcorper "
L"pulvinar. Sed convallis magna eu sem. Maecenas sollicitudin. Nulla "
L"turpis magna, cursus sit amet, suscipit a, interdum id, felis. Nulla "
L"non lectus sed nisl molestie malesuada. Aliquam ante. Integer lacinia. "
L"Nullam sapien sem, ornare ac, nonummy non, lobortis a enim. Integer "
L"lacinia. Mauris metus. Fusce suscipit libero eget elit.\n"
L"\n"
L"Nam quis nulla. Fusce nibh. Nulla pulvinar eleifend sem. Curabitur "
L"sagittis hendrerit ante. Cras pede libero, dapibus nec, pretium sit "
L"amet, tempor quis. Nulla non lectus sed nisl molestie malesuada. "
L"Maecenas sollicitudin. Duis condimentum augue id magna semper rutrum. "
L"Proin mattis lacinia justo. Ut enim ad minima veniam, quis nostrum "
L"exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid "
L"ex ea commodi consequatur? Integer in sapien. Nemo enim ipsam "
L"voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia "
L"consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. "
L"Fusce aliquam vestibulum ipsum. In enim a arcu imperdiet malesuada. "
L"Maecenas ipsum velit, consectetuer eu lobortis ut, dictum at dui.\n"
L"\n"
L"Duis viverra diam non justo. Class aptent taciti sociosqu ad litora "
L"torquent per conubia nostra, per inceptos hymenaeos. Mauris metus. "
L"Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil "
L"impedit quo minus plus id quod maxime placeat facere possimus, omnis "
L"voluptas assumenda est, omnis dolor repellendus. Class aptent taciti "
L"sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos.";

static void
PaintToCanvas(WD_HCANVAS hCanvas)
{
RECT client;
WD_HBRUSH hBrush;
WD_HFONT hFont;
WD_RECT rect;
WD_HTEXT hTitle;
WD_HTEXT hText;
WD_FONTMETRICS fontMetrics;
WD_TEXTMETRICS titleMetrics;

GetClientRect(hwndMain, &client);
rect.x0 = 10.0f;
rect.x1 = client.right - 10.0f;

wdBeginPaint(hCanvas);
wdClear(hCanvas, WD_RGB(255,255,255));
hBrush = wdCreateSolidBrush(hCanvas, WD_RGB(0,0,0));
hFont = wdCreateFontWithGdiHandle(GetStockObject(DEFAULT_GUI_FONT));
wdFontMetrics(hFont, &fontMetrics);

/* Create and paint title. */
rect.y0 = 10.0f;
rect.y1 = client.bottom - 10.0f;
hTitle = wdCreateText(hFont, &rect, pszTitle, -1, 0);
wdSetTextFontSize(hTitle, 0, wcslen(pszTitle), 1.66f * fontMetrics.fEmHeight);
wdSetTextFontSize(hTitle, 0, 1, 1.85f * fontMetrics.fEmHeight);
wdSetTextFontSize(hTitle, 6, 1, 1.85f * fontMetrics.fEmHeight);
wdTextMetrics(hTitle, &titleMetrics);
wdDrawText(hCanvas, hTitle, hBrush, rect.x0, rect.y0, 0);

/* Create body text, customize some its parts, and paint it. */
rect.y0 = 20.0f + titleMetrics.fHeight;
rect.y1 = client.bottom - 10.0f;
hText = wdCreateText(hFont, &rect, pszText, -1, 0);
wdSetTextFontWeight(hText, 103, 12, FW_BOLD);
wdSetTextFontStyle(hText, 932, 68, WD_TEXTSTYLE_ITALIC);
wdSetTextStrikethrough(hText, 2159, 5, TRUE);
wdSetTextUnderline(hText, 2165, 4, TRUE);
wdDrawText(hCanvas, hText, hBrush, rect.x0, rect.y0, 0);

wdDestroyText(hTitle);
wdDestroyText(hText);
wdDestroyBrush(hBrush);
wdDestroyFont(hFont);
wdEndPaint(hCanvas);
}

/* Main window procedure */
static LRESULT CALLBACK
MainWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg) {
case WM_PAINT:
{
PAINTSTRUCT ps;
WD_HCANVAS hCanvas;

BeginPaint(hwndMain, &ps);
hCanvas = wdCreateCanvasWithPaintStruct(hwndMain, &ps, 0);
PaintToCanvas(hCanvas);
wdDestroyCanvas(hCanvas);
EndPaint(hwndMain, &ps);
return 0;
}

case WM_PRINTCLIENT:
{
HDC dc = (HDC) wParam;
WD_HCANVAS hCanvas;

hCanvas = wdCreateCanvasWithHDC(dc, NULL, 0);
PaintToCanvas(hCanvas);
wdDestroyCanvas(hCanvas);
return 0;
}

case WM_DESTROY:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hwnd, uMsg, wParam, lParam);
}


int APIENTRY
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
WNDCLASS wc = { 0 };
MSG msg;

wdInitialize(WD_INIT_TEXTAPI);

/* Register main window class */
wc.lpfnWndProc = MainWinProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszClassName = _T("main_window");
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);

/* Create main window */
hwndMain = CreateWindow(
_T("main_window"), _T("LibWinDraw Example: Draw Text"),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 650,
NULL, NULL, hInstance, NULL
);
SendMessage(hwndMain, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT),
MAKELPARAM(TRUE, 0));
ShowWindow(hwndMain, nCmdShow);

/* Message loop */
while(GetMessage(&msg, NULL, 0, 0)) {
if(IsDialogMessage(hwndMain, &msg))
continue;

TranslateMessage(&msg);
DispatchMessage(&msg);
}

wdTerminate(WD_INIT_TEXTAPI);

/* Return exit code of WM_QUIT */
return (int)msg.wParam;
}
Loading