Current section
Files
Jump to
Current section
Files
c_src/render_script.c
/*
# Created by Boyd Multerer on June 1, 2018.
# Copyright © 2018 Kry10 Industries. All rights reserved.
#
functions to play a compiled render script
*/
#include <stdio.h>
// #include <string.h>
#include <math.h>
#include <stdlib.h>
// #include <GLFW/glfw3.h>
#include <GLES2/gl2.h>
#include "nanovg/nanovg.h"
#include "types.h"
#include "comms.h"
#include "render_script.h"
#include "tx.h"
// state control
#define OP_PUSH_STATE 0X01
#define OP_POP_STATE 0X02
#define OP_RESET_STATE 0X03
#define OP_RUN_SCRIPT 0X04
// RENDER STYLES
#define OP_PAINT_LINEAR 0X06
#define OP_PAINT_BOX 0X07
#define OP_PAINT_RADIAL 0X08
#define OP_PAINT_IMAGE 0X09
#define OP_PAINT_DYNAMIC 0X0A
// #define OP_ANTI_ALIAS 0X0A
#define OP_STROKE_WIDTH 0X0C
#define OP_STROKE_COLOR 0X0D
#define OP_STROKE_PAINT 0X0E
#define OP_FILL_COLOR 0X10
#define OP_FILL_PAINT 0x11
#define OP_MITER_LIMIT 0X14
#define OP_LINE_CAP 0X15
#define OP_LINE_JOIN 0X16
#define OP_GLOBAL_ALPHA 0X17
// SCISSORING
#define OP_SCISSOR 0X1B
#define OP_INTERSECT_SCISSOR 0X1C
#define OP_RESET_SCISSOR 0X1D
// PATH OPERATIONS
#define OP_PATH_BEGIN 0X20
#define OP_PATH_MOVE_TO 0X21
#define OP_PATH_LINE_TO 0X22
#define OP_PATH_BEZIER_TO 0X23
#define OP_PATH_QUADRATIC_TO 0X24
#define OP_PATH_ARC_TO 0X25
#define OP_PATH_CLOSE 0X26
#define OP_PATH_WINDING 0X27
#define OP_FILL 0X29
#define OP_STROKE 0X2A
#define OP_TRIANGLE 0X2C
#define OP_ARC 0X2D
#define OP_RECT 0X2E
#define OP_ROUND_RECT 0X2F
#define OP_ROUND_RECT_VAR 0X30
#define OP_ELLIPSE 0X31
#define OP_CIRCLE 0X32
#define OP_SECTOR 0X33
#define OP_TEXT 0x34
// TRANSFORM OPERATIONS
#define OP_TX_RESET 0X36
#define OP_TX_IDENTITY 0X37
#define OP_TX_MATRIX 0X38
#define OP_TX_TRANSLATE 0X39
#define OP_TX_SCALE 0X3A
#define OP_TX_ROTATE 0X3B
#define OP_TX_SKEW_X 0X3C
#define OP_TX_SKEW_Y 0X3D
#define OP_FONT 0X40
#define OP_FONT_BLUR 0X41
#define OP_FONT_SIZE 0X42
#define OP_TEXT_ALIGN 0X43
#define OP_TEXT_HEIGHT 0X44
#define OP_TERMINATE 0XFF
static const float TAU = NVG_PI * 2;
NVGpaint current_paint;
//=============================================================================
// access functions for scripts
void delete_script( driver_data_t* p_data, GLuint id ) {
if (p_data->p_scripts[id]) {
free(p_data->p_scripts[id]);
p_data->p_scripts[id] = NULL;
}
}
void delete_all( driver_data_t* p_data ){
for (GLuint i = 0; i < p_data->num_scripts; i++ ) {
delete_script( p_data, i );
}
}
void put_script( driver_data_t* p_data, GLuint id, void* p_script ) {
delete_script( p_data, id );
p_data->p_scripts[id] = p_script;
}
void* get_script( driver_data_t* p_data, GLuint id ) {
return p_data->p_scripts[id];
}
//=============================================================================
// types
typedef struct __attribute__((__packed__))
{
GLuint r;
GLuint g;
GLuint b;
GLuint a;
} color_t;
typedef struct __attribute__((__packed__))
{
GLfloat x;
GLfloat y;
} xy_t;
typedef struct __attribute__((__packed__))
{
GLfloat x;
GLfloat y;
GLfloat w;
GLfloat h;
} xywh_t;
typedef struct __attribute__((__packed__))
{
GLfloat w;
GLfloat h;
} wh_t;
typedef struct __attribute__((__packed__))
{
GLfloat w;
GLfloat h;
GLfloat r;
} whr_t;
typedef struct __attribute__((__packed__))
{
GLfloat c1x;
GLfloat c1y;
GLfloat c2x;
GLfloat c2y;
GLfloat x;
GLfloat y;
} bezier_to_t;
typedef struct __attribute__((__packed__))
{
GLfloat cx;
GLfloat cy;
GLfloat x;
GLfloat y;
} quadratic_to_t;
typedef struct __attribute__((__packed__))
{
GLfloat x1;
GLfloat y1;
GLfloat x2;
GLfloat y2;
GLfloat radius;
} arc_to_t;
// typedef struct __attribute__((__packed__))
// {
// GLfloat cx;
// GLfloat cy;
// GLfloat radius;
// GLfloat a0;
// GLfloat a1;
// byte direction;
// } arc_t;
typedef struct __attribute__((__packed__))
{
GLfloat rx;
GLfloat ry;
} ellipse_t;
typedef struct __attribute__((__packed__))
{
GLfloat r;
} circle_t;
typedef struct __attribute__((__packed__))
{
GLfloat radius;
GLfloat start;
GLfloat finish;
} arc_sector_t;
typedef struct __attribute__((__packed__))
{
GLfloat a;
GLfloat b;
GLfloat c;
GLfloat d;
GLfloat e;
GLfloat f;
} matrix_t;
typedef struct __attribute__((__packed__))
{
GLfloat x0;
GLfloat y0;
GLfloat x1;
GLfloat y1;
GLfloat x2;
GLfloat y2;
} triangle_t;
typedef struct __attribute__((__packed__))
{
GLfloat sx;
GLfloat sy;
GLfloat ex;
GLfloat ey;
GLuint sr;
GLuint sg;
GLuint sb;
GLuint sa;
GLuint er;
GLuint eg;
GLuint eb;
GLuint ea;
} linear_gradient_t;
typedef struct __attribute__((__packed__))
{
GLfloat x;
GLfloat y;
GLfloat w;
GLfloat h;
GLfloat radius;
GLfloat feather;
GLuint sr;
GLuint sg;
GLuint sb;
GLuint sa;
GLuint er;
GLuint eg;
GLuint eb;
GLuint ea;
} box_gradient_t;
typedef struct __attribute__((__packed__))
{
GLfloat cx;
GLfloat cy;
GLfloat r_in;
GLfloat r_out;
GLuint sr;
GLuint sg;
GLuint sb;
GLuint sa;
GLuint er;
GLuint eg;
GLuint eb;
GLuint ea;
} radial_gradient_t;
typedef struct __attribute__((__packed__))
{
GLfloat ox;
GLfloat oy;
GLfloat ex;
GLfloat ey;
GLfloat angle;
GLuint alpha;
GLuint key_size;
} image_pattern_t;
typedef struct __attribute__((__packed__))
{
GLuint size;
} text_t;
//=============================================================================
// operations
//---------------------------------------------------------
// run script
void* internal_run_script( void* p_script, driver_data_t* p_data ) {
GLuint id = *(GLuint*)p_script;
// char buff[200];
// sprintf(buff, "run_script %d", id);
// send_puts( buff );
run_script( id, p_data );
return p_script + sizeof(GLuint);
}
//---------------------------------------------------------
// paint setup
void* paint_linear( NVGcontext* p_ctx, void* p_script ) {
linear_gradient_t* grad = (linear_gradient_t*)p_script;
current_paint = nvgLinearGradient(
p_ctx,
grad->sx, grad->sy, grad->ex, grad->ey,
nvgRGBA(grad->sr, grad->sg, grad->sb, grad->sa),
nvgRGBA(grad->er, grad->eg, grad->eb, grad->ea)
);
return p_script + sizeof(linear_gradient_t);
}
void* paint_box( NVGcontext* p_ctx, void* p_script ) {
box_gradient_t* grad = (box_gradient_t*)p_script;
current_paint = nvgBoxGradient(
p_ctx,
grad->x, grad->y, grad->w, grad->h,
grad->radius, grad->feather,
nvgRGBA(grad->sr, grad->sg, grad->sb, grad->sa),
nvgRGBA(grad->er, grad->eg, grad->eb, grad->ea)
);
return p_script + sizeof(box_gradient_t);
}
void* paint_radial( NVGcontext* p_ctx, void* p_script ) {
radial_gradient_t* grad = (radial_gradient_t*)p_script;
current_paint = nvgRadialGradient(
p_ctx,
grad->cx, grad->cy, grad->r_in, grad->r_out,
nvgRGBA(grad->sr, grad->sg, grad->sb, grad->sa),
nvgRGBA(grad->er, grad->eg, grad->eb, grad->ea)
);
return p_script + sizeof(radial_gradient_t);
}
void* paint_image( NVGcontext* p_ctx, void* p_script, driver_data_t* p_data ) {
image_pattern_t* img = (image_pattern_t*)p_script;
p_script += sizeof(image_pattern_t);
float alpha = (float)img->alpha / 255.0;
// get the image id from the hash.
int id = get_tx_id(p_data->p_tx_ids, p_script);
// if the id is -1, then it isn't loaded
if ( id < 0 ) {
send_static_texture_miss( p_script );
} else {
// if ox, oy, ex, ey are all zero, then use the
// natural h/w of the image
float ox = img->ox;
float oy = img->oy;
float ex = img->ex;
float ey = img->ey;
if ( ox == 0.0 && oy == 0.0 && ex == 0.0 && ey == 0.0 ) {
int w, h;
nvgImageSize(p_ctx, id, &w, &h);
ex = w;
ey = h;
}
// the id is loaded and found
current_paint = nvgImagePattern(
p_ctx,
ox, oy, ex, ey,
img->angle, id, alpha
);
}
return p_script + img->key_size;
}
void* paint_dynamic(NVGcontext* p_ctx, void* p_script, driver_data_t* p_data)
{
image_pattern_t* img = (image_pattern_t*) p_script;
p_script += sizeof(image_pattern_t);
float alpha = (float) img->alpha / 255.0;
// get the image id from the hash.
int id = get_tx_id(p_data->p_tx_ids, p_script);
// if the id is -1, then it isn't loaded
if (id < 0)
{
send_dynamic_texture_miss(p_script);
}
else
{
// if ox, oy, ex, ey are all zero, then use the
// natural h/w of the image
float ox = img->ox;
float oy = img->oy;
float ex = img->ex;
float ey = img->ey;
if (ox == 0.0 && oy == 0.0 && ex == 0.0 && ey == 0.0)
{
int w, h;
nvgImageSize(p_ctx, id, &w, &h);
ex = w;
ey = h;
}
// the id is loaded and found
current_paint =
nvgImagePattern(p_ctx, ox, oy, ex, ey, img->angle, id, alpha);
}
return p_script + img->key_size;
}
//---------------------------------------------------------
// render styles
void* shape_anti_alias( NVGcontext* p_ctx, void* p_script ) {
nvgShapeAntiAlias(p_ctx, *(int*)p_script);
return p_script + sizeof(int);
}
void* stroke_color( NVGcontext* p_ctx, void* p_script ) {
color_t* color = (color_t*)p_script;
nvgStrokeColor(p_ctx, nvgRGBA(color->r, color->g, color->b, color->a));
return p_script + sizeof(color_t);
}
void* shape_width( NVGcontext* p_ctx, void* p_script ) {
nvgStrokeWidth(p_ctx, *(float*)p_script);
return p_script + sizeof(float);
}
void* fill_color( NVGcontext* p_ctx, void* p_script ) {
color_t* color = (color_t*)p_script;
nvgFillColor(p_ctx, nvgRGBA(color->r, color->g, color->b, color->a));
return p_script + sizeof(color_t);
}
void* miter_limit( NVGcontext* p_ctx, void* p_script ) {
nvgMiterLimit(p_ctx, *(float*)p_script);
return p_script + sizeof(float);
}
void* line_cap( NVGcontext* p_ctx, void* p_script ) {
uint32_t join = *(uint32_t*)p_script;
switch( join ) {
case 0: nvgLineCap(p_ctx, NVG_BUTT); break;
case 1: nvgLineCap(p_ctx, NVG_ROUND); break;
case 2: nvgLineCap(p_ctx, NVG_SQUARE); break;
default: break;
}
return p_script + sizeof(uint32_t);
}
void* line_join( NVGcontext* p_ctx, void* p_script ) {
uint32_t join = *(uint32_t*)p_script;
switch( join ) {
case 0: nvgLineJoin(p_ctx, NVG_MITER); break;
case 1: nvgLineJoin(p_ctx, NVG_ROUND); break;
case 2: nvgLineJoin(p_ctx, NVG_BEVEL); break;
default: break;
}
return p_script + sizeof(uint32_t);
}
void* global_alpha( NVGcontext* p_ctx, void* p_script ) {
nvgGlobalAlpha(p_ctx, *(float*)p_script);
return p_script + sizeof(float);
}
//---------------------------------------------------------
// scissors
void* scissor( NVGcontext* p_ctx, void* p_script ) {
wh_t* wh = (wh_t*)p_script;
nvgScissor(p_ctx, 0, 0, wh->w, wh->h);
return p_script + sizeof(wh_t);
}
void* intersect_scissor( NVGcontext* p_ctx, void* p_script ) {
wh_t* wh = (wh_t*)p_script;
nvgIntersectScissor(p_ctx, 0, 0, wh->w, wh->h);
return p_script + sizeof(wh_t);
}
//---------------------------------------------------------
// paths
void* move_to( NVGcontext* p_ctx, void* p_script ) {
xy_t* xywh = (xy_t*)p_script;
nvgMoveTo(p_ctx, xywh->x, xywh->y);
return p_script + sizeof(xy_t);
}
void* line_to( NVGcontext* p_ctx, void* p_script ) {
xy_t* xywh = (xy_t*)p_script;
nvgLineTo(p_ctx, xywh->x, xywh->y);
return p_script + sizeof(xy_t);
}
void* bezier_to( NVGcontext* p_ctx, void* p_script ) {
bezier_to_t* bezier = (bezier_to_t*)p_script;
nvgBezierTo(p_ctx, bezier->c1x, bezier->c1y, bezier->c2x, bezier->c2y, bezier->x, bezier->y);
return p_script + sizeof(bezier_to_t);
}
void* quadratic_to( NVGcontext* p_ctx, void* p_script ) {
quadratic_to_t* quad = (quadratic_to_t*)p_script;
nvgQuadTo(p_ctx, quad->cx, quad->cy, quad->x, quad->y);
return p_script + sizeof(quadratic_to_t);
}
void* arc_to( NVGcontext* p_ctx, void* p_script ) {
arc_to_t* arc = (arc_to_t*)p_script;
nvgArcTo(p_ctx, arc->x1, arc->y1, arc->x2, arc->y2, arc->radius);
return p_script + sizeof(arc_to_t);
}
void* path_winding( NVGcontext* p_ctx, void* p_script ) {
if (*(int*)p_script) {
nvgPathWinding(p_ctx, NVG_SOLID);
} else {
nvgPathWinding(p_ctx, NVG_HOLE);
}
return p_script + sizeof(int);
}
void* triangle( NVGcontext* p_ctx, void* p_script ) {
triangle_t* tri = (triangle_t*)p_script;
nvgMoveTo(p_ctx, tri->x0, tri->y0);
nvgLineTo(p_ctx, tri->x1, tri->y1);
nvgLineTo(p_ctx, tri->x2, tri->y2);
nvgClosePath(p_ctx);
return p_script + sizeof(triangle_t);
}
void* rect( NVGcontext* p_ctx, void* p_script ) {
wh_t* wh = (wh_t*)p_script;
nvgRect(p_ctx, 0, 0, wh->w, wh->h);
return p_script + sizeof(wh_t);
}
void* round_rect( NVGcontext* p_ctx, void* p_script ) {
whr_t* whr = (whr_t*)p_script;
nvgRoundedRect(p_ctx, 0, 0, whr->w, whr->h, whr->r);
return p_script + sizeof(whr_t);
}
void* ellipse( NVGcontext* p_ctx, void* p_script ) {
ellipse_t* ellipse = (ellipse_t*)p_script;
nvgEllipse(p_ctx, 0, 0, ellipse->rx, ellipse->ry);
return p_script + sizeof(ellipse_t);
}
void* circle( NVGcontext* p_ctx, void* p_script ) {
GLfloat radius = *(GLfloat*)p_script;
nvgCircle(p_ctx, 0, 0, radius);
return p_script + sizeof(GLfloat);
}
void* arc( NVGcontext* p_ctx, void* p_script ) {
// bring sector data onto the stack
arc_sector_t sector = *(arc_sector_t*)p_script;
// clamp the angle to a circle
float angle = sector.finish - sector.start;
angle = angle > TAU ? TAU : angle;
angle = angle < -TAU ? -TAU : angle;
// calculate the number of segments
int segment_count = log2(sector.radius) * fabsf(angle) * 2;
float increment = angle / segment_count;
float a = sector.start;
// don't draw anything if the angle is so small that the segment_count is zero
if ( segment_count > 0 ) {
// Arc starts on the perimeter. Sector starts in the center.
for (int i = 0; i <= segment_count; ++i) {
float px, py;
px = sector.radius * cos(a);
py = sector.radius * sin(a);
if (i == 0 ) {
nvgMoveTo(p_ctx, px, py);
} else {
nvgLineTo(p_ctx, px, py);
}
a += increment ;
}
// arc doesn't close
}
return p_script + sizeof(arc_sector_t);
}
void* sector( NVGcontext* p_ctx, void* p_script ) {
// bring sector data onto the stack
arc_sector_t sector = *(arc_sector_t*)p_script;
// clamp the angle to a circle
float angle = sector.finish - sector.start;
angle = angle > TAU ? TAU : angle;
angle = angle < -TAU ? -TAU : angle;
// calculate the number of segments
int segment_count = log2(sector.radius) * fabsf(angle) * 2;
float increment = angle / segment_count;
float a = sector.start;
// don't draw anything if the angle is so small that the segment_count is zero
if ( segment_count > 0 ) {
// Arc starts on the perimeter. Sector starts in the center.
nvgMoveTo(p_ctx, 0, 0);
for (int i = 0; i <= segment_count; ++i) {
float px, py;
px = sector.radius * cos(a);
py = sector.radius * sin(a);
nvgLineTo(p_ctx, px, py);
a += increment ;
}
nvgClosePath(p_ctx);
}
return p_script + sizeof(arc_sector_t);
}
void* text( NVGcontext* p_ctx, void* p_script ) {
text_t* text_info = (text_t*)p_script;
p_script += sizeof(text_t);
float x = 0;
float y = 0;
const char* start = p_script;
const char* end = start + text_info->size;
float lineh;
nvgTextMetrics(p_ctx, NULL, NULL, &lineh);
NVGtextRow rows[3];
int nrows, i;
// up to this code to break the lines...
while ((nrows = nvgTextBreakLines(p_ctx, start, end, 1000, rows, 3))) {
for (i = 0; i < nrows; i++) {
NVGtextRow* row = &rows[i];
nvgText(p_ctx, x, y, row->start, row->end);
y += lineh;
}
// Keep going...
start = rows[nrows-1].next;
}
// Text is padded to 32-bits
return p_script + ((text_info->size + 3) & ~3);
}
// typedef struct __attribute__((__packed__))
// {
// GLfloat x;
// GLfloat y;
// GLuint size;
// } text_t;
//---------------------------------------------------------
// transforms
void* tx_rotate( NVGcontext* p_ctx, void* p_script ) {
nvgRotate(p_ctx, *(float*)p_script);
return p_script + sizeof(float);
}
void* tx_translate( NVGcontext* p_ctx, void* p_script ) {
xy_t* xy = (xy_t*)p_script;
nvgTranslate(p_ctx, xy->x, xy->y);
return p_script + sizeof(xy_t);
}
void* tx_scale( NVGcontext* p_ctx, void* p_script ) {
xy_t* xy = (xy_t*)p_script;
nvgScale(p_ctx, xy->x, xy->y);
return p_script + sizeof(xy_t);
}
void* tx_skew_x( NVGcontext* p_ctx, void* p_script ) {
nvgSkewX(p_ctx, *(float*)p_script);
return p_script + sizeof(float);
}
void* tx_skew_y( NVGcontext* p_ctx, void* p_script ) {
nvgSkewY(p_ctx, *(float*)p_script);
return p_script + sizeof(float);
}
void* tx_matrix( NVGcontext* p_ctx, void* p_script ) {
matrix_t* tx = (matrix_t*)p_script;
nvgTransform(p_ctx, tx->a, tx->b, tx->c, tx->d, tx->e, tx->f);
return p_script + sizeof(matrix_t);
}
//---------------------------------------------------------
// font styles
void* font( NVGcontext* p_ctx, void* p_script ) {
GLuint name_length = *(GLuint*)p_script;
p_script += sizeof(GLuint);
// get the id for the font. If it isn't loaded, request it
int font_id = nvgFindFont(p_ctx, p_script);
if ( font_id >= 0 ) {
nvgFontFaceId(p_ctx, font_id);
} else {
// the font is NOT loaded. Request it from the ex code above
send_font_miss( p_script );
}
return p_script + name_length;
}
void* font_blur( NVGcontext* p_ctx, void* p_script ) {
nvgFontBlur(p_ctx, *(float*)p_script);
return p_script + sizeof(float);
}
void* font_size( NVGcontext* p_ctx, void* p_script ) {
nvgFontSize(p_ctx, *(float*)p_script);
return p_script + sizeof(float);
}
void* text_align( NVGcontext* p_ctx, void* p_script ) {
nvgTextAlign(p_ctx, *(uint32_t*)p_script);
return p_script + sizeof(uint32_t);
}
void* text_height( NVGcontext* p_ctx, void* p_script ) {
nvgTextLineHeight(p_ctx, *(float*)p_script);
return p_script + sizeof(float);
}
//=============================================================================
// the main script function
//---------------------------------------------------------
void run_script( GLuint script_id, driver_data_t* p_data ) {
char buff[200];
// sprintf(buff, "script id: %d", script_id);
// send_puts(buff);
// get the script in question. bail if it isn't there
void* p_script = get_script( p_data, script_id );
if (p_script == NULL) {
// sprintf(buff, "Tried to render NULL script %d", script_id);
// send_puts( buff );
return;
};
// setup
NVGcontext* p_ctx = p_data->p_ctx;
// get the first op
GLuint op = *(GLuint*)p_script;
// loop though the script, running each command in turn.
// recurse into more script calls if necessary
while ( op != OP_TERMINATE ) {
// sprintf(buff, "op: 0x%X", op);
// send_puts(buff);
// advance the pointer past the op code
p_script += sizeof(GLuint);
// take the appropriate action based on the command id
switch( op ) {
// state control
case OP_PUSH_STATE: nvgSave(p_ctx); break;
case OP_POP_STATE: nvgRestore(p_ctx); break;
case OP_RESET_STATE: nvgReset(p_ctx); break;
// script control
case OP_RUN_SCRIPT: p_script = internal_run_script( p_script, p_data ); break;
// render styles
case OP_PAINT_LINEAR: p_script = paint_linear( p_ctx, p_script ); break;
case OP_PAINT_BOX: p_script = paint_box( p_ctx, p_script ); break;
case OP_PAINT_RADIAL: p_script = paint_radial( p_ctx, p_script ); break;
case OP_PAINT_IMAGE:
p_script = paint_image(p_ctx, p_script, p_data);
break;
case OP_PAINT_DYNAMIC:
p_script = paint_dynamic(p_ctx, p_script, p_data);
break;
// case OP_ANTI_ALIAS: p_script = shape_anti_alias( p_ctx, p_script ); break;
case OP_STROKE_WIDTH: p_script = shape_width( p_ctx, p_script ); break;
case OP_STROKE_COLOR: p_script = stroke_color( p_ctx, p_script ); break;
case OP_STROKE_PAINT: nvgStrokePaint(p_ctx, current_paint); break;
case OP_FILL_COLOR: p_script = fill_color( p_ctx, p_script ); break;
case OP_FILL_PAINT: nvgFillPaint(p_ctx, current_paint); break;
case OP_MITER_LIMIT: p_script = miter_limit( p_ctx, p_script ); break;
case OP_LINE_CAP: p_script = line_cap( p_ctx, p_script ); break;
case OP_LINE_JOIN: p_script = line_join( p_ctx, p_script ); break;
case OP_GLOBAL_ALPHA: p_script = global_alpha( p_ctx, p_script ); break;
// scissoring
case OP_SCISSOR: p_script = scissor( p_ctx, p_script ); break;
case OP_INTERSECT_SCISSOR: p_script = intersect_scissor( p_ctx, p_script ); break;
case OP_RESET_SCISSOR: nvgResetScissor(p_ctx); break;
// path operations
case OP_PATH_BEGIN: nvgBeginPath(p_ctx); break;
case OP_PATH_MOVE_TO: p_script = move_to( p_ctx, p_script ); break;
case OP_PATH_LINE_TO: p_script = line_to( p_ctx, p_script ); break;
case OP_PATH_BEZIER_TO: p_script = bezier_to( p_ctx, p_script ); break;
case OP_PATH_QUADRATIC_TO: p_script = quadratic_to( p_ctx, p_script ); break;
case OP_PATH_ARC_TO: p_script = arc_to( p_ctx, p_script ); break;
case OP_PATH_CLOSE: nvgClosePath(p_ctx); break;
case OP_PATH_WINDING: p_script = path_winding( p_ctx, p_script ); break;
case OP_FILL: nvgFill(p_ctx); break;
case OP_STROKE: nvgStroke(p_ctx); break;
case OP_TRIANGLE: p_script = triangle( p_ctx, p_script ); break;
case OP_ARC: p_script = arc( p_ctx, p_script ); break;
case OP_RECT: p_script = rect( p_ctx, p_script ); break;
case OP_ROUND_RECT: p_script = round_rect( p_ctx, p_script ); break;
case OP_ROUND_RECT_VAR: break;
case OP_ELLIPSE: p_script = ellipse( p_ctx, p_script ); break;
case OP_CIRCLE: p_script = circle( p_ctx, p_script ); break;
case OP_SECTOR: p_script = sector( p_ctx, p_script ); break;
case OP_TEXT: p_script = text( p_ctx, p_script ); break;
// transform operations
case OP_TX_RESET: nvgResetTransform(p_ctx); break;
case OP_TX_IDENTITY: break;
case OP_TX_MATRIX: p_script = tx_matrix( p_ctx, p_script ); break;
case OP_TX_TRANSLATE: p_script = tx_translate( p_ctx, p_script ); break;
case OP_TX_SCALE: p_script = tx_scale( p_ctx, p_script ); break;
case OP_TX_ROTATE: p_script = tx_rotate( p_ctx, p_script ); break;
case OP_TX_SKEW_X: p_script = tx_skew_x( p_ctx, p_script ); break;
case OP_TX_SKEW_Y: p_script = tx_skew_y( p_ctx, p_script ); break;
// font styles
case OP_FONT: p_script = font( p_ctx, p_script ); break;
case OP_FONT_BLUR: p_script = font_blur( p_ctx, p_script ); break;
case OP_FONT_SIZE: p_script = font_size( p_ctx, p_script ); break;
case OP_TEXT_ALIGN: p_script = text_align( p_ctx, p_script ); break;
case OP_TEXT_HEIGHT: p_script = text_height( p_ctx, p_script ); break;
case OP_TERMINATE: return;
default:
sprintf(buff, "!!!Unknown script command: %d", op);
send_puts( buff );
// send_puts( "!!!Unknown script command" );
return;
}
// prep the next op code
op = *(GLuint*)p_script;
}
}