Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for rendering raster images #30

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Ignore build dirs
/build
/cmake-build-*

# Ignore IDE specific dirs
*.idea
**/.vscode
7 changes: 6 additions & 1 deletion example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ cmake_minimum_required(VERSION 3.3)

set(CMAKE_C_STANDARD 99)

project(smiley C)
project(examples C)

add_executable(smiley smiley.c)
target_link_libraries(smiley plutovg m)

add_executable(texture texture.c)
target_link_libraries(texture plutovg m)

file(COPY assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
Binary file added example/assets/texture1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/assets/texture2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/assets/texture3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/assets/texture4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7,985 changes: 7,985 additions & 0 deletions example/stb_image.h

Large diffs are not rendered by default.

82 changes: 82 additions & 0 deletions example/texture.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "plutovg.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define NUM_TEXTURES 4

int main(void) {
// PlutoVG
const int canvas_width = 900;
const int canvas_height = 900;
plutovg_surface_t *surface = plutovg_surface_create(canvas_width, canvas_height);
plutovg_t *pluto = plutovg_create(surface);

// Draw raster textures in 4 corners
int positions[NUM_TEXTURES][2] = {{-1, -1},
{1, -1},
{-1, 1},
{1, 1}};
for (int i = 0; i < NUM_TEXTURES; ++i)
{
char filename[PATH_MAX];
sprintf(filename, "assets/texture%d.png", i + 1);

int width, height, channels;
unsigned char *image_data = stbi_load(filename, &width, &height, &channels, 0);

if (!image_data) {
fprintf(stderr, "Error loading textures: %s\n", stbi_failure_reason());
return 1;
}

const int x = positions[i][0] * width / 2;
const int y = positions[i][1] * height / 2;

plutovg_save(pluto);
plutovg_image(pluto, x, y, image_data, width, height, channels);
plutovg_restore(pluto);

stbi_image_free(image_data);
}

// Draw vector shapes on top of the textures
const double center_x = canvas_width * 0.5;
const double center_y = canvas_height * 0.5;
const double face_radius = canvas_width * 0.25;
const double eye_radius = face_radius * 0.1;
const double mouth_radius = face_radius * 0.7;
const double eye_offset_x = face_radius * 0.35;
const double eye_offset_y = face_radius * 0.3;
const double eye_x = center_x - eye_offset_x;
const double eye_y = center_y - eye_offset_y;

const double pi = 3.14159265358979323846;

plutovg_save(pluto);
plutovg_arc(pluto, center_x, center_y, face_radius, 0, 2 * pi, 0);
plutovg_set_rgb(pluto, 1, 1, 0);
plutovg_fill_preserve(pluto);
plutovg_set_rgb(pluto, 0, 0, 0);
plutovg_set_line_width(pluto, 10);
plutovg_stroke(pluto);
plutovg_restore(pluto);

plutovg_save(pluto);
plutovg_arc(pluto, eye_x, eye_y, eye_radius, 0, 2 * pi, 0);
plutovg_arc(pluto, center_x + eye_offset_x, eye_y, eye_radius, 0, 2 * pi, 0);
plutovg_fill(pluto);
plutovg_restore(pluto);

plutovg_save(pluto);
plutovg_arc(pluto, center_x, center_y, mouth_radius, 0, pi, 0);
plutovg_set_line_width(pluto, 10);
plutovg_stroke(pluto);
plutovg_restore(pluto);

plutovg_surface_write_to_png(surface, "texture.png");
plutovg_surface_destroy(surface);
plutovg_destroy(pluto);

return 0;
}
2 changes: 2 additions & 0 deletions include/plutovg.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ void plutovg_rel_quad_to(plutovg_t* pluto, double dx1, double dy1, double dx2, d
void plutovg_rel_cubic_to(plutovg_t* pluto, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3);

void plutovg_rect(plutovg_t* pluto, double x, double y, double w, double h);
void plutovg_pixel(plutovg_t* pluto, int x, int y);
void plutovg_image(plutovg_t* pluto, int x, int y, unsigned char* data, int w, int h, int c);
void plutovg_round_rect(plutovg_t* pluto, double x, double y, double w, double h, double rx, double ry);
void plutovg_ellipse(plutovg_t* pluto, double cx, double cy, double rx, double ry);
void plutovg_circle(plutovg_t* pluto, double cx, double cy, double r);
Expand Down
26 changes: 26 additions & 0 deletions source/plutovg.c
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,32 @@ void plutovg_rect(plutovg_t* pluto, double x, double y, double w, double h)
plutovg_path_add_rect(pluto->path, x, y, w, h);
}

void plutovg_pixel(plutovg_t* pluto, int x, int y)
{
plutovg_path_add_rect(pluto->path, x, y, 1, 1);
}

void plutovg_image(plutovg_t* pluto, int x, int y, unsigned char* data, int w, int h, int c)
{
const int canvas_h = pluto->surface->height;
const int canvas_w = pluto->surface->width;

for (int i = plutovg_max(0, -y); i < plutovg_min(h, canvas_h - y); ++i) {
for (int j = plutovg_max(0, -x); j < plutovg_min(w, canvas_w - x); ++j) {
plutovg_pixel(pluto, j + x, i + y);

unsigned char *pixel_offset = data + (j + w * i) * c;
const double r = pixel_offset[0] / 255.0;
const double g = pixel_offset[1] / 255.0;
const double b = pixel_offset[2] / 255.0;
const double a = c >= 4 ? pixel_offset[3] / 255.0 : 1.0;

plutovg_set_rgba(pluto, r, g, b, a);
plutovg_fill(pluto);
}
}
}

void plutovg_round_rect(plutovg_t* pluto, double x, double y, double w, double h, double rx, double ry)
{
plutovg_path_add_round_rect(pluto->path, x, y, w, h, rx, ry);
Expand Down