Nuklear/demo/gdip/nuklear_gdip.h
Dmitry Hrabrov d6ac1e4d3f nk_gdip_fill_rect coordinates fix
Fix incorrect button drawing (wrong stroke, empty spaces in stroke line near the corners). Since there are quarters of circle in the angles then lines must be moved to R, not to D.
2016-12-29 21:34:58 +03:00

1007 lines
29 KiB
C

/*
* Nuklear - v1.17 - public domain
* no warrenty implied; use at your own risk.
* authored from 2015-2016 by Micha Mettke
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_GDIP_H_
#define NK_GDIP_H_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/* font */
typedef struct GdipFont GdipFont;
NK_API GdipFont* nk_gdipfont_create(const char *name, int size);
NK_API void nk_gdipfont_del(GdipFont *font);
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);
#endif
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_GDIP_IMPLEMENTATION
#include <stdlib.h>
#include <malloc.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);
struct GdipFont
{
struct nk_user_font nk;
GpFont* handle;
};
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 + r, y, x + w - r, y);
GdipDrawArcI(gdip.memory, gdip.pen, x + w - d, y, d, d, 270, 90);
GdipDrawLineI(gdip.memory, gdip.pen, x + w, y + r, x + w, y + h - r);
GdipDrawArcI(gdip.memory, gdip.pen, x + w - d, y + h - d, d, d, 0, 90);
GdipDrawLineI(gdip.memory, gdip.pen, x, y + r, x, y + h - r);
GdipDrawArcI(gdip.memory, gdip.pen, x, y + h - d, d, d, 90, 90);
GdipDrawLineI(gdip.memory, gdip.pen, x + r, y + h, x + w - r, 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 = (WCHAR*)_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, font->handle, &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)
{
GdipFont *font = (GdipFont*)calloc(1, sizeof(GdipFont));
GpFontFamily *family;
int wsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
WCHAR* wname = (WCHAR*)_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->handle);
GdipDeleteFontFamily(family);
return font;
}
static float
nk_gdipfont_get_text_width(nk_handle handle, float height, const char *text, int len)
{
GdipFont *font = (GdipFont *)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 = (WCHAR*)_alloca(wsize * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
GdipMeasureString(gdip.memory, wstr, wsize, font->handle, &layout, gdip.format, &bbox, NULL, NULL);
return bbox.Width;
}
void
nk_gdipfont_del(GdipFont *font)
{
if(!font) return;
GdipDeleteFont(font->handle);
free(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 = (HGLOBAL)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 = (char*)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 = (HGLOBAL)GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t));
if (!mem) {
CloseClipboard();
return;
}
wstr = (wchar_t*)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 = &gdipfont->nk;
font->userdata = nk_handle_ptr(gdipfont);
GdipGetFontSize(gdipfont->handle, &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);
nk_input_key(&gdip.ctx, NK_KEY_SCROLL_START, down);
return 1;
case VK_END:
nk_input_key(&gdip.ctx, NK_KEY_TEXT_END, down);
nk_input_key(&gdip.ctx, NK_KEY_SCROLL_END, down);
return 1;
case VK_NEXT:
nk_input_key(&gdip.ctx, NK_KEY_SCROLL_DOWN, down);
return 1;
case VK_PRIOR:
nk_input_key(&gdip.ctx, NK_KEY_SCROLL_UP, 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);
}
#endif