aboutsummaryrefslogtreecommitdiffstats
path: root/demos/3rdparty/notepad-2/notepadCore.c
diff options
context:
space:
mode:
Diffstat (limited to 'demos/3rdparty/notepad-2/notepadCore.c')
-rw-r--r--demos/3rdparty/notepad-2/notepadCore.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/demos/3rdparty/notepad-2/notepadCore.c b/demos/3rdparty/notepad-2/notepadCore.c
new file mode 100644
index 00000000..abb189bc
--- /dev/null
+++ b/demos/3rdparty/notepad-2/notepadCore.c
@@ -0,0 +1,235 @@
+/*
+ * File: notepadCore.c
+ *
+ * This file is a part of the Notepad demo application for ChibiOS/GFX
+ * Copyright © 2013, Kumar Abhishek [abhishek.kakkar@edaboard.com].
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of 'Kumar Abhishek' may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * DISCLAIMER OF WARRANTY:
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#include "notepadCore.h"
+#include "notepadUIDefines.h"
+
+#define PEN_IN_DRAWING_AREA(ev) ((ev.x >= ncoreDrawingArea->x) && (ev.x <= (ncoreDrawingArea->x + ncoreDrawingArea->width)) && \
+ (ev.y >= ncoreDrawingArea->y) && (ev.y <= (ncoreDrawingArea->y + ncoreDrawingArea->height)))
+
+/* This is the drawing core */
+static WORKING_AREA(waDrawThread, NCORE_THD_STACK_SIZE);
+
+static uint8_t nPenWidth = 1;
+static uint8_t nMode = NCORE_MODE_DRAW;
+
+static Thread *nThd;
+
+static GHandle ncoreDrawingArea = NULL;
+static BaseSequentialStream *nStatusConsole = NULL;
+
+static void draw_point(coord_t x, coord_t y) {
+ color_t c = ncoreDrawingArea->color;
+
+ if (nMode == NCORE_MODE_DRAW)
+ c = ncoreDrawingArea->color;
+ else if (nMode == NCORE_MODE_ERASE)
+ c = ncoreDrawingArea->bgcolor;
+
+ if (nPenWidth == 1)
+ gdispDrawPixel(x, y, c);
+ else
+ gdispFillCircle(x, y, nPenWidth, c);
+}
+
+/* Bresenham's Line Drawing Algorithm
+ Modified version to draw line of variable thickness */
+static void draw_line(coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
+ int16_t dy, dx;
+ int16_t addx, addy;
+ int16_t P, diff, i;
+
+ if (x1 >= x0) {
+ dx = x1 - x0;
+ addx = 1;
+ } else {
+ dx = x0 - x1;
+ addx = -1;
+ }
+ if (y1 >= y0) {
+ dy = y1 - y0;
+ addy = 1;
+ } else {
+ dy = y0 - y1;
+ addy = -1;
+ }
+
+ if (dx >= dy) {
+ dy *= 2;
+ P = dy - dx;
+ diff = P - dx;
+
+ for(i=0; i<=dx; ++i) {
+ draw_point(x0, y0);
+ if (P < 0) {
+ P += dy;
+ x0 += addx;
+ } else {
+ P += diff;
+ x0 += addx;
+ y0 += addy;
+ }
+ }
+ } else {
+ dx *= 2;
+ P = dx - dy;
+ diff = P - dy;
+
+ for(i=0; i<=dy; ++i) {
+ draw_point(x0, y0);
+ if (P < 0) {
+ P += dx;
+ y0 += addy;
+ } else {
+ P += diff;
+ x0 += addx;
+ y0 += addy;
+ }
+ }
+ }
+}
+
+/* Core thread */
+static msg_t ncoreDrawThread(void *msg) {
+
+ GEventMouse ev, evPrev;
+ coord_t dx, dy;
+
+ int state = 0, dist;
+
+ (void)msg;
+
+ ginputGetMouseStatus(0, &evPrev);
+
+ while (1) {
+
+ // Exit signal received? If yes, terminate.
+ if (chThdShouldTerminate())
+ return 0;
+
+ ginputGetMouseStatus(0, &ev);
+ switch(state) {
+ case 0: if (ev.meta == GMETA_MOUSE_DOWN) {
+ state = 1;
+ if (nMode == NCORE_MODE_FILL && PEN_IN_DRAWING_AREA(ev)) {
+ // Set bgcolor to current color, clear the display.
+ ncoreDrawingArea->bgcolor = ncoreDrawingArea->color;
+ gwinClear(ncoreDrawingArea);
+ }
+ }
+ else
+ chThdYield();
+ break;
+
+
+ case 1: if (ev.meta == GMETA_MOUSE_UP) {
+ state = 0;
+ //chprintf(nStatusConsole, "\nPen Up: (%d, %d)", ev.x, ev.y);
+ break;
+ }
+
+ dx = abs(ev.x - evPrev.x);
+ dy = abs(ev.y - evPrev.y);
+
+ dist = dx * dx + dy * dy;
+
+ if (dist > 0)
+ {
+ gdispSetClip(ncoreDrawingArea->x,
+ ncoreDrawingArea->y,
+ ncoreDrawingArea->width,
+ ncoreDrawingArea->height);
+
+ if (PEN_IN_DRAWING_AREA(ev)){
+ // Do Interpolation
+ if (dist <= 2) {
+ draw_point(ev.x, ev.y);
+ }
+ else if (dist <= 5) {
+ // Line drawing does not give good results for this case.
+ // So draw two pixels directly
+ draw_point(ev.x, ev.y);
+ draw_point((ev.x + evPrev.x) / 2, (ev.y + evPrev.y) / 2);
+ }
+ else if (dx * dx <= MAX_DX && dy * dy <= MAX_DY) {
+ draw_line(ev.x, ev.y, evPrev.x, evPrev.y);
+ }
+ }
+
+ //chprintf(nStatusConsole, "\nPen Down: (%d, %d)", ev.x, ev.y);
+ }
+ break;
+ }
+ evPrev = ev;
+ }
+
+ return 0;
+}
+
+/* Spawn the core thread */
+void ncoreSpawnDrawThread(GHandle drawingArea, BaseSequentialStream *statusConsole) {
+
+ ncoreDrawingArea = drawingArea;
+ nStatusConsole = statusConsole;
+
+ nThd = chThdCreateStatic(waDrawThread,
+ sizeof(waDrawThread),
+ NCORE_THD_PRIO,
+ ncoreDrawThread,
+ NULL);
+
+}
+
+/* Terminate the core thread, wait for control release */
+void ncoreTerminateDrawThread(void) {
+ chThdTerminate(nThd);
+ chThdWait(nThd);
+}
+
+/* Get and set the pen width
+ * Brush is cicular, width is pixel radius */
+void ncoreSetPenWidth(uint8_t penWidth) { nPenWidth = penWidth; }
+uint8_t ncoreGetPenWidth(void) { return nPenWidth; }
+
+/* Get and set the drawing color */
+void ncoreSetPenColor(color_t penColor) { gwinSetColor(ncoreDrawingArea, penColor); }
+color_t ncoreGetPenColor(void) { return ncoreDrawingArea->color; }
+
+/* Set mode */
+void ncoreSetMode(uint8_t mode) { nMode = mode; }
+uint8_t ncoreGetMode(void) { return nMode; }