Skip to content

Instantly share code, notes, and snippets.

@arce
Created March 26, 2020 15:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arce/a9bc3b499ed78fb5c3f51357d0511f70 to your computer and use it in GitHub Desktop.
Save arce/a9bc3b499ed78fb5c3f51357d0511f70 to your computer and use it in GitHub Desktop.
libshape.c
Pull requests
Issues
Marketplace
Explore
@arce
mgthomas99
/
easy-vg
forked from ajstarks/openvg
Watch 1
Star 1
Fork 80
Code Issues 2 Pull requests 0 Actions Projects 1 Wiki Security Insights
Branch: master
easy-vg/src/libshapes.c
Find file Copy path
@mgthomas99 mgthomas99 fixed function name
5a03d53 on Jun 11, 2018
1 contributor
740 lines (645 sloc) 22.8 KB
RawBlameHistory
/**
* High-level OpenVG API.
*
* @author Anthony Starks <ajstarks@gmail.com>
* @author George Thomas <m.g.thomas99@gmail.com>
* @author <github.com/paeryn>
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <jpeglib.h>
#include "EGL/egl.h"
#include "VG/openvg.h"
#include "VG/vgu.h"
#include "bcm_host.h"
#include "fontinfo.h"
#include "oglinit.h"
#include "./../lib/DejaVuSans.inc"
// createImageFromJpeg decompresses a JPEG image to the standard image format
// source: https://github.com/ileben/ShivaVG/blob/master/examples/test_image.c
VGImage createImageFromJpeg(const char *filename) {
FILE *infile;
struct jpeg_decompress_struct jdc;
struct jpeg_error_mgr jerr;
JSAMPARRAY buffer;
unsigned int bstride;
unsigned int bbpp;
VGImage img;
VGubyte *data;
unsigned int width;
unsigned int height;
unsigned int dstride;
unsigned int dbpp;
VGubyte *brow;
VGubyte *drow;
unsigned int x;
unsigned int lilEndianTest = 1;
VGImageFormat rgbaFormat;
// Check for endianness
if (((unsigned char *)&lilEndianTest)[0] == 1)
rgbaFormat = VG_sABGR_8888;
else
rgbaFormat = VG_sRGBA_8888;
// Try to open image file
infile = fopen(filename, "rb");
if (infile == NULL) {
printf("Failed opening '%s' for reading!\n", filename);
return VG_INVALID_HANDLE;
}
// Setup default error handling
jdc.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&jdc);
// Set input file
jpeg_stdio_src(&jdc, infile);
// Read header and start
jpeg_read_header(&jdc, TRUE);
jpeg_start_decompress(&jdc);
width = jdc.output_width;
height = jdc.output_height;
// Allocate buffer using jpeg allocator
bbpp = jdc.output_components;
bstride = width * bbpp;
buffer = (*jdc.mem->alloc_sarray)
((j_common_ptr) & jdc, JPOOL_IMAGE, bstride, 1);
// Allocate image data buffer
dbpp = 4;
dstride = width * dbpp;
data = (VGubyte *) malloc(dstride * height);
// Iterate until all scanlines processed
while (jdc.output_scanline < height) {
// Read scanline into buffer
jpeg_read_scanlines(&jdc, buffer, 1);
drow = data + (height - jdc.output_scanline) * dstride;
brow = buffer[0];
// Expand to RGBA
for (x = 0; x < width; ++x, drow += dbpp, brow += bbpp) {
switch (bbpp) {
case 4:
drow[0] = brow[0];
drow[1] = brow[1];
drow[2] = brow[2];
drow[3] = brow[3];
break;
case 3:
drow[0] = brow[0];
drow[1] = brow[1];
drow[2] = brow[2];
drow[3] = 255;
break;
}
}
}
// Create VG image
img = vgCreateImage(rgbaFormat, width, height, VG_IMAGE_QUALITY_BETTER);
vgImageSubData(img, data, dstride, rgbaFormat, 0, 0, width, height);
// Cleanup
jpeg_destroy_decompress(&jdc);
fclose(infile);
free(data);
return img;
}
// makeimage makes an image from a raw raster of red, green, blue, alpha values
void makeimage(VGfloat x, VGfloat y, int w, int h, VGubyte * data) {
unsigned int dstride = w * 4;
VGImageFormat rgbaFormat = VG_sABGR_8888;
VGImage img = vgCreateImage(rgbaFormat, w, h, VG_IMAGE_QUALITY_BETTER);
vgImageSubData(img, (void *)data, dstride, rgbaFormat, 0, 0, w, h);
vgSetPixels(x, y, img, 0, 0, w, h);
vgDestroyImage(img);
}
static EVG_STATE_T _state, *state = &_state; // global graphics state
static const int MAXFONTPATH = 500;
static int init_x = 0; // Initial window position and size
static int init_y = 0;
static unsigned int init_w = 0;
static unsigned int init_h = 0;
//
// Terminal settings
//
// terminal settings structures
struct termios new_term_attr;
struct termios orig_term_attr;
// saveterm saves the current terminal settings
void saveterm() {
tcgetattr(fileno(stdin), &orig_term_attr);
}
// rawterm sets the terminal to raw mode
void rawterm() {
memcpy(&new_term_attr, &orig_term_attr, sizeof(struct termios));
new_term_attr.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL);
new_term_attr.c_cc[VTIME] = 0;
new_term_attr.c_cc[VMIN] = 0;
tcsetattr(fileno(stdin), TCSANOW, &new_term_attr);
}
// restore resets the terminal to the previously saved setting
void restoreterm() {
tcsetattr(fileno(stdin), TCSANOW, &orig_term_attr);
}
//
// Font functions
//
// loadfont loads font path data
// derived from http://web.archive.org/web/20070808195131/http://developer.hybrid.fi/font2openvg/renderFont.cpp.txt
Fontinfo loadfont(const int *Points,
const int *PointIndices,
const unsigned char *Instructions,
const int *InstructionIndices,
const int *InstructionCounts,
const int *adv,
const short *cmap,
int ng) {
Fontinfo f;
int i;
memset(f.Glyphs, 0, MAXFONTPATH * sizeof(VGPath));
if (ng > MAXFONTPATH) {
return f;
}
for (i = 0; i < ng; i++) {
const int *p = &Points[PointIndices[i] * 2];
const unsigned char *instructions = &Instructions[InstructionIndices[i]];
int ic = InstructionCounts[i];
VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_S_32,
1.0f / 65536.0f, 0.0f, 0, 0,
VG_PATH_CAPABILITY_ALL);
f.Glyphs[i] = path;
if (ic) {
vgAppendPathData(path, ic, instructions, p);
}
}
f.CharacterMap = cmap;
f.GlyphAdvances = adv;
f.Count = ng;
f.descender_height = 0;
f.font_height = 0;
return f;
}
// unloadfont frees font path data
void unloadfont(VGPath * glyphs, int n) {
int i;
for (i = 0; i < n; i++) {
vgDestroyPath(glyphs[i]);
}
}
// Image places an image at the specifed location
void Image(VGfloat x, VGfloat y, int w, int h, const char *filename) {
VGImage img = createImageFromJpeg(filename);
vgSetPixels(x, y, img, 0, 0, w, h);
vgDestroyImage(img);
}
// dumpscreen writes the raster
void dumpscreen(int w, int h, FILE * fp) {
void *ScreenBuffer = malloc(w * h * 4);
vgReadPixels(ScreenBuffer, (w * 4), VG_sABGR_8888, 0, 0, w, h);
fwrite(ScreenBuffer, 1, w * h * 4, fp);
free(ScreenBuffer);
}
Fontinfo SansTypeface;
// initWindowSize requests a specific window size & position, if not called
// then init() will open a full screen window.
// Done this way to preserve the original init() behaviour.
void initWindowSize(int x, int y, unsigned int w, unsigned int h) {
init_x = x;
init_y = y;
init_w = w;
init_h = h;
}
// init sets the system to its initial state
void evgInit(int *w, int *h) {
bcm_host_init();
memset(state, 0, sizeof(*state));
state->window_x = init_x;
state->window_y = init_y;
state->window_width = init_w;
state->window_height = init_h;
oglinit(state);
SansTypeface = loadfont(DejaVuSans_glyphPoints,
DejaVuSans_glyphPointIndices,
DejaVuSans_glyphInstructions,
DejaVuSans_glyphInstructionIndices,
DejaVuSans_glyphInstructionCounts,
DejaVuSans_glyphAdvances,
DejaVuSans_characterMap,
DejaVuSans_glyphCount);
SansTypeface.descender_height = DejaVuSans_descender_height;
SansTypeface.font_height = DejaVuSans_font_height;
*w = state->window_width;
*h = state->window_height;
}
// AreaClear clears a given rectangle in window coordinates (not affected by
// transformations)
void evgClearRect(unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
vgClear(x, y, w, h);
}
// WindowClear clears the window to previously set background colour
void evgClear() {
evgClearRect(0, 0, state->window_width, state->window_height);
}
// finish cleans up
void evgFinish() {
unloadfont(SansTypeface.Glyphs, SansTypeface.Count);
eglSwapBuffers(state->display, state->surface);
eglMakeCurrent(state->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface(state->display, state->surface);
eglDestroyContext(state->display, state->context);
eglTerminate(state->display);
}
//
// Transformations
//
// Translate the coordinate system to x,y
void evgTranslate(VGfloat x, VGfloat y) {
vgTranslate(x, y);
}
// Rotate around angle r
void evgRotate(VGfloat r) {
vgRotate(r);
}
// Shear shears the x coordinate by x degrees, the y coordinate by y degrees
void evgShear(VGfloat x, VGfloat y) {
vgShear(x, y);
}
// Scale scales by x, y
void evgScale(VGfloat x, VGfloat y) {
vgScale(x, y);
}
//
// Style functions
//
// setfill sets the fill color
void evgSetFill(VGfloat color[4]) {
VGPaint fillPaint = vgCreatePaint();
vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, color);
vgSetPaint(fillPaint, VG_FILL_PATH);
vgDestroyPaint(fillPaint);
}
// setstroke sets the stroke color
void evgSetStroke(VGfloat color[4]) {
VGPaint strokePaint = vgCreatePaint();
vgSetParameteri(strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(strokePaint, VG_PAINT_COLOR, 4, color);
vgSetPaint(strokePaint, VG_STROKE_PATH);
vgDestroyPaint(strokePaint);
}
// StrokeWidth sets the stroke width
void evgStrokeWidth(VGfloat width) {
vgSetf(VG_STROKE_LINE_WIDTH, width);
vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
}
//
// Color functions
//
//
// RGBA fills a color vectors from a RGBA quad.
void RGBA(unsigned int r, unsigned int g, unsigned int b, VGfloat a, VGfloat color[4]) {
if (r > 255) {
r = 0;
}
if (g > 255) {
g = 0;
}
if (b > 255) {
b = 0;
}
if (a < 0.0 || a > 1.0) {
a = 1.0;
}
color[0] = (VGfloat) r / 255.0f;
color[1] = (VGfloat) g / 255.0f;
color[2] = (VGfloat) b / 255.0f;
color[3] = a;
}
// RGB returns a solid color from a RGB triple
void RGB(unsigned int r, unsigned int g, unsigned int b, VGfloat color[4]) {
RGBA(r, g, b, 1.0f, color);
}
// Stroke sets the stroke color, defined as a RGB triple.
void evgStroke(unsigned int r, unsigned int g, unsigned int b, VGfloat a) {
VGfloat color[4];
RGBA(r, g, b, a, color);
evgSetStroke(color);
}
// Fill sets the fillcolor, defined as a RGBA quad.
void evgFill(unsigned int r, unsigned int g, unsigned int b, VGfloat a) {
VGfloat color[4];
RGBA(r, g, b, a, color);
evgSetFill(color);
}
// setstops sets color stops for gradients
void evgSetStop(VGPaint paint, VGfloat * stops, int n) {
VGboolean multmode = VG_FALSE;
VGColorRampSpreadMode spreadmode = VG_COLOR_RAMP_SPREAD_REPEAT;
vgSetParameteri(paint, VG_PAINT_COLOR_RAMP_SPREAD_MODE, spreadmode);
vgSetParameteri(paint, VG_PAINT_COLOR_RAMP_PREMULTIPLIED, multmode);
vgSetParameterfv(paint, VG_PAINT_COLOR_RAMP_STOPS, 5 * n, stops);
vgSetPaint(paint, VG_FILL_PATH);
}
// LinearGradient fills with a linear gradient
void evgFillLinearGradient(VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2, VGfloat * stops, int ns) {
VGfloat lgcoord[4] = { x1, y1, x2, y2 };
VGPaint paint = vgCreatePaint();
vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT);
vgSetParameterfv(paint, VG_PAINT_LINEAR_GRADIENT, 4, lgcoord);
evgSetStop(paint, stops, ns);
vgDestroyPaint(paint);
}
// RadialGradient fills with a linear gradient
void evgFillRadialGradient(VGfloat cx, VGfloat cy, VGfloat fx, VGfloat fy, VGfloat radius, VGfloat * stops, int ns) {
VGfloat radialcoord[5] = { cx, cy, fx, fy, radius };
VGPaint paint = vgCreatePaint();
vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_RADIAL_GRADIENT);
vgSetParameterfv(paint, VG_PAINT_RADIAL_GRADIENT, 5, radialcoord);
evgSetStop(paint, stops, ns);
vgDestroyPaint(paint);
}
// ClipRect limits the drawing area to specified rectangle
void evgClipRect(VGint x, VGint y, VGint w, VGint h) {
vgSeti(VG_SCISSORING, VG_TRUE);
VGint coords[4] = { x, y, w, h };
vgSetiv(VG_SCISSOR_RECTS, 4, coords);
}
// ClipEnd stops limiting drawing area to specified rectangle
void evgClipEnd() {
vgSeti(VG_SCISSORING, VG_FALSE);
}
// Text Functions
// next_utf_char handles UTF encoding
unsigned char *next_utf8_char(unsigned char *utf8, int *codepoint) {
int seqlen;
int datalen = (int)strlen((const char *)utf8);
unsigned char *p = utf8;
if (datalen < 1 || *utf8 == 0) { // End of string
return NULL;
}
if (!(utf8[0] & 0x80)) { // 0xxxxxxx
*codepoint = (wchar_t) utf8[0];
seqlen = 1;
} else if ((utf8[0] & 0xE0) == 0xC0) { // 110xxxxx
*codepoint = (int)(((utf8[0] & 0x1F) << 6) | (utf8[1] & 0x3F));
seqlen = 2;
} else if ((utf8[0] & 0xF0) == 0xE0) { // 1110xxxx
*codepoint = (int)(((utf8[0] & 0x0F) << 12) | ((utf8[1] & 0x3F) << 6) | (utf8[2] & 0x3F));
seqlen = 3;
} else {
return NULL; // No code points this high here
}
p += seqlen;
return p;
}
// Text renders a string of text at a specified location, size, using the specified font glyphs
// derived from http://web.archive.org/web/20070808195131/http://developer.hybrid.fi/font2openvg/renderFont.cpp.txt
void evgText(VGfloat x, VGfloat y, const char *s, Fontinfo f, int pointsize) {
VGfloat size = (VGfloat) pointsize, xx = x, mm[9];
vgGetMatrix(mm);
int character;
unsigned char *ss = (unsigned char *)s;
while ((ss = next_utf8_char(ss, &character)) != NULL) {
int glyph = f.CharacterMap[character];
if (character >= MAXFONTPATH-1) {
continue;
}
if (glyph == -1) {
continue; //glyph is undefined
}
VGfloat mat[9] = {
size, 0.0f, 0.0f,
0.0f, size, 0.0f,
xx, y, 1.0f
};
vgLoadMatrix(mm);
vgMultMatrix(mat);
vgDrawPath(f.Glyphs[glyph], VG_FILL_PATH);
xx += size * f.GlyphAdvances[glyph] / 65536.0f;
}
vgLoadMatrix(mm);
}
// TextWidth returns the width of a text string at the specified font and size.
VGfloat TextWidth(const char *s, Fontinfo f, int pointsize) {
VGfloat tw = 0.0;
VGfloat size = (VGfloat) pointsize;
int character;
unsigned char *ss = (unsigned char *)s;
while ((ss = next_utf8_char(ss, &character)) != NULL) {
int glyph = f.CharacterMap[character];
if (character >= MAXFONTPATH-1) {
continue;
}
if (glyph == -1) {
continue; //glyph is undefined
}
tw += size * f.GlyphAdvances[glyph] / 65536.0f;
}
return tw;
}
// TextMid draws text, centered on (x,y)
void evgTextMid(VGfloat x, VGfloat y, const char *s, Fontinfo f, int pointsize) {
VGfloat tw = TextWidth(s, f, pointsize);
evgText(x - (tw / 2.0), y, s, f, pointsize);
}
// TextEnd draws text, with its end aligned to (x,y)
void evgTextEnd(VGfloat x, VGfloat y, const char *s, Fontinfo f, int pointsize) {
VGfloat tw = TextWidth(s, f, pointsize);
evgText(x - tw, y, s, f, pointsize);
}
// TextHeight reports a font's height
VGfloat TextHeight(Fontinfo f, int pointsize) {
return (f.font_height * pointsize) / 65536;
}
// TextDepth reports a font's depth (how far under the baseline it goes)
VGfloat TextDepth(Fontinfo f, int pointsize) {
return (-f.descender_height * pointsize) / 65536;
}
//
// Shape functions
//
// newpath creates path data
// Changed capabilities as others not needed at the moment - allows possible
// driver optimisations.
VGPath evgNewPath() {
return vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_APPEND_TO); // Other capabilities not needed
}
// makecurve makes path data using specified segments and coordinates
void evgMakeCurve(VGubyte * segments, VGfloat * coords, VGbitfield flags) {
VGPath path = evgNewPath();
vgAppendPathData(path, 2, segments, coords);
vgDrawPath(path, flags);
vgDestroyPath(path);
}
// CBezier makes a quadratic bezier curve
void evgCbezier(VGfloat sx, VGfloat sy, VGfloat cx, VGfloat cy, VGfloat px, VGfloat py, VGfloat ex, VGfloat ey) {
VGubyte segments[] = { VG_MOVE_TO_ABS, VG_CUBIC_TO };
VGfloat coords[] = { sx, sy, cx, cy, px, py, ex, ey };
evgMakeCurve(segments, coords, VG_FILL_PATH | VG_STROKE_PATH);
}
// QBezier makes a quadratic bezier curve
void evgQbezier(VGfloat sx, VGfloat sy, VGfloat cx, VGfloat cy, VGfloat ex, VGfloat ey) {
VGubyte segments[] = { VG_MOVE_TO_ABS, VG_QUAD_TO };
VGfloat coords[] = { sx, sy, cx, cy, ex, ey };
evgMakeCurve(segments, coords, VG_FILL_PATH | VG_STROKE_PATH);
}
// interleave interleaves arrays of x, y into a single array
void interleave(VGfloat * x, VGfloat * y, int n, VGfloat * points) {
while (n--) {
*points++ = *x++;
*points++ = *y++;
}
}
// poly makes either a polygon or polyline
void evgPoly(VGfloat * x, VGfloat * y, VGint n, VGbitfield flag) {
VGfloat points[n * 2];
VGPath path = evgNewPath();
interleave(x, y, n, points);
vguPolygon(path, points, n, VG_FALSE);
vgDrawPath(path, flag);
vgDestroyPath(path);
}
// Polygon makes a filled polygon with vertices in x, y arrays
void evgPolygon(VGfloat * x, VGfloat * y, VGint n) {
evgPoly(x, y, n, VG_FILL_PATH);
}
// Polyline makes a polyline with vertices at x, y arrays
void evgPolyline(VGfloat * x, VGfloat * y, VGint n) {
evgPoly(x, y, n, VG_STROKE_PATH);
}
// Rect makes a rectangle at the specified location and dimensions
void evgRect(VGfloat x, VGfloat y, VGfloat w, VGfloat h) {
VGPath path = evgNewPath();
vguRect(path, x, y, w, h);
vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH);
vgDestroyPath(path);
}
// Line makes a line from (x1,y1) to (x2,y2)
void evgLine(VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2) {
VGPath path = evgNewPath();
vguLine(path, x1, y1, x2, y2);
vgDrawPath(path, VG_STROKE_PATH);
vgDestroyPath(path);
}
// Roundrect makes an rounded rectangle at the specified location and dimensions
void evgRoundRect(VGfloat x, VGfloat y, VGfloat w, VGfloat h, VGfloat rw, VGfloat rh) {
VGPath path = evgNewPath();
vguRoundRect(path, x, y, w, h, rw, rh);
vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH);
vgDestroyPath(path);
}
// Ellipse makes an ellipse at the specified location and dimensions
void evgEllipse(VGfloat x, VGfloat y, VGfloat w, VGfloat h) {
VGPath path = evgNewPath();
vguEllipse(path, x, y, w, h);
vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH);
vgDestroyPath(path);
}
// Circle makes a circle at the specified location and dimensions
void evgCircle(VGfloat x, VGfloat y, VGfloat r) {
evgEllipse(x, y, r, r);
}
// Arc makes an elliptical arc at the specified location and dimensions
void evgArc(VGfloat x, VGfloat y, VGfloat w, VGfloat h, VGfloat sa, VGfloat aext) {
VGPath path = evgNewPath();
vguArc(path, x, y, w, h, sa, aext, VGU_ARC_OPEN);
vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH);
vgDestroyPath(path);
}
// Start begins the picture, clearing a rectangular region with a specified color
void evgBegin() {
VGfloat color[4] = { 0, 0, 0, 1 };
evgSetFill(color);
evgSetStroke(color);
evgStrokeWidth(0);
vgLoadIdentity();
}
// End checks for errors, and renders to the display
void evgEnd() {
assert(vgGetError() == VG_NO_ERROR);
eglSwapBuffers(state->display, state->surface);
assert(eglGetError() == EGL_SUCCESS);
}
// SaveEnd dumps the raster before rendering to the display
void evgSaveEnd(const char *filename) {
FILE *fp;
assert(vgGetError() == VG_NO_ERROR);
if (strlen(filename) == 0) {
dumpscreen(state->screen_width, state->screen_height, stdout);
} else {
fp = fopen(filename, "wb");
if (fp != NULL) {
dumpscreen(state->screen_width, state->screen_height, fp);
fclose(fp);
}
}
eglSwapBuffers(state->display, state->surface);
assert(eglGetError() == EGL_SUCCESS);
}
// Backgroud clears the screen to a solid background color
void evgBackground(unsigned int r, unsigned int g, unsigned int b) {
VGfloat colour[4];
RGB(r, g, b, colour);
vgSetfv(VG_CLEAR_COLOR, 4, colour);
evgClear();
}
// BackgroundRGB clears the screen to a background color with alpha
void evgBackgroundRGB(unsigned int r, unsigned int g, unsigned int b, VGfloat a) {
VGfloat colour[4];
RGBA(r, g, b, a, colour);
vgSetfv(VG_CLEAR_COLOR, 4, colour);
evgClear();
}
// WindowOpacity sets the window opacity
void evgWindowOpacity(unsigned int a) {
dispmanChangeWindowOpacity(state, a);
}
// WindowPosition moves the window to given position
void WindowPosition(int x, int y) {
dispmanMoveWindow(state, x, y);
}
// Outlined shapes
// Hollow shapes -because filling still happens even with a fill of 0,0,0,0
// unlike where using a strokewidth of 0 disables the stroke.
// Either this or change the original functions to require the VG_x_PATH flags
// CBezier makes a quadratic bezier curve, stroked
void CbezierOutline(VGfloat sx, VGfloat sy, VGfloat cx, VGfloat cy, VGfloat px, VGfloat py, VGfloat ex, VGfloat ey) {
VGubyte segments[] = { VG_MOVE_TO_ABS, VG_CUBIC_TO };
VGfloat coords[] = { sx, sy, cx, cy, px, py, ex, ey };
evgMakeCurve(segments, coords, VG_STROKE_PATH);
}
// QBezierOutline makes a quadratic bezier curve, outlined
void QbezierOutline(VGfloat sx, VGfloat sy, VGfloat cx, VGfloat cy, VGfloat ex, VGfloat ey) {
VGubyte segments[] = { VG_MOVE_TO_ABS, VG_QUAD_TO };
VGfloat coords[] = { sx, sy, cx, cy, ex, ey };
evgMakeCurve(segments, coords, VG_STROKE_PATH);
}
// RectOutline makes a rectangle at the specified location and dimensions, outlined
void RectOutline(VGfloat x, VGfloat y, VGfloat w, VGfloat h) {
VGPath path = evgNewPath();
vguRect(path, x, y, w, h);
vgDrawPath(path, VG_STROKE_PATH);
vgDestroyPath(path);
}
// RoundrectOutline makes an rounded rectangle at the specified location and dimensions, outlined
void RoundrectOutline(VGfloat x, VGfloat y, VGfloat w, VGfloat h, VGfloat rw, VGfloat rh) {
VGPath path = evgNewPath();
vguRoundRect(path, x, y, w, h, rw, rh);
vgDrawPath(path, VG_STROKE_PATH);
vgDestroyPath(path);
}
// EllipseOutline makes an ellipse at the specified location and dimensions, outlined
void EllipseOutline(VGfloat x, VGfloat y, VGfloat w, VGfloat h) {
VGPath path = evgNewPath();
vguEllipse(path, x, y, w, h);
vgDrawPath(path, VG_STROKE_PATH);
vgDestroyPath(path);
}
// CircleOutline makes a circle at the specified location and dimensions, outlined
void CircleOutline(VGfloat x, VGfloat y, VGfloat r) {
EllipseOutline(x, y, r, r);
}
// ArcOutline makes an elliptical arc at the specified location and dimensions, outlined
void ArcOutline(VGfloat x, VGfloat y, VGfloat w, VGfloat h, VGfloat sa, VGfloat aext) {
VGPath path = evgNewPath();
vguArc(path, x, y, w, h, sa, aext, VGU_ARC_OPEN);
vgDrawPath(path, VG_STROKE_PATH);
vgDestroyPath(path);
}
© 2020 GitHub, Inc.
Terms
Privacy
Security
Status
Help
Contact GitHub
Pricing
API
Training
Blog
About
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment