Commit 40a4d417 authored by Øyvind Kolås's avatar Øyvind Kolås
Browse files

(feat:ctc) add preliminary pycardium ctx integration

We should perhaps have a ctx object returned from the display instead
of overloading the displas as the ctx context?
parent 6bcb071c
......@@ -185,6 +185,110 @@ class Display:
sys_display.circ(x, y, rad, col, filled, size)
return self
def fill(self):
sys_display.fill()
return self
def line_width(self, lw):
sys_display.line_width(lw)
return self
def font_size(self, lw):
sys_display.font_size(lw)
return self
def stroke(self):
sys_display.stroke()
return self
def text(self, utf8):
sys_display.text(utf8)
return self
#def svg_path(self, d):
# sys_display.svg_path(d)
# return self
def flush(self):
sys_display.flush()
return self
def scale(self, x, y):
sys_display.scale(x, y)
return self
def translate(self, x, y):
sys_display.translate(x, y)
return self
def rotate(self, r):
sys_display.rotate(r)
return self
def save(self):
sys_display.save()
return self
def restore(self):
sys_display.restore()
return self
def rgba(self, r, g, b, a):
sys_display.rgba(r, g, b, a)
return self
def line_to(self, x0, y0):
sys_display.line_to(x0, y0)
return self
def move_to(self, x0, y0):
sys_display.move_to(x0, y0)
return self
def quad_to(self, x0, y0, x1, y1):
sys_display.quad_to(x0, y0, x1, y1)
return self
def curve_to(self, x0, y0, x1, y1, x2, y2):
sys_display.curve_to(x0, y0, x1, y1, x2, y2)
return self
def rel_line_to(self, x0, y0):
sys_display.rel_line_to(x0, y0)
return self
def rel_move_to(self, x0, y0):
sys_display.rel_move_to(x0, y0)
return self
def rel_quad_to(self, x0, y0, x1, y1):
sys_display.rel_quad_to(x0, y0, x1, y1)
return self
def rectangle(self, x0, y0, x1, y1):
sys_display.rectangle(x0, y0, x1, y1)
return self
def rel_curve_to(self, x0, y0, x1, y1, x2, y2):
sys_display.rel_curve_to(x0, y0, x1, y1, x2, y2)
return self
def linear_gradient(self, x0, y0, x1, y1):
sys_display.linear_gradient(x0, y0, x1, y1)
return self
def gradient_add_stop(self, pos, r, g, b, a):
sys_display.gradient_add_stop (pos, r, g, b, a)
return self
def gradient_clear_stops(self):
sys_display.gradient_clear_stops()
return self
def radial_gradient(self, x0, y0, r0, x1, y1, r1):
sys_display.radial_gradient(x0, y0, r0, x1, y1, r1)
return self
open = Display.open
close = Display.close
......@@ -104,6 +104,40 @@ Q(rect)
Q(circ)
Q(clear)
Q(arc)
Q(gray)
Q(gradient_add_stop)
Q(fill)
Q(clip)
Q(font)
Q(svg_path)
Q(stroke)
Q(begin_path)
Q(save)
Q(restore)
Q(rotate)
Q(line_width)
Q(font_size)
Q(scale)
Q(translate)
Q(line_to)
Q(move_to)
Q(curve_to)
Q(quad_to)
Q(quad_to)
Q(rectangle)
Q(rel_line_to)
Q(rel_move_to)
Q(rel_curve_to)
Q(rel_quad_to)
Q(close_path)
Q(rgba)
Q(global_alpha)
Q(text)
Q(text_width)
Q(linear_gradient)
Q(radial_gradient)
/* ambient */
Q(light_sensor)
Q(start)
......
#include "epicardium.h"
#include <stdint.h>
#include "py/obj.h"
#include "py/objint.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include <stdio.h>
//#include <stdio.h>
#if 1
#define CTX_MIN_JOURNAL_SIZE 384
#define CTX_MAX_JOURNAL_SIZE 384
#define CTX_RASTERIZER 0
#define CTX_GRADIENT_CACHE 0
#define CTX_LIMIT_FORMATS 1
#define CTX_RENDERSTREAM_STATIC 1
#define CTX_EVENTS 0
#define CTX_PARSER 0
#define CTX_FORMATTER 0
#define CTX_FONTS_FROM_FILE 0
#define CTX_IMPLEMENTATION 1
#define _CTX_INTERNAL_FONT_
#define malloc m_malloc
#define realloc m_realloc
#define free m_free
#include "../../lib/ctx/ctx-font-regular-spacing.h"
#include "../../lib/ctx/ctx.h"
#undef free
#undef malloc
#undef realloc
static Ctx *ctx = NULL;
void full_cb (CtxRenderstream *rs, void *data)
{
epic_disp_ctx (rs->entries, rs->count * 9);
rs->count = 0;
}
static Ctx *ensure_ctx (void)
{
if (!ctx)
{
ctx = ctx_new ();
ctx_reset (ctx);
//ctx_set_full_cb (ctx, full_cb, NULL);
}
CtxRenderstream *rs = &ctx->renderstream;
/* with full_cb this used to be more precise - and
* it will go wrong with very long text strings.
*/
if (rs->count > CTX_MAX_JOURNAL_SIZE-64)
{
epic_disp_ctx (rs->entries, rs->count * 9);
rs->count = 0;
}
return ctx;
}
#endif
static uint16_t rgb888_to_rgb565(uint8_t *bytes)
{
......@@ -13,6 +69,16 @@ static uint16_t rgb888_to_rgb565(uint8_t *bytes)
(bytes[2] >> 3);
}
static inline void rgb565_to_rgb888 (uint16_t pixel,
uint8_t *red,
uint8_t *green,
uint8_t *blue)
{
*blue = (pixel & 31)<<3;
*green = ((pixel>>5) & 63)<<2;
*red = ((pixel>>11) & 31)<<3;
}
static uint16_t get_color(mp_obj_t color_in)
{
if (mp_obj_get_int(mp_obj_len(color_in)) < 3) {
......@@ -32,6 +98,10 @@ static uint16_t get_color(mp_obj_t color_in)
return rgb888_to_rgb565(colors);
}
static int ctx_mode = 0;
static int ctx_mode_text = 2;
static int ctx_commands_received = 0;
/* print something on the display */
static mp_obj_t mp_display_print(size_t n_args, const mp_obj_t *args)
{
......@@ -43,7 +113,37 @@ static mp_obj_t mp_display_print(size_t n_args, const mp_obj_t *args)
int32_t posy = mp_obj_get_int(args[2]);
uint32_t fg = get_color(args[3]);
uint32_t bg = get_color(args[4]);
int res = epic_disp_print(posx, posy, (const char *)print, fg, bg);
int res = 0;
if (ctx_mode || ctx_mode_text) {
Ctx *ctx = ensure_ctx();
float font_size = 20.0f;
ctx_font_size (ctx, font_size);
if (fg!=bg) {
uint8_t r,g,b;
rgb565_to_rgb888 (bg, &r, &g, &b);
ctx_rgba8 (ctx, r, g, b, 255);
ctx_rectangle (ctx, posx, posy,
ctx_text_width (ctx, (const char*)print), font_size);
ctx_fill (ctx);
}
{
uint8_t r,g,b;
rgb565_to_rgb888 (fg, &r, &g, &b);
ctx_rgba8 (ctx, r, g, b, 255);
}
ctx_move_to (ctx, posx, posy + font_size * 0.8f);
ctx_text (ctx, (const char*)print);
if (!ctx_mode)
{
CtxRenderstream *rs = &ctx->renderstream;
epic_disp_ctx (rs->entries, rs->count * 9);
ctx_reset (ctx);
ctx_commands_received=0;
rs->count = 0;
}
} else {
res = epic_disp_print(posx, posy, (const char *)print, fg, bg);
}
if (res < 0) {
mp_raise_OSError(-res);
}
......@@ -65,9 +165,50 @@ static mp_obj_t mp_display_print_adv(size_t n_args, const mp_obj_t *args)
uint32_t fg = get_color(args[3]);
uint32_t bg = get_color(args[4]);
uint8_t fontName = mp_obj_get_int(args[5]);
int res = epic_disp_print_adv(
fontName, posx, posy, (const char *)print, fg, bg
);
int res = 0;
if (ctx_mode || ctx_mode_text) {
Ctx *ctx = ensure_ctx();
float font_size = 20.0f;
switch (fontName)
{
case 0: font_size = 8.0; break;
case 1: font_size = 12.0; break;
case 2: font_size = 16.0; break;
case 3: font_size = 20.0; break;
case 4: font_size = 24.0; break;
case 5: font_size = 32.0; break;
case 6: font_size = 40.0; break;
case 7: font_size = 64.0; break;
case 8: font_size = 80.0; break;
}
ctx_font_size (ctx, font_size);
if (fg != bg) {
uint8_t r,g,b;
rgb565_to_rgb888 (bg, &r, &g, &b);
ctx_rgba8 (ctx, r, g, b, 255);
ctx_rectangle (ctx, posx, posy,
ctx_text_width (ctx, (const char*)print), font_size);
ctx_fill (ctx);
}
{
uint8_t r,g,b;
rgb565_to_rgb888 (fg, &r, &g, &b);
ctx_rgba8 (ctx, r, g, b, 255);
}
ctx_move_to (ctx, posx, posy + font_size * 0.8);
ctx_text (ctx, (const char*)print);
if (!ctx_mode)
{
CtxRenderstream *rs = &ctx->renderstream;
epic_disp_ctx (rs->entries, rs->count * 9);
ctx_reset (ctx);
ctx_commands_received=0;
rs->count = 0;
}
} else {
res = epic_disp_print_adv(
fontName, posx, posy, (const char *)print, fg, bg);
}
if (res < 0) {
mp_raise_OSError(-res);
}
......@@ -84,7 +225,21 @@ static mp_obj_t mp_display_pixel(size_t n_args, const mp_obj_t *args)
int16_t y = mp_obj_get_int(args[1]);
uint16_t col = get_color(args[2]);
int res = epic_disp_pixel(x, y, col);
int res = 0;
if (ctx_mode) {
Ctx *ctx = ensure_ctx();
uint8_t r,g,b;
rgb565_to_rgb888 (col, &r, &g, &b);
#if 0
ctx_rgb (ctx, r/255.0, g/255.0, b/255.0);
ctx_rectangle (ctx, x, y, 1, 1);
ctx_fill (ctx);
#else
ctx_set_pixel_u8 (ctx, x, y, r, g, b, 255);
#endif
} else {
res = epic_disp_pixel (x, y, col);
}
if (res < 0) {
mp_raise_OSError(-res);
}
......@@ -109,6 +264,8 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
display_backlight_obj, 1, 1, mp_display_backlight
);
/* draw line on the display */
static mp_obj_t mp_display_line(size_t n_args, const mp_obj_t *args)
{
......@@ -124,7 +281,22 @@ static mp_obj_t mp_display_line(size_t n_args, const mp_obj_t *args)
mp_raise_ValueError("Line style has to be 0 or 1");
}
int res = epic_disp_line(xs, ys, xe, ye, col, ls, ps);
int res = 0;
if (ctx_mode) {
Ctx *ctx = ensure_ctx();
ctx_line_width (ctx, ps);
ctx_move_to (ctx, xs, ys);
ctx_line_to (ctx, xe, ye);
uint8_t r,g,b;
rgb565_to_rgb888 (col, &r, &g, &b);
if (ls == LINESTYLE_DOTTED)
ctx_rgba8 (ctx, r, g, b, 127);
else
ctx_rgba8 (ctx, r, g, b, 255);
ctx_stroke (ctx);
} else {
res = epic_disp_line(xs, ys, xe, ye, col, ls, ps);
}
if (res < 0) {
mp_raise_OSError(-res);
}
......@@ -149,7 +321,26 @@ static mp_obj_t mp_display_rect(size_t n_args, const mp_obj_t *args)
mp_raise_ValueError("Fill style has to be 0 or 1");
}
int res = epic_disp_rect(xs, ys, xe, ye, col, fs, ps);
int res = 0;
if (ctx_mode) {
Ctx *ctx = ensure_ctx();
ctx_rectangle (ctx, xs, ys, xe-xs, ye-ys);
uint8_t r,g,b;
rgb565_to_rgb888 (col, &r, &g, &b);
ctx_rgba8 (ctx, r, g, b, 255);
if (fs == FILLSTYLE_FILLED)
{
ctx_fill (ctx);
}
else
{
ctx_line_width (ctx, ps);
ctx_stroke (ctx);
}
} else {
res = epic_disp_rect(xs, ys, xe, ye, col, fs, ps);
}
if (res < 0) {
mp_raise_OSError(-res);
}
......@@ -170,12 +361,32 @@ static mp_obj_t mp_display_circ(size_t n_args, const mp_obj_t *args)
uint16_t ps = mp_obj_get_int(args[5]);
if (fs > 1) {
mp_raise_ValueError("Fill style has to be 0 or 1");
mp_raise_ValueError("Fill style has to be 0 or 1");
}
int res = epic_disp_circ(x, y, rad, col, fs, ps);
int res = 0;
if (ctx_mode) {
Ctx *ctx = ensure_ctx();
ctx_arc (ctx, x, y, rad, 0.0, CTX_PI*1.85, 0);
uint8_t r,g,b;
rgb565_to_rgb888 (col, &r, &g, &b);
if (fs == FILLSTYLE_EMPTY && ps == LINESTYLE_DOTTED)
ctx_rgba8 (ctx, r, g, b, 127);
/*XXX:dotted and half transparent isn't really the same thing.. */
else
ctx_rgba8 (ctx, r, g, b, 255);
if (fs == FILLSTYLE_FILLED) {
ctx_fill (ctx);
} else {
ctx_line_width (ctx, ps);
ctx_stroke (ctx);
}
} else {
res = epic_disp_circ(x, y, rad, col, fs, ps);
}
if (res < 0) {
mp_raise_OSError(-res);
mp_raise_OSError(-res);
}
return mp_const_none;
}
......@@ -187,7 +398,18 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
static mp_obj_t mp_display_clear(mp_obj_t col)
{
uint16_t color = get_color(col);
int res = epic_disp_clear(color);
int res = 0;
if (ctx_mode) {
Ctx *ctx = ensure_ctx();
ctx_reset (ctx);
uint8_t r,g,b;
rgb565_to_rgb888 (color, &r, &g, &b);
ctx_rgba8 (ctx, r, g, b, 255);
ctx_rectangle (ctx, 0, 0, DISP_WIDTH, DISP_HEIGHT);
ctx_fill (ctx);
} else {
res = epic_disp_clear(color);
}
if (res < 0) {
mp_raise_OSError(-res);
}
......@@ -197,6 +419,13 @@ static MP_DEFINE_CONST_FUN_OBJ_1(display_clear_obj, mp_display_clear);
static mp_obj_t mp_display_update()
{
if (ctx_mode || ctx_commands_received) {
Ctx *ctx = ensure_ctx ();
epic_disp_ctx (ctx->renderstream.entries,
ctx->renderstream.count * 9);
ctx_reset (ctx);
ctx_commands_received=0;
}
int res = epic_disp_update();
if (res < 0) {
mp_raise_OSError(-res);
......@@ -225,6 +454,343 @@ static mp_obj_t mp_display_close()
}
static MP_DEFINE_CONST_FUN_OBJ_0(display_close_obj, mp_display_close);
static mp_obj_t mp_display_scale(mp_obj_t arg0, mp_obj_t arg1)
{
float x = mp_obj_get_float(arg0);
float y = mp_obj_get_float(arg1);
ctx_scale (ensure_ctx(), x, y);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(display_scale_obj, mp_display_scale);
static mp_obj_t mp_display_translate(mp_obj_t arg0, mp_obj_t arg1)
{
float x = mp_obj_get_float(arg0);
float y = mp_obj_get_float(arg1);
ctx_translate (ensure_ctx(), x, y);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(display_translate_obj, mp_display_translate);
static mp_obj_t mp_display_rotate(mp_obj_t arg)
{
float x1 = mp_obj_get_float(arg);
ctx_rotate (ensure_ctx(), x1);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(display_rotate_obj, mp_display_rotate);
static mp_obj_t mp_display_line_width(mp_obj_t arg)
{
float x1 = mp_obj_get_float(arg);
ctx_line_width (ensure_ctx(), x1);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(display_line_width_obj,
mp_display_line_width);
static mp_obj_t mp_display_gray(mp_obj_t arg)
{
float x1 = mp_obj_get_float(arg);
ctx_gray (ensure_ctx(), x1);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(display_gray_obj,
mp_display_gray);
static mp_obj_t mp_display_global_alpha(mp_obj_t arg)
{
float x1 = mp_obj_get_float(arg);
ctx_global_alpha (ensure_ctx(), x1);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(display_global_alpha_obj,
mp_display_global_alpha);
static mp_obj_t mp_display_font_size(mp_obj_t arg)
{
float x1 = mp_obj_get_float(arg);
ctx_font_size (ensure_ctx(), x1);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(display_font_size_obj,
mp_display_font_size);
static mp_obj_t mp_display_line_to(mp_obj_t arg0, mp_obj_t arg1)
{
float x1 = mp_obj_get_float(arg0);
float y1 = mp_obj_get_float(arg1);
ctx_line_to (ensure_ctx(), x1, y1);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(display_line_to_obj,
mp_display_line_to);
static mp_obj_t mp_display_move_to(mp_obj_t arg0, mp_obj_t arg1)
{
float x1 = mp_obj_get_float(arg0);
float y1 = mp_obj_get_float(arg1);
ctx_move_to (ensure_ctx(), x1, y1);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(display_move_to_obj,
mp_display_move_to);
static mp_obj_t mp_display_quad_to(size_t n_args, const mp_obj_t *args)
{
float x1 = mp_obj_get_float(args[0]);
float y1 = mp_obj_get_float(args[1]);
float x2 = mp_obj_get_float(args[2]);
float y2 = mp_obj_get_float(args[3]);
ctx_quad_to (ensure_ctx(), x1, y1, x2, y2);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
display_quad_to_obj, 4, 4, mp_display_quad_to
);
static mp_obj_t mp_display_linear_gradient(size_t n_args, const mp_obj_t *args)
{
float x1 = mp_obj_get_float(args[0]);
float y1 = mp_obj_get_float(args[1]);
float x2 = mp_obj_get_float(args[2]);
float y2 = mp_obj_get_float(args[3]);
ctx_linear_gradient (ensure_ctx(), x1, y1, x2, y2);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
display_linear_gradient_obj, 4, 4, mp_display_linear_gradient
);
static mp_obj_t mp_display_radial_gradient(size_t n_args, const mp_obj_t *args)
{
float x1 = mp_obj_get_float(args[0]);
float y1 = mp_obj_get_float(args[1]);
float r1 = mp_obj_get_float(args[2]);
float x2 = mp_obj_get_float(args[3]);