VkvgSurface vkvg_surface_create (VkvgDevice dev, uint32_t width, uint32_t height);
VkvgSurface vkvg_surface_create_from_image (VkvgDevice dev, const char* filePath);
VkvgSurface vkvg_surface_create_from_svg (VkvgDevice dev, const char* filePath);
+VkvgSurface vkvg_surface_create_from_svg_fragment (VkvgDevice dev, char *fragment);
VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void* vkhImg);
// VkvgSurface vkvg_surface_create_from_bitmap (VkvgDevice dev, unsigned char* img, uint32_t width, uint32_t height);
VkvgSurface vkvg_surface_reference (VkvgSurface surf);
void vkvg_surface_write_to_png (VkvgSurface surf, const char* path);
void vkvg_multisample_surface_resolve (VkvgSurface surf);
+//nsvg interface for easy svg drawing
+typedef struct NSVGimage NSVGimage;
+
+NSVGimage* nsvg_load_file (VkvgDevice dev, const char* filePath);
+NSVGimage* nsvg_load (VkvgDevice dev, char* fragment);
+void nsvg_destroy (NSVGimage* svg);
+void nsvg_get_size (NSVGimage* svg, int* width, int* height);
+void vkvg_render_svg (VkvgContext ctx, NSVGimage* svg);
+
+
//mimic from cairo, to facilitate usage of vkvg as cairo vulkan backend
typedef enum _vkvg_operator {
VKVG_OPERATOR_CLEAR,
#include "vkvg_pattern.h"
#include "vkh_queue.h"
+#include "nanosvg.h"
+
#ifdef DEBUG
static vec2 debugLinePoints[1000];
static uint32_t dlpCount = 0;
void vkvg_get_matrix (VkvgContext ctx, const vkvg_matrix_t* matrix){
memcpy (matrix, &ctx->pushConsts.mat, sizeof(vkvg_matrix_t));
}
+
+void vkvg_render_svg (VkvgContext ctx, NSVGimage* svg){
+ NSVGshape* shape;
+ NSVGpath* path;
+
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+
+ vkvg_set_source_rgba(ctx,0.0,0.0,0.0,1);
+
+ for (shape = svg->shapes; shape != NULL; shape = shape->next) {
+
+ vkvg_new_path(ctx);
+
+ float o = shape->opacity;
+
+ vkvg_set_line_width(ctx, shape->strokeWidth);
+
+ for (path = shape->paths; path != NULL; path = path->next) {
+ float* p = path->pts;
+ vkvg_move_to(ctx, p[0],p[1]);
+ for (int i = 1; i < path->npts-2; i += 3) {
+ p = &path->pts[i*2];
+ vkvg_curve_to(ctx, p[0],p[1], p[2],p[3], p[4],p[5]);
+ }
+ if (path->closed)
+ vkvg_close_path(ctx);
+ }
+
+ if (shape->fill.type == NSVG_PAINT_COLOR)
+ _svg_set_color(ctx, shape->fill.color, o);
+ else if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT){
+ NSVGgradient* g = shape->fill.gradient;
+ _svg_set_color(ctx, g->stops[0].color, o);
+ }
+
+ if (shape->fill.type != NSVG_PAINT_NONE){
+ if (shape->stroke.type == NSVG_PAINT_NONE){
+ vkvg_fill(ctx);
+ continue;
+ }
+ vkvg_fill_preserve (ctx);
+ }
+
+ if (shape->stroke.type == NSVG_PAINT_COLOR)
+ _svg_set_color(ctx, shape->stroke.color, o);
+ else if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT){
+ NSVGgradient* g = shape->stroke.gradient;
+ _svg_set_color(ctx, g->stops[0].color, o);
+ }
+
+ vkvg_stroke(ctx);
+ }
+
+}
VkDescriptorSetLayout dslSrc; /**< context source surface descriptors layout */
VkDescriptorSetLayout dslGrad; /**< context gradient descriptors layout */
- int hdpi, /**< only used for FreeType fonts */
+ int hdpi, /**< only used for FreeType fonts and svg loading */
vdpi;
VkhImage emptyImg; /**< prevent unbound descriptor to trigger Validation error 61 */
return surf;
}
-void svg_set_color (VkvgContext ctx, uint32_t c, float alpha) {
+void _svg_set_color (VkvgContext ctx, uint32_t c, float alpha) {
float a = (c >> 24 & 255) / 255.f;
float b = (c >> 16 & 255) / 255.f;
float g = (c >> 8 & 255) / 255.f;
vkvg_set_source_rgba(ctx,r,g,b,a*alpha);
}
-VkvgSurface vkvg_surface_create_from_svg (VkvgDevice dev, const char* filePath) {
- NSVGimage* svg = nsvgParseFromFile(filePath, "px", 96);
+VkvgSurface _svg_load (VkvgDevice dev, NSVGimage* svg) {
NSVGshape* shape;
NSVGpath* path;
_init_surface (surf);
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
-
- vkvg_set_source_rgba(ctx,0.0,0.0,0.0,1);
-
- for (shape = svg->shapes; shape != NULL; shape = shape->next) {
-
- vkvg_new_path(ctx);
-
- float o = shape->opacity;
-
- vkvg_set_line_width(ctx, shape->strokeWidth);
-
- for (path = shape->paths; path != NULL; path = path->next) {
- float* p = path->pts;
- vkvg_move_to(ctx, p[0],p[1]);
- for (int i = 1; i < path->npts-2; i += 3) {
- p = &path->pts[i*2];
- vkvg_curve_to(ctx, p[0],p[1], p[2],p[3], p[4],p[5]);
- }
- if (path->closed)
- vkvg_close_path(ctx);
- }
-
- if (shape->fill.type == NSVG_PAINT_COLOR)
- svg_set_color(ctx, shape->fill.color, o);
- else if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT){
- NSVGgradient* g = shape->fill.gradient;
- svg_set_color(ctx, g->stops[0].color, o);
- }
-
- if (shape->fill.type != NSVG_PAINT_NONE){
- if (shape->stroke.type == NSVG_PAINT_NONE){
- vkvg_fill(ctx);
- continue;
- }
- vkvg_fill_preserve (ctx);
- }
-
- if (shape->stroke.type == NSVG_PAINT_COLOR)
- svg_set_color(ctx, shape->stroke.color, o);
- else if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT){
- NSVGgradient* g = shape->stroke.gradient;
- svg_set_color(ctx, g->stops[0].color, o);
- }
-
- vkvg_stroke(ctx);
- }
+ vkvg_render_svg(ctx, svg);
+ vkvg_destroy(ctx);
nsvgDelete(svg);
- vkvg_destroy(ctx);
surf->references = 1;
vkvg_device_reference (surf->dev);
return surf;
}
+VkvgSurface vkvg_surface_create_from_svg (VkvgDevice dev, const char* filePath) {
+ return _svg_load(dev, nsvgParseFromFile(filePath, "px", dev->hdpi));
+}
+VkvgSurface vkvg_surface_create_from_svg_fragment (VkvgDevice dev, char* fragment) {
+ return _svg_load(dev, nsvgParse(fragment, "px", dev->hdpi));
+}
+NSVGimage* nsvg_load_file (VkvgDevice dev, const char* filePath) {
+ return nsvgParseFromFile(filePath, "px", dev->hdpi);
+}
+NSVGimage* nsvg_load (VkvgDevice dev, char* fragment) {
+ return nsvgParse (fragment, "px", dev->hdpi);
+}
+void nsvg_destroy (NSVGimage* svg) {
+ nsvgDelete(svg);
+}
+void nsvg_get_size (NSVGimage* svg, int* width, int* height) {
+ *width = (int)svg->width;
+ *height = (int)svg->height;
+}
+
void vkvg_surface_destroy(VkvgSurface surf)
{
surf->references--;
}vkvg_surface;
void _clear_surface (VkvgSurface surf, VkImageAspectFlags aspect);
+void _svg_set_color (VkvgContext ctx, uint32_t c, float alpha);
#endif
#define NANOSVG_IMPLEMENTATION // Expands implementation
#include "nanosvg.h"
-void svg_set_color (VkvgContext ctx, uint32_t c, float alpha) {
+void _svg_set_color (VkvgContext ctx, uint32_t c, float alpha) {
float a = (c >> 24 & 255) / 255.f;
float b = (c >> 16 & 255) / 255.f;
float g = (c >> 8 & 255) / 255.f;
}
static float rotation = 0.f;
+//static const char* path = "/mnt/devel/crow-drm/Images/Icons/minimize.svg";
+static const char* path = "data/tiger.svg";
void test_svg_surface() {
- VkvgSurface svgSurf = vkvg_surface_create_from_svg(device, "data/tiger.svg");
+ VkvgSurface svgSurf = vkvg_surface_create_from_svg(device, path);
VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_source_rgb(ctx,0,0,0);
+ vkvg_paint(ctx);
+
vkvg_set_source_surface(ctx, svgSurf, 0,0);
vkvg_paint(ctx);
vkvg_surface_destroy(svgSurf);
}
+void test_nsvg() {
+ NSVGimage* svg = nsvg_load_file(device, path);
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_scale(ctx,0.04f,0.04f);
+ vkvg_render_svg(ctx, svg);
+ vkvg_destroy(ctx);
+ nsvg_destroy(svg);
+}
+
void test_svg () {
rotation+=0.01f;
vkvg_set_source_rgba(ctx,0.0,0.0,0.0,1);
for (shape = svg->shapes; shape != NULL; shape = shape->next) {
-
vkvg_new_path(ctx);
float o = shape->opacity;
}
if (shape->fill.type == NSVG_PAINT_COLOR)
- svg_set_color(ctx, shape->fill.color, o);
+ _svg_set_color(ctx, shape->fill.color, o);
else if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT){
NSVGgradient* g = shape->fill.gradient;
- svg_set_color(ctx, g->stops[0].color, o);
+ _svg_set_color(ctx, g->stops[0].color, o);
}
if (shape->fill.type != NSVG_PAINT_NONE){
}
if (shape->stroke.type == NSVG_PAINT_COLOR)
- svg_set_color(ctx, shape->stroke.color, o);
+ _svg_set_color(ctx, shape->stroke.color, o);
else if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT){
NSVGgradient* g = shape->stroke.gradient;
- svg_set_color(ctx, g->stops[0].color, o);
+ _svg_set_color(ctx, g->stops[0].color, o);
}
vkvg_stroke(ctx);
int main(int argc, char *argv[]) {
- perform_test (test_svg_surface, 1024, 768);
+ perform_test (test_nsvg, 1024, 768);
return 0;
}