Merge pull request #112 from mmozeiko/gdip

Demo with Win32 GDI+ rendering
This commit is contained in:
Micha Mettke 2016-04-26 07:21:27 -07:00
commit 4de258c256
4 changed files with 1108 additions and 0 deletions

5
demo/gdip/build.bat Normal file
View File

@ -0,0 +1,5 @@
@echo off
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
cl /nologo /W3 /WX /O2 /fp:fast /Gm- /Fedemo.exe main.c user32.lib gdiplus.lib /link /incremental:no

127
demo/gdip/main.c Normal file
View File

@ -0,0 +1,127 @@
/* nuklear - v1.00 - public domain */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <string.h>
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#include "nuklear_gdip.h"
#include "nuklear_gdip.c"
static LRESULT CALLBACK
WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
if (nk_gdip_handle_event(wnd, msg, wparam, lparam))
return 0;
return DefWindowProcW(wnd, msg, wparam, lparam);
}
int main(void)
{
GdipFont* font;
struct nk_context *ctx;
WNDCLASSW wc;
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
DWORD style = WS_OVERLAPPEDWINDOW;
DWORD exstyle = WS_EX_APPWINDOW;
HWND wnd;
int running = 1;
int needs_refresh = 1;
/* Win32 */
memset(&wc, 0, sizeof(wc));
wc.lpfnWndProc = WindowProc;
wc.hInstance = GetModuleHandleW(0);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"NuklearWindowClass";
RegisterClassW(&wc);
AdjustWindowRectEx(&rect, style, FALSE, exstyle);
wnd = CreateWindowExW(exstyle, wc.lpszClassName, L"Nuklear Demo",
style | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
rect.right - rect.left, rect.bottom - rect.top,
NULL, NULL, wc.hInstance, NULL);
/* GUI */
ctx = nk_gdip_init(wnd, WINDOW_WIDTH, WINDOW_HEIGHT);
font = nk_gdipfont_create("Arial", 12);
nk_gdip_set_font(font);
while (running)
{
MSG msg;
/* Input */
nk_input_begin(ctx);
if (needs_refresh == 0)
{
if (GetMessageW(&msg, NULL, 0, 0) <= 0)
{
running = 0;
}
else
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
needs_refresh = 1;
}
else
{
needs_refresh = 0;
}
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
running = 0;
TranslateMessage(&msg);
DispatchMessageW(&msg);
needs_refresh = 1;
}
nk_input_end(ctx);
/* GUI */
{struct nk_panel layout;
if (nk_begin(ctx, &layout, "Demo", nk_rect(50, 50, 200, 200),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
enum {EASY, HARD};
static int op = EASY;
static int property = 20;
nk_layout_row_static(ctx, 30, 80, 1);
if (nk_button_label(ctx, "button", NK_BUTTON_DEFAULT))
fprintf(stdout, "button pressed\n");
nk_layout_row_dynamic(ctx, 30, 2);
if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
nk_layout_row_dynamic(ctx, 22, 1);
nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
}
nk_end(ctx);}
if (nk_window_is_closed(ctx, "Demo")) break;
/* Draw */
nk_gdip_render(NK_ANTI_ALIASING_ON, nk_rgb(30,30,30));
}
nk_gdipfont_del(font);
nk_gdip_shutdown();
UnregisterClassW(wc.lpszClassName, wc.hInstance);
return 0;
}

958
demo/gdip/nuklear_gdip.c Normal file
View File

