mirror of
https://github.com/CamHenlin/MessagesForMacintosh.git
synced 2024-11-24 22:32:19 +00:00
1525 lines
48 KiB
C
1525 lines
48 KiB
C
/*
|
||
* Nuklear - 1.32.0 - public domain
|
||
* no warranty implied; use at your own risk.
|
||
* based on allegro5 version authored from 2015-2016 by Micha Mettke
|
||
* quickdraw version camhenlin 2021-2022
|
||
*
|
||
* v1 intent:
|
||
* - only default system font support
|
||
* - no graphics/images support - quickdraw has very limited support for this
|
||
*/
|
||
/*
|
||
* ==============================================================
|
||
*
|
||
* API
|
||
*
|
||
* ===============================================================
|
||
*/
|
||
#ifndef NK_QUICKDRAW_H_
|
||
#define NK_QUICKDRAW_H_
|
||
#include <MacTypes.h>
|
||
#include <Types.h>
|
||
#include <Quickdraw.h>
|
||
#include <Scrap.h>
|
||
#include <Serial.h>
|
||
#include "SerialHelper.h"
|
||
#include <stdlib.h>
|
||
|
||
#define ENABLED_DOUBLE_BUFFERING
|
||
#define COMMAND_CACHING
|
||
#include "nuklear.h"
|
||
// #define NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
// #define DRAW_BLIT_LOCATION
|
||
|
||
Boolean lastInputWasBackspace;
|
||
|
||
typedef struct NkQuickDrawFont NkQuickDrawFont;
|
||
NK_API struct nk_context* nk_quickdraw_init(unsigned int width, unsigned int height);
|
||
NK_API int nk_quickdraw_handle_event(EventRecord *event, struct nk_context *nuklear_context);
|
||
NK_API void nk_quickdraw_shutdown(void);
|
||
NK_API void nk_quickdraw_render(WindowPtr window, struct nk_context *ctx);
|
||
|
||
NK_API struct nk_image* nk_quickdraw_create_image(const char* file_name);
|
||
NK_API void nk_quickdraw_del_image(struct nk_image* image);
|
||
NK_API NkQuickDrawFont* nk_quickdraw_font_create_from_file();
|
||
|
||
#endif
|
||
|
||
/*
|
||
* ==============================================================
|
||
*
|
||
* IMPLEMENTATION
|
||
*
|
||
* ===============================================================
|
||
*/
|
||
#define MAX_MEMORY_IN_KB 6
|
||
#ifdef NK_QUICKDRAW_IMPLEMENTATION
|
||
#ifndef NK_QUICKDRAW_TEXT_MAX
|
||
#define NK_QUICKDRAW_TEXT_MAX 256
|
||
#endif
|
||
#endif
|
||
struct NkQuickDrawFont {
|
||
struct nk_user_font nk;
|
||
char *font;
|
||
};
|
||
|
||
int lastEventWasKey = 0;
|
||
void *last;
|
||
void *buf;
|
||
|
||
// constant keyboard mappings for convenenience
|
||
// See Inside Macintosh: Text pg A-7, A-8
|
||
int homeKey = (int)0x01;
|
||
int enterKey = (int)0x03;
|
||
int endKey = (int)0x04;
|
||
int helpKey = (int)0x05;
|
||
int backspaceKey = (int)0x08;
|
||
int deleteKey = (int)0x7F;
|
||
int tabKey = (int)0x09;
|
||
int pageUpKey = (int)0x0B;
|
||
int pageDownKey = (int)0x0C;
|
||
int returnKey = (int)0x0D;
|
||
int rightArrowKey = (int)0x1D;
|
||
int leftArrowKey = (int)0x1C;
|
||
int downArrowKey = (int)0x1F;
|
||
int upArrowKey = (int)0x1E;
|
||
int eitherShiftKey = (int)0x0F;
|
||
int escapeKey = (int)0x1B;
|
||
|
||
// #define NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
// #def#ifdef NK_QUICKDRAW_EVENTS_DEBUGG
|
||
|
||
typedef struct {
|
||
Ptr Address;
|
||
long RowBytes;
|
||
GrafPtr bits;
|
||
Rect bounds;
|
||
BitMap BWBits;
|
||
GrafPort BWPort;
|
||
Handle OrigBits;
|
||
} ShockBitmap;
|
||
|
||
void NewShockBitmap(ShockBitmap *theMap, short width, short height) {
|
||
|
||
theMap->bits = 0L;
|
||
SetRect(&theMap->bounds, 0, 0, width, height);
|
||
|
||
theMap->BWBits.bounds = theMap->bounds;
|
||
theMap->BWBits.rowBytes = ((width+15) >> 4)<<1; // round to even
|
||
theMap->BWBits.baseAddr = NewPtr(((long) height * (long) theMap->BWBits.rowBytes));
|
||
|
||
theMap->BWBits.baseAddr = StripAddress(theMap->BWBits.baseAddr);
|
||
|
||
OpenPort(&theMap->BWPort);
|
||
SetPort(&theMap->BWPort);
|
||
SetPortBits(&theMap->BWBits);
|
||
|
||
SetRectRgn(theMap->BWPort.visRgn, theMap->bounds.left, theMap->bounds.top, theMap->bounds.right, theMap->bounds.bottom);
|
||
SetRectRgn(theMap->BWPort.clipRgn, theMap->bounds.left, theMap->bounds.top, theMap->bounds.right, theMap->bounds.bottom);
|
||
EraseRect(&theMap->bounds);
|
||
|
||
theMap->Address = theMap->BWBits.baseAddr;
|
||
theMap->RowBytes = (long) theMap->BWBits.rowBytes;
|
||
theMap->bits = (GrafPtr) &theMap->BWPort;
|
||
}
|
||
|
||
ShockBitmap gMainOffScreen;
|
||
|
||
// bezier code is from http://preserve.mactech.com/articles/mactech/Vol.05/05.01/BezierCurve/index.html
|
||
// as it is not built in to quickdraw like other "modern" graphics environments
|
||
/*
|
||
The greater the number of curve segments, the smoother the curve,
|
||
and the longer it takes to generate and draw. The number below was pulled
|
||
out of a hat, and seems to work o.k.
|
||
*/
|
||
#define SEGMENTS 16
|
||
|
||
static Fixed weight1[SEGMENTS + 1];
|
||
static Fixed weight2[SEGMENTS + 1];
|
||
|
||
#define w1(s) weight1[s]
|
||
#define w2(s) weight2[s]
|
||
#define w3(s) weight2[SEGMENTS - s]
|
||
#define w4(s) weight1[SEGMENTS - s]
|
||
|
||
/*
|
||
* SetupBezier -- one-time setup code.
|
||
* Compute the weights for the Bezier function.
|
||
* For the those concerned with space, the tables can be precomputed.
|
||
Setup is done here for purposes of illustration.
|
||
*/
|
||
void setupBezier() {
|
||
|
||
Fixed t, zero, one;
|
||
int s;
|
||
|
||
zero = FixRatio(0, 1);
|
||
one = FixRatio(1, 1);
|
||
weight1[0] = one;
|
||
weight2[0] = zero;
|
||
|
||
for (s = 1; s < SEGMENTS; ++s) {
|
||
|
||
t = FixRatio(s, SEGMENTS);
|
||
weight1[s] = FixMul(one - t, FixMul(one - t, one - t));
|
||
weight2[s] = 3 * FixMul(t, FixMul(t - one, t - one));
|
||
}
|
||
|
||
weight1[SEGMENTS] = zero;
|
||
weight2[SEGMENTS] = zero;
|
||
}
|
||
|
||
/*
|
||
* computeSegments -- compute segments for the Bezier curve
|
||
* Compute the segments along the curve.
|
||
* The curve touches the endpoints, so don’t bother to compute them.
|
||
*/
|
||
static void computeSegments(p1, p2, p3, p4, segment) Point p1, p2, p3, p4; Point segment[]; {
|
||
|
||
int s;
|
||
|
||
segment[0] = p1;
|
||
|
||
for (s = 1; s < SEGMENTS; ++s) {
|
||
|
||
segment[s].v = FixRound(w1(s) * p1.v + w2(s) * p2.v + w3(s) * p3.v + w4(s) * p4.v);
|
||
segment[s].h = FixRound(w1(s) * p1.h + w2(s) * p2.h + w3(s) * p3.h + w4(s) * p4.h);
|
||
}
|
||
|
||
segment[SEGMENTS] = p4;
|
||
}
|
||
|
||
/*
|
||
* BezierCurve -- Draw a Bezier Curve
|
||
* Draw a curve with the given endpoints (p1, p4), and the given
|
||
* control points (p2, p3).
|
||
* Note that we make no assumptions about pen or pen mode.
|
||
*/
|
||
void BezierCurve(p1, p2, p3, p4) Point p1, p2, p3, p4; {
|
||
|
||
int s;
|
||
Point segment[SEGMENTS + 1];
|
||
|
||
computeSegments(p1, p2, p3, p4, segment);
|
||
MoveTo(segment[0].h, segment[0].v);
|
||
|
||
for (s = 1 ; s <= SEGMENTS ; ++s) {
|
||
|
||
if (segment[s].h != segment[s - 1].h || segment[s].v != segment[s - 1].v) {
|
||
|
||
LineTo(segment[s].h, segment[s].v);
|
||
}
|
||
}
|
||
}
|
||
|
||
// ex usage:
|
||
// Point control[4] = {{144,72}, {72,144}, {216,144}, {144,216}};
|
||
// BezierCurve(c[0], c[1], c[2], c[3]);
|
||
|
||
static struct nk_quickdraw {
|
||
unsigned int width;
|
||
unsigned int height;
|
||
struct nk_context nuklear_context;
|
||
struct nk_buffer cmds;
|
||
} quickdraw;
|
||
|
||
// TODO: maybe V2 - skipping images for first pass
|
||
NK_API struct nk_image* nk_quickdraw_create_image(const char* file_name) {
|
||
|
||
// TODO: just read the file to a char, we can draw it using quickdraw
|
||
// b&w bitmaps are pretty easy to draw...
|
||
// for us to do this, we need to figure out the format, then figure out if we can make it in to a quickdraw rect
|
||
// and set the buffer to the image handle pointer in the image struct
|
||
// i assume this gets consumed elsewhere in the code, thinking NK_COMMAND_IMAGE
|
||
char* bitmap = ""; //al_load_bitmap(file_name); // TODO: https://www.allegro.cc/manual/5/al_load_bitmap, loads file to in-memory buffer understood by allegro
|
||
|
||
if (bitmap == NULL) {
|
||
|
||
fprintf(stdout, "Unable to load image file: %s\n", file_name);
|
||
return NULL;
|
||
}
|
||
|
||
struct nk_image *image = (struct nk_image*)calloc(1, sizeof(struct nk_image));
|
||
image->handle.ptr = bitmap;
|
||
image->w = 0; // al_get_bitmap_width(bitmap); // TODO: this can be retrieved from a bmp file
|
||
image->h = 0; // al_get_bitmap_height(bitmap); // TODO: this can be retrieved from a bmp file
|
||
|
||
return image;
|
||
}
|
||
|
||
// TODO: maybe V2 - skipping images for first pass
|
||
NK_API void nk_quickdraw_del_image(struct nk_image* image) {
|
||
|
||
if (!image) {
|
||
|
||
return;
|
||
}
|
||
|
||
// al_destroy_bitmap(image->handle.ptr); // TODO: https://www.allegro.cc/manual/5/al_destroy_bitmap
|
||
//this is just de-allocating the memory from a loaded bitmap
|
||
|
||
free(image);
|
||
}
|
||
|
||
// NOTE: you will need to generate this yourself if you want to add additional font support!
|
||
short widthFor12ptFont[128] = {
|
||
0,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
8,
|
||
10,
|
||
10,
|
||
10,
|
||
0,
|
||
10,
|
||
10,
|
||
10,
|
||
11,
|
||
11,
|
||
9,
|
||
11,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
10,
|
||
4,
|
||
6,
|
||
7,
|
||
10,
|
||
7,
|
||
11,
|
||
10,
|
||
3,
|
||
5,
|
||
5,
|
||
7,
|
||
7,
|
||
4,
|
||
7,
|
||
4,
|
||
7,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
4,
|
||
4,
|
||
6,
|
||
8,
|
||
6,
|
||
8,
|
||
11,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
7,
|
||
7,
|
||
8,
|
||
8,
|
||
6,
|
||
7,
|
||
9,
|
||
7,
|
||
12,
|
||
9,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
7,
|
||
6,
|
||
8,
|
||
8,
|
||
12,
|
||
8,
|
||
8,
|
||
8,
|
||
5,
|
||
7,
|
||
5,
|
||
8,
|
||
8,
|
||
6,
|
||
8,
|
||
8,
|
||
7,
|
||
8,
|
||
8,
|
||
6,
|
||
8,
|
||
8,
|
||
4,
|
||
6,
|
||
8,
|
||
4,
|
||
12,
|
||
8,
|
||
8,
|
||
8,
|
||
8,
|
||
6,
|
||
7,
|
||
6,
|
||
8,
|
||
8,
|
||
12,
|
||
8,
|
||
8,
|
||
8,
|
||
5,
|
||
5,
|
||
5,
|
||
8,
|
||
8
|
||
};
|
||
|
||
// doing this in a "fast" way by using a precomputed table for a 12pt font
|
||
static short nk_quickdraw_font_get_text_width(nk_handle handle, short height, const char *text, short len) {
|
||
|
||
// this is going to produce a lot of logging and not a lot of value:
|
||
// #ifdef DEBUG_FUNCTION_CALLS
|
||
// writeSerialPortDebug(boutRefNum, "DEBUG_FUNCTION_CALLS: nk_quickdraw_font_get_text_width");
|
||
// #endif
|
||
|
||
if (!text || len == 0) {
|
||
|
||
return 0;
|
||
}
|
||
|
||
short width = 0;
|
||
|
||
for (short i = 0; i < len; i++) {
|
||
|
||
width += widthFor12ptFont[(int)text[i]];
|
||
}
|
||
|
||
return width;
|
||
}
|
||
|
||
static int _get_text_width(const char *text, int len) {
|
||
|
||
#ifdef DEBUG_FUNCTION_CALLS
|
||
writeSerialPortDebug(boutRefNum, "DEBUG_FUNCTION_CALLS: _get_text_width");
|
||
#endif
|
||
|
||
if (!text || len == 0) {
|
||
|
||
return 0;
|
||
}
|
||
|
||
int width = 0;
|
||
|
||
for (int i = 0; i < len; i++) {
|
||
|
||
width += widthFor12ptFont[(int)text[i]];
|
||
}
|
||
|
||
return width;
|
||
}
|
||
|
||
/* Flags are identical to al_load_font() flags argument */
|
||
NK_API NkQuickDrawFont* nk_quickdraw_font_create_from_file() {
|
||
|
||
NkQuickDrawFont *font = (NkQuickDrawFont*)calloc(1, sizeof(NkQuickDrawFont));
|
||
|
||
font->font = calloc(1, 1024);
|
||
if (font->font == NULL) {
|
||
fprintf(stdout, "Unable to load font file\n");
|
||
return NULL;
|
||
}
|
||
font->nk.userdata = nk_handle_ptr(font);
|
||
font->nk.height = (int)12;
|
||
font->nk.width = nk_quickdraw_font_get_text_width;
|
||
return font;
|
||
}
|
||
|
||
// used for bounds checking
|
||
int mostLeft = WINDOW_WIDTH;
|
||
int mostBottom = 1;
|
||
int mostTop = WINDOW_HEIGHT;
|
||
int mostRight = 1;
|
||
|
||
void updateBounds(int top, int bottom, int left, int right) {
|
||
|
||
#ifdef DEBUG_FUNCTION_CALLS
|
||
writeSerialPortDebug(boutRefNum, "DEBUG_FUNCTION_CALLS: updateBounds");
|
||
#endif
|
||
|
||
if (left < mostLeft) {
|
||
|
||
mostLeft = left;
|
||
}
|
||
|
||
if (right > mostRight) {
|
||
|
||
mostRight = right;
|
||
}
|
||
|
||
if (top < mostTop) {
|
||
|
||
mostTop = top;
|
||
}
|
||
|
||
if (bottom > mostBottom) {
|
||
|
||
mostBottom = bottom;
|
||
}
|
||
}
|
||
|
||
#ifdef COMMAND_CACHING
|
||
void runDrawCommand(const struct nk_command *cmd, const struct nk_command *lastCmd) {
|
||
#else
|
||
void runDrawCommand(const struct nk_command *cmd) {
|
||
#endif
|
||
#ifdef DEBUG_FUNCTION_CALLS
|
||
writeSerialPortDebug(boutRefNum, "DEBUG_FUNCTION_CALLS: runDrawCommand");
|
||
#endif
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
char x[255];
|
||
sprintf(x, "cmd: %d", cmd->type);
|
||
writeSerialPortDebug(boutRefNum, x);
|
||
char y[255];
|
||
sprintf(y, "lastCmd: %d", lastCmd->type);
|
||
writeSerialPortDebug(boutRefNum, y);
|
||
#endif
|
||
|
||
switch (cmd->type) {
|
||
|
||
case NK_COMMAND_NOP:
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_NOP");
|
||
#endif
|
||
|
||
break;
|
||
case NK_COMMAND_SCISSOR: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_SCISSOR");
|
||
#endif
|
||
|
||
const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
|
||
|
||
// there is no point in supressing scissor commands because they only affect
|
||
// where we can actually draw to:
|
||
// #ifdef COMMAND_CACHING
|
||
// if (memcmp(s, lastCmd, sizeof(struct nk_command_scissor)) == 0) {
|
||
|
||
// #ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
// writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_scissor");
|
||
// #endif
|
||
|
||
// break;
|
||
// }
|
||
// #endif
|
||
|
||
Rect quickDrawRectangle;
|
||
quickDrawRectangle.top = s->y;
|
||
quickDrawRectangle.left = s->x;
|
||
quickDrawRectangle.bottom = s->y + s->h;
|
||
quickDrawRectangle.right = s->x + s->w;
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
// we use "-8192" here to filter out nuklear "nk_null_rect" which we do not want updating bounds
|
||
if (quickDrawRectangle.top != -8192) {
|
||
|
||
updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right);
|
||
}
|
||
#endif
|
||
|
||
ClipRect(&quickDrawRectangle);
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_RECT: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT");
|
||
#endif
|
||
|
||
// http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/QuickDraw/QuickDraw-102.html#MARKER-9-372
|
||
// http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/QuickDraw/QuickDraw-103.html#HEADING103-0
|
||
const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(r, lastCmd, sizeof(struct nk_command_rect)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_rect");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
ForeColor(r->color);
|
||
PenSize(r->line_thickness, r->line_thickness);
|
||
|
||
Rect quickDrawRectangle;
|
||
quickDrawRectangle.top = r->y;
|
||
quickDrawRectangle.left = r->x;
|
||
quickDrawRectangle.bottom = r->y + r->h;
|
||
quickDrawRectangle.right = r->x + r->w;
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right);
|
||
#endif
|
||
|
||
FrameRoundRect(&quickDrawRectangle, r->rounding, r->rounding);
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_RECT_FILLED: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT_FILLED");
|
||
#endif
|
||
|
||
const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
|
||
|
||
if (r->allowCache == false) {
|
||
|
||
Rect quickDrawRectangle;
|
||
quickDrawRectangle.top = r->y;
|
||
quickDrawRectangle.left = r->x;
|
||
quickDrawRectangle.bottom = r->y + r->h;
|
||
quickDrawRectangle.right = r->x + r->w;
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right);
|
||
#endif
|
||
|
||
FillRoundRect(&quickDrawRectangle, r->rounding, r->rounding, &qd.white);
|
||
break;
|
||
}
|
||
|
||
#ifdef COMMAND_CACHING
|
||
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(r, lastCmd, sizeof(struct nk_command_rect_filled)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_rect_filled");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
// TODO: to support coloring the lines, we need to map from qd Pattern types to integer colors
|
||
// color = nk_color_to_quickdraw_bw_color(r->color);
|
||
// ForeColor(color);
|
||
ForeColor(blackColor);
|
||
|
||
PenSize(1.0, 1.0);
|
||
|
||
Rect quickDrawRectangle;
|
||
quickDrawRectangle.top = r->y;
|
||
quickDrawRectangle.left = r->x;
|
||
quickDrawRectangle.bottom = r->y + r->h;
|
||
quickDrawRectangle.right = r->x + r->w;
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right);
|
||
#endif
|
||
|
||
FillRoundRect(&quickDrawRectangle, r->rounding, r->rounding, &r->color);
|
||
FrameRoundRect(&quickDrawRectangle, r->rounding, r->rounding); // http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/QuickDraw/QuickDraw-105.html#HEADING105-0
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_TEXT: {
|
||
|
||
const struct nk_command_text *t = (const struct nk_command_text*)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
if (!lastInputWasBackspace && t->allowCache && cmd->type == lastCmd->type && memcmp(t, lastCmd, sizeof(struct nk_command_text)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
char log[255];
|
||
|
||
sprintf(log, "ALREADY DREW CMD nk_command_text string: \"%s\", height: %d, length: %d, x: %d, y: %d, allowCache: %d", t->string, t->height, t->length, t->x, t->y, t->allowCache);
|
||
writeSerialPortDebug(boutRefNum, log);
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
char log[255];
|
||
|
||
sprintf(log, "NK_COMMAND_TEXT string: \"%s\", height: %d, length: %d, x: %d, y: %d, allowCache: %d", t->string, t->height, t->length, t->x, t->y, t->allowCache);
|
||
writeSerialPortDebug(boutRefNum, log);
|
||
#endif
|
||
|
||
Rect quickDrawRectangle;
|
||
quickDrawRectangle.top = t->y;
|
||
quickDrawRectangle.left = t->x;
|
||
quickDrawRectangle.bottom = t->y + 15;
|
||
quickDrawRectangle.right = t->x + _get_text_width((const char*)t->string, (int)t->length);
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right);
|
||
#endif
|
||
|
||
#ifdef COMMAND_CACHING
|
||
EraseRect(&quickDrawRectangle);
|
||
#endif
|
||
|
||
ForeColor(t->foreground);
|
||
MoveTo(t->x, t->y + t->height);
|
||
|
||
PenSize(1.0, 1.0);
|
||
DrawText((const char*)t->string, 0, t->length);
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_LINE: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_LINE");
|
||
#endif
|
||
|
||
const struct nk_command_line *l = (const struct nk_command_line *)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(l, lastCmd, sizeof(struct nk_command_line)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_line");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
// great reference: http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/QuickDraw/QuickDraw-60.html
|
||
ForeColor(l->color);
|
||
PenSize(l->line_thickness, l->line_thickness);
|
||
MoveTo(l->begin.x, l->begin.y);
|
||
LineTo(l->end.x, l->end.y);
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_CIRCLE: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_CIRCLE");
|
||
#endif
|
||
|
||
const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(c, lastCmd, sizeof(struct nk_command_circle)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_circle");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
ForeColor(c->color);
|
||
Rect quickDrawRectangle;
|
||
quickDrawRectangle.top = c->y;
|
||
quickDrawRectangle.left = c->x;
|
||
quickDrawRectangle.bottom = c->y + c->h;
|
||
quickDrawRectangle.right = c->x + c->w;
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right);
|
||
#endif
|
||
|
||
FrameOval(&quickDrawRectangle); // An oval is a circular or elliptical shape defined by the bounding rectangle that encloses it. inside macintosh: imaging with quickdraw 3-25
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_CIRCLE_FILLED: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_CIRCLE_FILLED");
|
||
#endif
|
||
|
||
const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(c, lastCmd, sizeof(struct nk_command_circle_filled)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_circle_filled");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
ForeColor(blackColor);
|
||
// BackPat(&colorPattern); // inside macintosh: imaging with quickdraw 3-48
|
||
PenSize(1.0, 1.0);
|
||
Rect quickDrawRectangle;
|
||
quickDrawRectangle.top = c->y;
|
||
quickDrawRectangle.left = c->x;
|
||
quickDrawRectangle.bottom = c->y + c->h;
|
||
quickDrawRectangle.right = c->x + c->w;
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right);
|
||
#endif
|
||
|
||
FillOval(&quickDrawRectangle, &c->color);
|
||
FrameOval(&quickDrawRectangle);// An oval is a circular or elliptical shape defined by the bounding rectangle that encloses it. inside macintosh: imaging with quickdraw 3-25
|
||
// http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/QuickDraw/QuickDraw-111.html#HEADING111-0
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_TRIANGLE: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_TRIANGLE");
|
||
#endif
|
||
|
||
const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(t, lastCmd, sizeof(struct nk_command_triangle)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_triangle");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
ForeColor(t->color);
|
||
PenSize(t->line_thickness, t->line_thickness);
|
||
|
||
MoveTo(t->a.x, t->a.y);
|
||
LineTo(t->b.x, t->b.y);
|
||
LineTo(t->c.x, t->c.y);
|
||
LineTo(t->a.x, t->a.y);
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_TRIANGLE_FILLED: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_TRIANGLE_FILLED");
|
||
#endif
|
||
|
||
const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(t, lastCmd, sizeof(struct nk_command_triangle_filled)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_triangle_filled");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
PenSize(1.0, 1.0);
|
||
// BackPat(&colorPattern); // inside macintosh: imaging with quickdraw 3-48
|
||
ForeColor(blackColor);
|
||
|
||
PolyHandle trianglePolygon = OpenPoly();
|
||
MoveTo(t->a.x, t->a.y);
|
||
LineTo(t->b.x, t->b.y);
|
||
LineTo(t->c.x, t->c.y);
|
||
LineTo(t->a.x, t->a.y);
|
||
ClosePoly();
|
||
|
||
FillPoly(trianglePolygon, &t->color);
|
||
KillPoly(trianglePolygon);
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_POLYGON: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_POLYGON");
|
||
#endif
|
||
|
||
const struct nk_command_polygon *p = (const struct nk_command_polygon*)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(p, lastCmd, sizeof(struct nk_command_polygon)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_polygon");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
ForeColor(p->color);
|
||
int i;
|
||
|
||
for (i = 0; i < p->point_count; i++) {
|
||
|
||
if (i == 0) {
|
||
|
||
MoveTo(p->points[i].x, p->points[i].y);
|
||
}
|
||
|
||
LineTo(p->points[i].x, p->points[i].y);
|
||
|
||
if (i == p->point_count - 1) {
|
||
|
||
LineTo(p->points[0].x, p->points[0].y);
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_POLYGON_FILLED: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_POLYGON_FILLED");
|
||
#endif
|
||
|
||
const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(p, lastCmd, sizeof(struct nk_command_polygon_filled)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_polygon_filled");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
// BackPat(&colorPattern); // inside macintosh: imaging with quickdraw 3-48 -- but might actually need PenPat -- look into this
|
||
ForeColor(blackColor);
|
||
int i;
|
||
|
||
PolyHandle trianglePolygon = OpenPoly();
|
||
for (i = 0; i < p->point_count; i++) {
|
||
|
||
if (i == 0) {
|
||
|
||
MoveTo(p->points[i].x, p->points[i].y);
|
||
}
|
||
|
||
LineTo(p->points[i].x, p->points[i].y);
|
||
|
||
if (i == p->point_count - 1) {
|
||
|
||
LineTo(p->points[0].x, p->points[0].y);
|
||
}
|
||
}
|
||
|
||
ClosePoly();
|
||
|
||
FillPoly(trianglePolygon, &p->color);
|
||
KillPoly(trianglePolygon);
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_POLYLINE: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_POLYLINE");
|
||
#endif
|
||
|
||
// this is similar to polygons except the polygon does not get closed to the 0th point
|
||
// check out the slight difference in the for loop
|
||
const struct nk_command_polygon *p = (const struct nk_command_polygon*)cmd;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
if (!lastInputWasBackspace && cmd->type == lastCmd->type && memcmp(p, lastCmd, sizeof(struct nk_command_polygon)) == 0) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "ALREADY DREW CMD nk_command_polygon");
|
||
#endif
|
||
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
ForeColor(p->color);
|
||
int i;
|
||
|
||
for (i = 0; i < p->point_count; i++) {
|
||
|
||
if (i == 0) {
|
||
|
||
MoveTo(p->points[i].x, p->points[i].y);
|
||
}
|
||
|
||
LineTo(p->points[i].x, p->points[i].y);
|
||
}
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_CURVE: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_CURVE");
|
||
#endif
|
||
|
||
const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
|
||
|
||
ForeColor(q->color);
|
||
Point p1 = { (int)q->begin.x, (int)q->begin.y};
|
||
Point p2 = { (int)q->ctrl[0].x, (int)q->ctrl[0].y};
|
||
Point p3 = { (int)q->ctrl[1].x, (int)q->ctrl[1].y};
|
||
Point p4 = { (int)q->end.x, (int)q->end.y};
|
||
|
||
BezierCurve(p1, p2, p3, p4);
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_ARC: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_ARC");
|
||
#endif
|
||
|
||
const struct nk_command_arc *a = (const struct nk_command_arc *)cmd;
|
||
|
||
ForeColor(a->color);
|
||
Rect arcBoundingBoxRectangle;
|
||
// this is kind of silly because the cx is at the center of the arc and we need to create a rectangle around it
|
||
// http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/QuickDraw/QuickDraw-60.html#MARKER-2-116
|
||
int x1 = (int)a->cx - (int)a->r;
|
||
int y1 = (int)a->cy - (int)a->r;
|
||
int x2 = (int)a->cx + (int)a->r;
|
||
int y2 = (int)a->cy + (int)a->r;
|
||
SetRect(&arcBoundingBoxRectangle, x1, y1, x2, y2);
|
||
|
||
FrameArc(&arcBoundingBoxRectangle, a->a[0], a->a[1]);
|
||
}
|
||
|
||
break;
|
||
case NK_COMMAND_IMAGE: {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_IMAGE");
|
||
#endif
|
||
|
||
// const struct nk_command_image *i = (const struct nk_command_image *)cmd;
|
||
// al_draw_bitmap_region(i->img.handle.ptr, 0, 0, i->w, i->h, i->x, i->y, 0); // TODO: look up and convert al_draw_bitmap_region
|
||
// TODO: consider implementing a bitmap drawing routine. we could iterate pixel by pixel and draw
|
||
// here is some super naive code that could work, used for another project that i was working on with a custom format but would be
|
||
// easy to modify for standard bitmap files (just need to know how many bytes represent each pixel and iterate from there):
|
||
//
|
||
// for (int i = 0; i < strlen(string); i++) {
|
||
// printf("\nchar: %c", string[i]);
|
||
// char pixel[1];
|
||
// memcpy(pixel, &string[i], 1);
|
||
// if (strcmp(pixel, "0") == 0) { // white pixel
|
||
// MoveTo(++x, y);
|
||
// } else if (strcmp(pixel, "1") == 0) { // black pixel
|
||
// // advance the pen and draw a 1px x 1px "line"
|
||
// MoveTo(++x, y);
|
||
// LineTo(x, y);
|
||
// } else if (strcmp(pixel, "|") == 0) { // next line
|
||
// x = 1;
|
||
// MoveTo(x, ++y);
|
||
// } else if (strcmp(pixel, "/") == 0) { // end
|
||
// }
|
||
// }
|
||
}
|
||
|
||
break;
|
||
|
||
// why are these cases not implemented?
|
||
case NK_COMMAND_RECT_MULTI_COLOR:
|
||
case NK_COMMAND_ARC_FILLED:
|
||
default:
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT_MULTI_COLOR/NK_COMMAND_ARC_FILLED/default");
|
||
#endif
|
||
break;
|
||
}
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NK_COMMAND_* draw complete");
|
||
#endif
|
||
}
|
||
|
||
#ifdef COMMAND_CACHING
|
||
const struct nk_command *lastCmd;
|
||
#endif
|
||
|
||
NK_API void nk_quickdraw_render(WindowPtr window, struct nk_context *ctx) {
|
||
|
||
#ifdef DEBUG_FUNCTION_CALLS
|
||
writeSerialPortDebug(boutRefNum, "DEBUG_FUNCTION_CALLS: nk_quickdraw_render");
|
||
#endif
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_START("IN nk_quickdraw_render");
|
||
#endif
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_START("get cmds and memcmp them");
|
||
#endif
|
||
|
||
void *cmds = nk_buffer_memory(&ctx->memory);
|
||
|
||
// do not render if the buffer did not change from the previous rendering run
|
||
if (!memcmp(cmds, last, ctx->memory.allocated)) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "NO RENDER BUFFER CHANGE, ABORT");
|
||
#endif
|
||
|
||
return;
|
||
}
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_END("get cmds and memcmp them");
|
||
#endif
|
||
|
||
const struct nk_command *cmd = 0;
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
OpenPort(&gMainOffScreen.BWPort);
|
||
SetPort(&gMainOffScreen.BWPort);
|
||
SetPortBits(&gMainOffScreen.BWBits);
|
||
#endif
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_START("rendering loop and switch");
|
||
#endif
|
||
|
||
#ifdef COMMAND_CACHING
|
||
lastCmd = nk_ptr_add_const(struct nk_command, last, 0);
|
||
#endif
|
||
|
||
nk_foreach(cmd, ctx) {
|
||
|
||
#ifdef COMMAND_CACHING
|
||
runDrawCommand(cmd, lastCmd);
|
||
#else
|
||
runDrawCommand(cmd);
|
||
#endif
|
||
|
||
#ifdef COMMAND_CACHING
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "COMMAND_CACHING: get next cached command");
|
||
#endif
|
||
|
||
if (lastCmd && lastCmd->next) {
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "COMMAND_CACHING: inside conditional");
|
||
#endif
|
||
|
||
lastCmd = nk_ptr_add_const(struct nk_command, last, lastCmd->next);
|
||
}
|
||
|
||
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
|
||
writeSerialPortDebug(boutRefNum, "COMMAND_CACHING: done getting lastCmd");
|
||
#endif
|
||
#endif
|
||
}
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_START("memcpy commands");
|
||
#endif
|
||
|
||
free(last);
|
||
last = calloc(1, MAX_MEMORY_IN_KB * 1024);
|
||
memcpy(last, cmds, ctx->memory.allocated);
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_END("memcpy commands");
|
||
#endif
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_END("rendering loop and switch");
|
||
#endif
|
||
|
||
#ifdef COMMAND_CACHING
|
||
lastInputWasBackspace = false;
|
||
#endif
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_START("copy bits");
|
||
#endif
|
||
|
||
SetPort(window);
|
||
|
||
Rect quickDrawRectangle;
|
||
quickDrawRectangle.top = mostTop;
|
||
quickDrawRectangle.left = mostLeft;
|
||
quickDrawRectangle.bottom = mostBottom;
|
||
quickDrawRectangle.right = mostRight;
|
||
|
||
CopyBits(&gMainOffScreen.bits->portBits, &window->portBits, &quickDrawRectangle, &quickDrawRectangle, srcCopy, 0L);
|
||
|
||
#ifdef DRAW_BLIT_LOCATION
|
||
ForeColor(blackColor);
|
||
// FillRoundRect(&quickDrawRectangle, 0, 0, &qd.ltGray);
|
||
FrameRoundRect(&quickDrawRectangle, 0, 0);
|
||
#endif
|
||
|
||
mostLeft = WINDOW_WIDTH;
|
||
mostBottom = 1;
|
||
mostTop = WINDOW_HEIGHT;
|
||
mostRight = 1;
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_END("copy bits");
|
||
#endif
|
||
#endif
|
||
|
||
#ifdef PROFILING
|
||
PROFILE_END("IN nk_quickdraw_render");
|
||
#endif
|
||
}
|
||
|
||
NK_API int nk_quickdraw_handle_event(EventRecord *event, struct nk_context *nuklear_context) {
|
||
|
||
#ifdef DEBUG_FUNCTION_CALLS
|
||
writeSerialPortDebug(boutRefNum, "DEBUG_FUNCTION_CALLS: nk_quickdraw_handle_event");
|
||
#endif
|
||
// see: inside macintosh: toolbox essentials 2-4
|
||
// and inside macintosh toolbox essentials 2-79
|
||
|
||
WindowPtr window;
|
||
FindWindow(event->where, &window);
|
||
// char logb[255];
|
||
// sprintf(logb, "nk_quickdraw_handle_event event %d", event->what);
|
||
// writeSerialPortDebug(boutRefNum, logb);
|
||
|
||
switch (event->what) {
|
||
case updateEvt: {
|
||
return 1;
|
||
}
|
||
break;
|
||
case osEvt: {
|
||
// the quicktime osEvts are supposed to cover mouse movement events
|
||
// notice that we are actually calling nk_input_motion in the EventLoop for the program
|
||
// instead, as handling this event directly does not appear to work for whatever reason
|
||
// TODO: research this
|
||
// writeSerialPortDebug(boutRefNum, "osEvt");
|
||
|
||
switch (event->message) {
|
||
|
||
case mouseMovedMessage: {
|
||
|
||
#ifdef NK_QUICKDRAW_EVENTS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "mouseMovedMessage");
|
||
#endif
|
||
|
||
|
||
// event->where should have coordinates??? or is it just a pointer to what the mouse is over?
|
||
// TODO need to figure this out
|
||
nk_input_motion(nuklear_context, event->where.h, event->where.v); // TODO figure out mouse coordinates - not sure if this is right
|
||
|
||
break;
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case mouseUp:
|
||
#ifdef NK_QUICKDRAW_EVENTS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "mouseUp!!!");
|
||
#endif
|
||
case mouseDown: {
|
||
|
||
#ifdef NK_QUICKDRAW_EVENTS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "mouseUp/Down");
|
||
#endif
|
||
|
||
short part = FindWindow(event->where, &window);
|
||
|
||
switch (part) {
|
||
case inContent: {
|
||
// event->where should have coordinates??? or is it just a pointer to what the mouse is over?
|
||
// TODO need to figure this out
|
||
#ifdef NK_QUICKDRAW_EVENTS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "mouseUp/Down IN DEFAULT ZONE!!!!");
|
||
#endif
|
||
|
||
// this converts the offset of the window to the actual location of the mouse within the window
|
||
Point tempPoint;
|
||
SetPt(&tempPoint, event->where.h, event->where.v);
|
||
GlobalToLocal(&tempPoint);
|
||
|
||
if (!event->where.h) {
|
||
|
||
#ifdef NK_QUICKDRAW_EVENTS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "no event location for mouse!!!!");
|
||
#endif
|
||
return 1;
|
||
}
|
||
int x = tempPoint.h;
|
||
int y = tempPoint.v;
|
||
|
||
#ifdef NK_QUICKDRAW_EVENTS_DEBUGGING
|
||
|
||
char logx[255];
|
||
sprintf(logx, "mouse location at time of click h: %d, v: %d, is mouse down: %d", x, y, event->what == mouseDown);
|
||
writeSerialPortDebug(boutRefNum, logx);
|
||
#endif
|
||
|
||
// nk_input_motion(nuklear_context, x, y); // you can enable this if you don't want to use motion tracking
|
||
// in the Mac event loop handler as in the nuklear quickdraw sample, and this will allow mouse clicks to
|
||
// work properly, but will not allow hover states to work
|
||
nk_input_motion(nuklear_context, x, y);
|
||
nk_input_button(nuklear_context, NK_BUTTON_LEFT, x, y, event->what == mouseDown);
|
||
}
|
||
break;
|
||
return 1;
|
||
}
|
||
|
||
break;
|
||
case keyDown:
|
||
case autoKey: {/* check for menukey equivalents */
|
||
|
||
char charKey = event->message & charCodeMask;
|
||
int key = (int)charKey;
|
||
|
||
|
||
#ifdef NK_QUICKDRAW_EVENTS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "keyDown/autoKey");
|
||
|
||
char logy[255];
|
||
sprintf(logy, "key pressed: key: '%c', 02x: '%02X', return: '%02X', %d == %d ??", key, key, returnKey, (int)(key), (int)(returnKey));
|
||
writeSerialPortDebug(boutRefNum, logy);
|
||
#endif
|
||
|
||
const Boolean isKeyDown = event->what == keyDown;
|
||
|
||
if (event->modifiers & cmdKey) {/* Command key down */
|
||
|
||
if (isKeyDown) {
|
||
|
||
// AdjustMenus(); /* enable/disable/check menu items properly */
|
||
// DoMenuCommand(MenuKey(key));
|
||
}
|
||
|
||
if (key == 'c') {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_COPY, 1);
|
||
} else if (key == 'v') {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_PASTE, 1);
|
||
} else if (key == 'x') {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_CUT, 1);
|
||
} else if (key == 'z') {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_TEXT_UNDO, 1);
|
||
} else if (key == 'r') {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_TEXT_REDO, 1);
|
||
}
|
||
} else if (key == eitherShiftKey) {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_SHIFT, isKeyDown);
|
||
} else if (key == deleteKey && isKeyDown) {
|
||
|
||
#ifdef COMMAND_CACHING
|
||
lastInputWasBackspace = true;
|
||
#endif
|
||
nk_input_key(nuklear_context, NK_KEY_DEL, isKeyDown);
|
||
} else if (key == enterKey) {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_ENTER, isKeyDown);
|
||
} else if (key == returnKey) {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_ENTER, isKeyDown);
|
||
} else if (key == tabKey) {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_TAB, isKeyDown);
|
||
} else if (key == leftArrowKey) {
|
||
|
||
#ifdef COMMAND_CACHING
|
||
lastInputWasBackspace = true;
|
||
#endif
|
||
nk_input_key(nuklear_context, NK_KEY_LEFT, isKeyDown);
|
||
} else if (key == rightArrowKey) {
|
||
|
||
#ifdef COMMAND_CACHING
|
||
lastInputWasBackspace = true;
|
||
#endif
|
||
nk_input_key(nuklear_context, NK_KEY_RIGHT, isKeyDown);
|
||
} else if (key == upArrowKey) {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_UP, isKeyDown);
|
||
} else if (key == downArrowKey) {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_DOWN, isKeyDown);
|
||
} else if (key == backspaceKey) {
|
||
|
||
#ifdef COMMAND_CACHING
|
||
lastInputWasBackspace = true;
|
||
#endif
|
||
nk_input_key(nuklear_context, NK_KEY_BACKSPACE, isKeyDown);
|
||
} else if (key == escapeKey) {
|
||
|
||
// nk_input_key(nuklear_context, NK_KEY_TEXT_RESET_MODE, isKeyDown);
|
||
} else if (key == pageUpKey) {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_SCROLL_UP, isKeyDown);
|
||
} else if (key == pageDownKey) {
|
||
|
||
nk_input_key(nuklear_context, NK_KEY_SCROLL_DOWN, isKeyDown);
|
||
} else if (key == homeKey) {
|
||
|
||
// nk_input_key(nuklear_context, NK_KEY_TEXT_START, isKeyDown);
|
||
nk_input_key(nuklear_context, NK_KEY_SCROLL_START, isKeyDown);
|
||
} else if (key == endKey) {
|
||
|
||
// nk_input_key(nuklear_context, NK_KEY_TEXT_END, isKeyDown);
|
||
nk_input_key(nuklear_context, NK_KEY_SCROLL_END, isKeyDown);
|
||
} else {
|
||
|
||
#ifdef NK_QUICKDRAW_EVENTS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "default keydown/autokey event");
|
||
#endif
|
||
|
||
nk_input_char(nuklear_context, charKey);
|
||
}
|
||
|
||
lastEventWasKey = 1;
|
||
|
||
return 1;
|
||
}
|
||
break;
|
||
default: {
|
||
#ifdef NK_QUICKDRAW_EVENTS_DEBUGGING
|
||
|
||
writeSerialPortDebug(boutRefNum, "default unhandled event");
|
||
#endif
|
||
|
||
return 1;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
// i think these functions are close to correct, but throw an error around invalid storage class
|
||
NK_INTERN void nk_quickdraw_clipboard_paste(nk_handle usr, struct nk_text_edit *edit) {
|
||
|
||
Handle hDest = NewHandle(0); // { automatically resizes it}
|
||
HLock(hDest);
|
||
// {put data into memory referenced thru hDest handle}
|
||
int sizeOfSurfData = GetScrap(hDest, 'TEXT', 0);
|
||
HUnlock(hDest);
|
||
nk_textedit_paste(edit, (char *)hDest, sizeOfSurfData);
|
||
DisposeHandle(hDest);
|
||
}
|
||
|
||
NK_INTERN void nk_quickdraw_clipboard_copy(nk_handle usr, const char *text, short len) {
|
||
|
||
// in Macintosh Toolbox the clipboard is referred to as "scrap manager"
|
||
PutScrap(len, 'TEXT', text);
|
||
}
|
||
|
||
// it us up to our "main" function to call this code
|
||
NK_API struct nk_context* nk_quickdraw_init(unsigned int width, unsigned int height) {
|
||
|
||
// needed to calculate bezier info, see mactech article.
|
||
setupBezier();
|
||
|
||
#ifdef ENABLED_DOUBLE_BUFFERING
|
||
NewShockBitmap(&gMainOffScreen, width, height);
|
||
#else
|
||
TextFont(0);
|
||
TextSize(12);
|
||
TextFace(0);
|
||
#endif
|
||
|
||
NkQuickDrawFont *quickdrawfont = nk_quickdraw_font_create_from_file();
|
||
struct nk_user_font *font = &quickdrawfont->nk;
|
||
|
||
#ifdef COMMAND_CACHING
|
||
lastCmd = malloc(sizeof(struct nk_command));
|
||
#endif
|
||
|
||
last = calloc(1, MAX_MEMORY_IN_KB * 1024);
|
||
buf = calloc(1, MAX_MEMORY_IN_KB * 1024);
|
||
nk_init_fixed(&quickdraw.nuklear_context, buf, MAX_MEMORY_IN_KB * 1024, font);
|
||
|
||
nk_style_push_font(&quickdraw.nuklear_context, font);
|
||
|
||
quickdraw.nuklear_context.clip.copy = nk_quickdraw_clipboard_copy;
|
||
quickdraw.nuklear_context.clip.paste = nk_quickdraw_clipboard_paste;
|
||
quickdraw.nuklear_context.clip.userdata = nk_handle_ptr(0);
|
||
|
||
ForeColor(blackColor);
|
||
|
||
return &quickdraw.nuklear_context;
|
||
}
|
||
|
||
NK_API void nk_quickdraw_shutdown(void) {
|
||
|
||
nk_free(&quickdraw.nuklear_context);
|
||
memset(&quickdraw, 0, sizeof(quickdraw));
|
||
}
|
||
|
||
|
||
|