@ -0,0 +1,958 @@
#include <stdlib.h>
#include <malloc.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define NK_IMPLEMENTATION
#include "nuklear_gdip.h"
#include "../../nuklear.h"
/* manually declare everything GDI+ needs, because
GDI+ headers are not usable from C */
#define WINGDIPAPI __stdcall
#define GDIPCONST const
typedef struct GpGraphics GpGraphics;
typedef struct GpImage GpImage;
typedef struct GpPen GpPen;
typedef struct GpBrush GpBrush;
typedef struct GpStringFormat GpStringFormat;
typedef struct GpFont GpFont;
typedef struct GpFontFamily GpFontFamily;
typedef struct GpFontCollection GpFontCollection;
typedef GpImage GpBitmap;
typedef GpBrush GpSolidFill;
typedef int Status;
typedef Status GpStatus;
typedef float REAL;
typedef DWORD ARGB;
typedef POINT GpPoint;
typedef enum {
TextRenderingHintSystemDefault = 0,
TextRenderingHintSingleBitPerPixelGridFit = 1,
TextRenderingHintSingleBitPerPixel = 2,
TextRenderingHintAntiAliasGridFit = 3,
TextRenderingHintAntiAlias = 4,
TextRenderingHintClearTypeGridFit = 5
} TextRenderingHint;
typedef enum {
StringFormatFlagsDirectionRightToLeft = 0x00000001,
StringFormatFlagsDirectionVertical = 0x00000002,
StringFormatFlagsNoFitBlackBox = 0x00000004,
StringFormatFlagsDisplayFormatControl = 0x00000020,
StringFormatFlagsNoFontFallback = 0x00000400,
StringFormatFlagsMeasureTrailingSpaces = 0x00000800,
StringFormatFlagsNoWrap = 0x00001000,
StringFormatFlagsLineLimit = 0x00002000,
StringFormatFlagsNoClip = 0x00004000
} StringFormatFlags;
typedef enum
{
QualityModeInvalid = -1,
QualityModeDefault = 0,
QualityModeLow = 1,
QualityModeHigh = 2
} QualityMode;
typedef enum
{
SmoothingModeInvalid = QualityModeInvalid,
SmoothingModeDefault = QualityModeDefault,
SmoothingModeHighSpeed = QualityModeLow,
SmoothingModeHighQuality = QualityModeHigh,
SmoothingModeNone,
SmoothingModeAntiAlias,
SmoothingModeAntiAlias8x4 = SmoothingModeAntiAlias,
SmoothingModeAntiAlias8x8
} SmoothingMode;
typedef enum
{
FontStyleRegular = 0,
FontStyleBold = 1,
FontStyleItalic = 2,
FontStyleBoldItalic = 3,
FontStyleUnderline = 4,
FontStyleStrikeout = 8
} FontStyle;
typedef enum {
FillModeAlternate,
FillModeWinding
} FillMode;
typedef enum {
CombineModeReplace,
CombineModeIntersect,
CombineModeUnion,
CombineModeXor,
CombineModeExclude,
CombineModeComplement
} CombineMode;
typedef enum {
UnitWorld,
UnitDisplay,
UnitPixel,
UnitPoint,
UnitInch,
UnitDocument,
UnitMillimeter
} Unit;
typedef struct {
FLOAT X;
FLOAT Y;
FLOAT Width;
FLOAT Height;
} RectF;
typedef enum {
DebugEventLevelFatal,
DebugEventLevelWarning
} DebugEventLevel;
typedef VOID (WINAPI *DebugEventProc)(DebugEventLevel level, CHAR *message);
typedef struct {
UINT32 GdiplusVersion;
DebugEventProc DebugEventCallback;
BOOL SuppressBackgroundThread;
BOOL SuppressExternalCodecs;
} GdiplusStartupInput;
typedef Status (WINAPI *NotificationHookProc)(OUT ULONG_PTR *token);
typedef VOID (WINAPI *NotificationUnhookProc)(ULONG_PTR token);
typedef struct {
NotificationHookProc NotificationHook;
NotificationUnhookProc NotificationUnhook;
} GdiplusStartupOutput;
/* startup & shutdown */
Status WINAPI GdiplusStartup(
OUT ULONG_PTR *token,
const GdiplusStartupInput *input,
OUT GdiplusStartupOutput *output);
VOID WINAPI GdiplusShutdown(ULONG_PTR token);
/* image */
GpStatus WINGDIPAPI
GdipCreateBitmapFromGraphics(INT width,
INT height,
GpGraphics* target,
GpBitmap** bitmap);
GpStatus WINGDIPAPI
GdipDisposeImage(GpImage *image);
GpStatus WINGDIPAPI
GdipGetImageGraphicsContext(GpImage *image, GpGraphics **graphics);
/* pen */
GpStatus WINGDIPAPI
GdipCreatePen1(ARGB color, REAL width, Unit unit, GpPen **pen);
GpStatus WINGDIPAPI
GdipDeletePen(GpPen *pen);
GpStatus WINGDIPAPI
GdipSetPenWidth(GpPen *pen, REAL width);
GpStatus WINGDIPAPI
GdipSetPenColor(GpPen *pen, ARGB argb);
/* brush */
GpStatus WINGDIPAPI
GdipCreateSolidFill(ARGB color, GpSolidFill **brush);
GpStatus WINGDIPAPI
GdipDeleteBrush(GpBrush *brush);
GpStatus WINGDIPAPI
GdipSetSolidFillColor(GpSolidFill *brush, ARGB color);
/* font */
GpStatus WINGDIPAPI
GdipCreateFont(
GDIPCONST GpFontFamily *fontFamily,
REAL emSize,
INT style,
Unit unit,
GpFont **font
);
GpStatus WINGDIPAPI
GdipDeleteFont(GpFont* font);
GpStatus WINGDIPAPI
GdipGetFontSize(GpFont *font, REAL *size);
GpStatus WINGDIPAPI
GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
GpFontCollection *fontCollection,
GpFontFamily **fontFamily);
GpStatus WINGDIPAPI
GdipDeleteFontFamily(GpFontFamily *fontFamily);
GpStatus WINGDIPAPI
GdipStringFormatGetGenericTypographic(GpStringFormat **format);
GpStatus WINGDIPAPI
GdipSetStringFormatFlags(GpStringFormat *format, INT flags);
GpStatus WINGDIPAPI
GdipDeleteStringFormat(GpStringFormat *format);
/* graphics */
GpStatus WINGDIPAPI
GdipCreateFromHWND(HWND hwnd, GpGraphics **graphics);
GpStatus WINGDIPAPI
GdipCreateFromHDC(HDC hdc, GpGraphics **graphics);
GpStatus WINGDIPAPI
GdipDeleteGraphics(GpGraphics *graphics);
GpStatus WINGDIPAPI
GdipSetSmoothingMode(GpGraphics *graphics, SmoothingMode smoothingMode);
GpStatus WINGDIPAPI
GdipSetClipRectI(GpGraphics *graphics, INT x, INT y,
INT width, INT height, CombineMode combineMode);
GpStatus WINGDIPAPI
GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1, INT y1,
INT x2, INT y2);
GpStatus WINGDIPAPI
GdipDrawArcI(GpGraphics *graphics, GpPen *pen, INT x, INT y,
INT width, INT height, REAL startAngle, REAL sweepAngle);
GpStatus WINGDIPAPI
GdipFillPieI(GpGraphics *graphics, GpBrush *brush, INT x, INT y,
INT width, INT height, REAL startAngle, REAL sweepAngle);
GpStatus WINGDIPAPI
GdipDrawRectangleI(GpGraphics *graphics, GpPen *pen, INT x, INT y,
INT width, INT height);
GpStatus WINGDIPAPI
GdipFillRectangleI(GpGraphics *graphics, GpBrush *brush, INT x, INT y,
INT width, INT height);
GpStatus WINGDIPAPI
GdipFillPolygonI(GpGraphics *graphics, GpBrush *brush,
GDIPCONST GpPoint *points, INT count, FillMode fillMode);
GpStatus WINGDIPAPI
GdipDrawPolygonI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points,
INT count);
GpStatus WINGDIPAPI
GdipFillEllipseI(GpGraphics *graphics, GpBrush *brush, INT x, INT y,
INT width, INT height);
GpStatus WINGDIPAPI
GdipDrawEllipseI(GpGraphics *graphics, GpPen *pen, INT x, INT y,
INT width, INT height);
GpStatus WINGDIPAPI
GdipDrawBezierI(GpGraphics *graphics, GpPen *pen, INT x1, INT y1,
INT x2, INT y2, INT x3, INT y3, INT x4, INT y4);
GpStatus WINGDIPAPI
GdipDrawString(
GpGraphics *graphics,
GDIPCONST WCHAR *string,
INT length,
GDIPCONST GpFont *font,
GDIPCONST RectF *layoutRect,
GDIPCONST GpStringFormat *stringFormat,
GDIPCONST GpBrush *brush
);
GpStatus WINGDIPAPI
GdipGraphicsClear(GpGraphics *graphics, ARGB color);
GpStatus WINGDIPAPI
GdipDrawImageI(GpGraphics *graphics, GpImage *image, INT x, INT y);
GpStatus WINGDIPAPI
GdipMeasureString(
GpGraphics *graphics,
GDIPCONST WCHAR *string,
INT length,
GDIPCONST GpFont *font,
GDIPCONST RectF *layoutRect,
GDIPCONST GpStringFormat *stringFormat,
RectF *boundingBox,
INT *codepointsFitted,
INT *linesFilled
);
GpStatus WINGDIPAPI
GdipSetTextRenderingHint(GpGraphics *graphics, TextRenderingHint mode);
static struct {
ULONG_PTR token;
GpGraphics *window;
GpGraphics *memory;
GpImage *bitmap;
GpPen *pen;
GpSolidFill *brush;
GpStringFormat *format;
struct nk_context ctx;
} gdip;
static ARGB convert_color(struct nk_color c)
{
return (c.a << 24) | (c.r << 16) | (c.g << 8) | c.b;
}
static void
nk_gdip_scissor(float x, float y, float w, float h)
{
GdipSetClipRectI(gdip.memory, (INT)x, (INT)y, (INT)(w + 1), (INT)(h + 1), CombineModeReplace);
}
static void
nk_gdip_stroke_line(short x0, short y0, short x1,
short y1, unsigned int line_thickness, struct nk_color col)
{
GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
GdipSetPenColor(gdip.pen, convert_color(col));
GdipDrawLineI(gdip.memory, gdip.pen, x0, y0, x1, y1);
}
static void
nk_gdip_stroke_rect(short x, short y, unsigned short w,
unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
{
GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
GdipSetPenColor(gdip.pen, convert_color(col));
if (r == 0) {
GdipDrawRectangleI(gdip.memory, gdip.pen, x, y, w, h);
} else {
INT d = 2 * r;
GdipDrawArcI(gdip.memory, gdip.pen, x, y, d, d, 180, 90);
GdipDrawLineI(gdip.memory, gdip.pen, x + d, y, x + w - d, y);
GdipDrawArcI(gdip.memory, gdip.pen, x + w - d, y, d, d, 270, 90);
GdipDrawLineI(gdip.memory, gdip.pen, x + w, y + d, x + w, y + h - d);
GdipDrawArcI(gdip.memory, gdip.pen, x + w - d, y + h - d, d, d, 0, 90);
GdipDrawLineI(gdip.memory, gdip.pen, x, y + d, x + w, y + h - d);
GdipDrawArcI(gdip.memory, gdip.pen, x, y + h - d, d, d, 90, 90);
GdipDrawLineI(gdip.memory, gdip.pen, x + d, y + h, x + w - d, y + h);
}
}
static void
nk_gdip_fill_rect(short x, short y, unsigned short w,
unsigned short h, unsigned short r, struct nk_color col)
{
GdipSetSolidFillColor(gdip.brush, convert_color(col));
if (r == 0) {
GdipFillRectangleI(gdip.memory, gdip.brush, x, y, w, h);
} else {
INT d = 2 * r;
GdipFillRectangleI(gdip.memory, gdip.brush, x + r, y, w - d, h);
GdipFillRectangleI(gdip.memory, gdip.brush, x, y + r, w, h - d);
GdipFillPieI(gdip.memory, gdip.brush, x, y, d, d, 180, 90);
GdipFillPieI(gdip.memory, gdip.brush, x + w - d, y, d, d, 270, 90);
GdipFillPieI(gdip.memory, gdip.brush, x + w - d, y + h - d, d, d, 0, 90);
GdipFillPieI(gdip.memory, gdip.brush, x, y + h - d, d, d, 90, 90);
}
}
static void
nk_gdip_fill_triangle(short x0, short y0, short x1,
short y1, short x2, short y2, struct nk_color col)
{
POINT points[] = {
{ x0, y0 },
{ x1, y1 },
{ x2, y2 },
};
GdipSetSolidFillColor(gdip.brush, convert_color(col));
GdipFillPolygonI(gdip.memory, gdip.brush, points, 3, FillModeAlternate);
}
static void
nk_gdip_stroke_triangle(short x0, short y0, short x1,
short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
{
POINT points[] = {
{ x0, y0 },
{ x1, y1 },
{ x2, y2 },
{ x0, y0 },
};
GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
GdipSetPenColor(gdip.pen, convert_color(col));
GdipDrawPolygonI(gdip.memory, gdip.pen, points, 4);
}
static void
nk_gdip_fill_polygon(const struct nk_vec2i *pnts, int count, struct nk_color col)
{
int i = 0;
#define MAX_POINTS 64
POINT points[MAX_POINTS];
GdipSetSolidFillColor(gdip.brush, convert_color(col));
for (i = 0; i < count && i < MAX_POINTS; ++i) {
points[i].x = pnts[i].x;
points[i].y = pnts[i].y;
}
GdipFillPolygonI(gdip.memory, gdip.brush, points, i, FillModeAlternate);
#undef MAX_POINTS
}
static void
nk_gdip_stroke_polygon(const struct nk_vec2i *pnts, int count,
unsigned short line_thickness, struct nk_color col)
{
GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
GdipSetPenColor(gdip.pen, convert_color(col));
if (count > 0) {
int i;
for (i = 1; i < count; ++i)
GdipDrawLineI(gdip.memory, gdip.pen, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
GdipDrawLineI(gdip.memory, gdip.pen, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y);
}
}
static void
nk_gdip_stroke_polyline(const struct nk_vec2i *pnts,
int count, unsigned short line_thickness, struct nk_color col)
{
GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
GdipSetPenColor(gdip.pen, convert_color(col));
if (count > 0) {
int i;
for (i = 1; i < count; ++i)
GdipDrawLineI(gdip.memory, gdip.pen, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
}
}
static void
nk_gdip_fill_circle(short x, short y, unsigned short w,
unsigned short h, struct nk_color col)
{
GdipSetSolidFillColor(gdip.brush, convert_color(col));
GdipFillEllipseI(gdip.memory, gdip.brush, x, y, w, h);
}
static void
nk_gdip_stroke_circle(short x, short y, unsigned short w,
unsigned short h, unsigned short line_thickness, struct nk_color col)
{
GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
GdipSetPenColor(gdip.pen, convert_color(col));
GdipDrawEllipseI(gdip.memory, gdip.pen, x, y, w, h);
}
static void
nk_gdip_stroke_curve(struct nk_vec2i p1,
struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4,
unsigned short line_thickness, struct nk_color col)
{
GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
GdipSetPenColor(gdip.pen, convert_color(col));
GdipDrawBezierI(gdip.memory, gdip.pen, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
}
static void
nk_gdip_draw_text(short x, short y, unsigned short w, unsigned short h,
const char *text, int len, GdipFont *font, struct nk_color cbg, struct nk_color cfg)
{
int wsize;
WCHAR* wstr;
RectF layout = { (FLOAT)x, (FLOAT)y, (FLOAT)w, (FLOAT)h };
if(!text || !font || !len) return;
wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
wstr = _alloca(wsize * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
GdipSetSolidFillColor(gdip.brush, convert_color(cbg));
GdipFillRectangleI(gdip.memory, gdip.brush, x, y, w, h);
GdipSetSolidFillColor(gdip.brush, convert_color(cfg));
GdipDrawString(gdip.memory, wstr, wsize, (GpFont *)font, &layout, gdip.format, gdip.brush);
}
static void
nk_gdip_clear(struct nk_color col)
{
GdipGraphicsClear(gdip.memory, convert_color(col));
}
static void
nk_gdip_blit(GpGraphics *graphics)
{
GdipDrawImageI(graphics, gdip.bitmap, 0, 0);
}
GdipFont*
nk_gdipfont_create(const char *name, int size)
{
GpFont* font;
GpFontFamily *family;
int wsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
WCHAR* wname = _alloca((wsize + 1) * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, wsize);
wname[wsize] = 0;
GdipCreateFontFamilyFromName(wname, NULL, &family);
GdipCreateFont(family, (REAL)size, FontStyleRegular, UnitPixel, &font);
GdipDeleteFontFamily(family);
return (GdipFont *)font;
}
static float
nk_gdipfont_get_text_width(nk_handle handle, float height, const char *text, int len)
{
GpFont *font = (GpFont *)handle.ptr;
RectF layout = { 0.0f, 0.0f, 65536.0f, 65536.0f };
RectF bbox;
int wsize;
WCHAR* wstr;
if (!font || !text)
return 0;
(void)height;
wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
wstr = _alloca(wsize * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
GdipMeasureString(gdip.memory, wstr, wsize, font, &layout, gdip.format, &bbox, NULL, NULL);
return bbox.Width;
}
void
nk_gdipfont_del(GdipFont *font)
{
if(!font) return;
GdipDeleteFont((GpFont *)font);
}
static void
nk_gdip_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
{
HGLOBAL mem;
SIZE_T size;
LPCWSTR wstr;
int utf8size;
char* utf8;
(void)usr;
if (!IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
return;
mem = GetClipboardData(CF_UNICODETEXT);
if (!mem) {
CloseClipboard();
return;
}
size = GlobalSize(mem) - 1;
if (!size) {
CloseClipboard();
return;
}
wstr = (LPCWSTR)GlobalLock(mem);
if (!wstr) {
CloseClipboard();
return;
}
utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), NULL, 0, NULL, NULL);
if (!utf8size) {
GlobalUnlock(mem);
CloseClipboard();
return;
}
utf8 = malloc(utf8size);
if (!utf8) {
GlobalUnlock(mem);
CloseClipboard();
return;
}
WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), utf8, utf8size, NULL, NULL);
nk_textedit_paste(edit, utf8, utf8size);
free(utf8);
GlobalUnlock(mem);
CloseClipboard();
}
static void
nk_gdip_clipbard_copy(nk_handle usr, const char *text, int len)
{
HGLOBAL mem;
wchar_t* wstr;
int wsize;
(void)usr;
if (!OpenClipboard(NULL))
return;
wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
if (!wsize) {
CloseClipboard();
return;
}
mem = GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t));
if (!mem) {
CloseClipboard();
return;
}
wstr = GlobalLock(mem);
if (!wstr) {
GlobalFree(mem);
CloseClipboard();
return;
}
MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
wstr[wsize] = 0;
GlobalUnlock(mem);
if (!SetClipboardData(CF_UNICODETEXT, mem))
GlobalFree(mem);
CloseClipboard();
}
NK_API struct nk_context*
nk_gdip_init(HWND hwnd, unsigned int width, unsigned int height)
{
GdiplusStartupInput startup = { 1, NULL, FALSE, TRUE };
GdiplusStartup(&gdip.token, &startup, NULL);
GdipCreateFromHWND(hwnd, &gdip.window);
GdipCreateBitmapFromGraphics(width, height, gdip.window, &gdip.bitmap);
GdipGetImageGraphicsContext(gdip.bitmap, &gdip.memory);
GdipCreatePen1(0, 1.0f, UnitPixel, &gdip.pen);
GdipCreateSolidFill(0, &gdip.brush);
GdipStringFormatGetGenericTypographic(&gdip.format);
GdipSetStringFormatFlags(gdip.format, StringFormatFlagsNoFitBlackBox |
StringFormatFlagsMeasureTrailingSpaces | StringFormatFlagsNoWrap |
StringFormatFlagsNoClip);
nk_init_default(&gdip.ctx, NULL);
gdip.ctx.clip.copy = nk_gdip_clipbard_copy;
gdip.ctx.clip.paste = nk_gdip_clipbard_paste;
return &gdip.ctx;
}
NK_API void
nk_gdip_set_font(GdipFont *gdipfont)
{
struct nk_user_font font;
font.userdata = nk_handle_ptr(gdipfont);
GdipGetFontSize((GpFont *)gdipfont, &font.height);
font.width = nk_gdipfont_get_text_width;
nk_style_set_font(&gdip.ctx, &font);
}
NK_API int
nk_gdip_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_SIZE:
if (gdip.window)
{
unsigned int width = LOWORD(lparam);
unsigned int height = HIWORD(lparam);
GdipDeleteGraphics(gdip.window);
GdipDeleteGraphics(gdip.memory);
GdipDisposeImage(gdip.bitmap);
GdipCreateFromHWND(wnd, &gdip.window);
GdipCreateBitmapFromGraphics(width, height, gdip.window, &gdip.bitmap);
GdipGetImageGraphicsContext(gdip.bitmap, &gdip.memory);
}
break;
case WM_PAINT:
{
PAINTSTRUCT paint;
HDC dc = BeginPaint(wnd, &paint);
GpGraphics *graphics;
GdipCreateFromHDC(dc, &graphics);
nk_gdip_blit(graphics);
GdipDeleteGraphics(graphics);
EndPaint(wnd, &paint);
return 1;
}
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
{
int down = (lparam >> 31) & 1;
int ctrl = GetKeyState(VK_CONTROL) & (1 << 15);
switch (wparam)
{
case VK_SHIFT:
case VK_LSHIFT:
case VK_RSHIFT:
nk_input_key(&gdip.ctx, NK_KEY_SHIFT, down);
return 1;
case VK_DELETE:
nk_input_key(&gdip.ctx, NK_KEY_DEL, down);
return 1;
case VK_RETURN:
nk_input_key(&gdip.ctx, NK_KEY_ENTER, down);
return 1;
case VK_TAB:
nk_input_key(&gdip.ctx, NK_KEY_TAB, down);
return 1;
case VK_LEFT:
if (ctrl)
nk_input_key(&gdip.ctx, NK_KEY_TEXT_WORD_LEFT, down);
else
nk_input_key(&gdip.ctx, NK_KEY_LEFT, down);
return 1;
case VK_RIGHT:
if (ctrl)
nk_input_key(&gdip.ctx, NK_KEY_TEXT_WORD_RIGHT, down);
else
nk_input_key(&gdip.ctx, NK_KEY_RIGHT, down);
return 1;
case VK_BACK:
nk_input_key(&gdip.ctx, NK_KEY_BACKSPACE, down);
return 1;
case VK_HOME:
nk_input_key(&gdip.ctx, NK_KEY_TEXT_START, down);
return 1;
case VK_END:
nk_input_key(&gdip.ctx, NK_KEY_TEXT_END, down);
return 1;
case 'C':
if (ctrl) {
nk_input_key(&gdip.ctx, NK_KEY_COPY, down);
return 1;
}
break;
case 'V':
if (ctrl) {
nk_input_key(&gdip.ctx, NK_KEY_PASTE, down);
return 1;
}
break;
case 'X':
if (ctrl) {
nk_input_key(&gdip.ctx, NK_KEY_CUT, down);
return 1;
}
break;
case 'Z':
if (ctrl) {
nk_input_key(&gdip.ctx, NK_KEY_TEXT_UNDO, down);
return 1;
}
break;
case 'R':
if (ctrl) {
nk_input_key(&gdip.ctx, NK_KEY_TEXT_REDO, down);
return 1;
}
break;
}
return 0;
}
case WM_CHAR:
if (wparam >= 32)
{
nk_input_unicode(&gdip.ctx, (nk_rune)wparam);
return 1;
}
break;
case WM_LBUTTONDOWN:
nk_input_button(&gdip.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_LBUTTONUP:
nk_input_button(&gdip.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_RBUTTONDOWN:
nk_input_button(&gdip.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_RBUTTONUP:
nk_input_button(&gdip.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_MBUTTONDOWN:
nk_input_button(&gdip.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_MBUTTONUP:
nk_input_button(&gdip.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_MOUSEWHEEL:
nk_input_scroll(&gdip.ctx, (float)(short)HIWORD(wparam) / WHEEL_DELTA);
return 1;
case WM_MOUSEMOVE:
nk_input_motion(&gdip.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam));
return 1;
}
return 0;
}
NK_API void
nk_gdip_shutdown(void)
{
GdipDeleteGraphics(gdip.window);
GdipDeleteGraphics(gdip.memory);
GdipDisposeImage(gdip.bitmap);
GdipDeletePen(gdip.pen);
GdipDeleteBrush(gdip.brush);
GdipDeleteStringFormat(gdip.format);
GdiplusShutdown(gdip.token);
nk_free(&gdip.ctx);
}
NK_API void
nk_gdip_render(enum nk_anti_aliasing AA, struct nk_color clear)
{
const struct nk_command *cmd;
GdipSetTextRenderingHint(gdip.memory, AA != NK_ANTI_ALIASING_OFF ?
TextRenderingHintClearTypeGridFit : TextRenderingHintSingleBitPerPixelGridFit);
GdipSetSmoothingMode(gdip.memory, AA != NK_ANTI_ALIASING_OFF ?
SmoothingModeHighQuality : SmoothingModeNone);
nk_gdip_clear(clear);
nk_foreach(cmd, &gdip.ctx)
{
switch (cmd->type) {
case NK_COMMAND_NOP: break;
case NK_COMMAND_SCISSOR: {
const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
nk_gdip_scissor(s->x, s->y, s->w, s->h);
} break;
case NK_COMMAND_LINE: {
const struct nk_command_line *l = (const struct nk_command_line *)cmd;
nk_gdip_stroke_line(l->begin.x, l->begin.y, l->end.x,
l->end.y, l->line_thickness, l->color);
} break;
case NK_COMMAND_RECT: {
const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
nk_gdip_stroke_rect(r->x, r->y, r->w, r->h,
(unsigned short)r->rounding, r->line_thickness, r->color);
} break;
case NK_COMMAND_RECT_FILLED: {
const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
nk_gdip_fill_rect(r->x, r->y, r->w, r->h,
(unsigned short)r->rounding, r->color);
} break;
case NK_COMMAND_CIRCLE: {
const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
nk_gdip_stroke_circle(c->x, c->y, c->w, c->h, c->line_thickness, c->color);
} break;
case NK_COMMAND_CIRCLE_FILLED: {
const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
nk_gdip_fill_circle(c->x, c->y, c->w, c->h, c->color);
} break;
case NK_COMMAND_TRIANGLE: {
const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
nk_gdip_stroke_triangle(t->a.x, t->a.y, t->b.x, t->b.y,
t->c.x, t->c.y, t->line_thickness, t->color);
} break;
case NK_COMMAND_TRIANGLE_FILLED: {
const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
nk_gdip_fill_triangle(t->a.x, t->a.y, t->b.x, t->b.y,
t->c.x, t->c.y, t->color);
} break;
case NK_COMMAND_POLYGON: {
const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd;
nk_gdip_stroke_polygon(p->points, p->point_count, p->line_thickness,p->color);
} break;
case NK_COMMAND_POLYGON_FILLED: {
const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
nk_gdip_fill_polygon(p->points, p->point_count, p->color);
} break;
case NK_COMMAND_POLYLINE: {
const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
nk_gdip_stroke_polyline(p->points, p->point_count, p->line_thickness, p->color);
} break;
case NK_COMMAND_TEXT: {
const struct nk_command_text *t = (const struct nk_command_text*)cmd;
nk_gdip_draw_text(t->x, t->y, t->w, t->h,
(const char*)t->string, t->length,
(GdipFont*)t->font->userdata.ptr,
t->background, t->foreground);
} break;
case NK_COMMAND_CURVE: {
const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
nk_gdip_stroke_curve(q->begin, q->ctrl[0], q->ctrl[1],
q->end, q->line_thickness, q->color);
} break;
case NK_COMMAND_RECT_MULTI_COLOR:
case NK_COMMAND_IMAGE:
case NK_COMMAND_ARC:
case NK_COMMAND_ARC_FILLED:
default: break;
}
}
nk_gdip_blit(gdip.window);
nk_clear(&gdip.ctx);
}

18
demo/gdip/nuklear_gdip.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef NK_GDI_H_
#define NK_GDI_H_
#include "../../nuklear.h"
typedef struct GdipFont GdipFont;
NK_API struct nk_context* nk_gdip_init(HWND hwnd, unsigned int width, unsigned int height);
NK_API void nk_gdip_set_font(GdipFont *font);
NK_API int nk_gdip_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
NK_API void nk_gdip_render(enum nk_anti_aliasing AA, struct nk_color clear);
NK_API void nk_gdip_shutdown(void);
/* font */
NK_API GdipFont* nk_gdipfont_create(const char *name, int size);
NK_API void nk_gdipfont_del(GdipFont *font);
#endif