Compare commits
2 Commits
a5c305d98c
...
bd8bb0065d
Author | SHA1 | Date |
---|---|---|
Hans-Joerg Schurr | bd8bb0065d | |
Hans-Joerg Schurr | 69229b956f |
|
@ -1,6 +1,7 @@
|
||||||
#include "hvif-light.h"
|
#include "hvif-light.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
|
@ -14,6 +15,26 @@
|
||||||
* 3. Put everything together
|
* 3. Put everything together
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* TODO: Gradients
|
||||||
|
* - Check the various forms
|
||||||
|
* - How is the gradient oriented in the picture
|
||||||
|
* - Apply transformation matrix
|
||||||
|
* - Color space
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
cairo_matrix_init_from_matrix(cairo_matrix_t* matrix, const hvif_matrix* hvif_matrix)
|
||||||
|
{
|
||||||
|
cairo_matrix_init(matrix,
|
||||||
|
hvif_matrix->xx,
|
||||||
|
hvif_matrix->yx,
|
||||||
|
hvif_matrix->xy,
|
||||||
|
hvif_matrix->yy,
|
||||||
|
hvif_matrix->x0,
|
||||||
|
hvif_matrix->y0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
create_path(cairo_t* cr, hvif_path* path)
|
create_path(cairo_t* cr, hvif_path* path)
|
||||||
{
|
{
|
||||||
|
@ -23,26 +44,93 @@ create_path(cairo_t* cr, hvif_path* path)
|
||||||
hvif_point p = path->points[3 * i];
|
hvif_point p = path->points[3 * i];
|
||||||
hvif_point cp1 = path->points[3 * i + 1];
|
hvif_point cp1 = path->points[3 * i + 1];
|
||||||
hvif_point cp2 = path->points[3 * i + 2];
|
hvif_point cp2 = path->points[3 * i + 2];
|
||||||
cairo_curve_to(cr, cp1.x, cp1.y, cp2.x, cp2.y, p.x, p.y);
|
uint8_t command = path_command_at(path, i);
|
||||||
|
if (command == PATH_COMMAND_CURVE)
|
||||||
|
cairo_curve_to(cr, cp1.x, cp1.y, cp2.x, cp2.y, p.x, p.y);
|
||||||
|
else
|
||||||
|
cairo_line_to(cr, p.x, p.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path->closed)
|
if (path->closed)
|
||||||
cairo_close_path(cr);
|
cairo_close_path(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
create_style(cairo_t* cr, hvif_style* style)
|
||||||
|
{
|
||||||
|
assert(style->num_stops > 0);
|
||||||
|
cairo_pattern_t *pat;
|
||||||
|
|
||||||
|
switch (style->gradient_type) {
|
||||||
|
case GRADIENT_LINEAR:
|
||||||
|
printf("GRADIENT_LINEAR\n");
|
||||||
|
pat = cairo_pattern_create_linear(-64, 32, 64, 32);
|
||||||
|
break;
|
||||||
|
case GRADIENT_CIRCULAR:
|
||||||
|
printf("GRADIENT_CIRCULAR\n");
|
||||||
|
pat = cairo_pattern_create_radial(0, 0, 0, 0, 0, 64);
|
||||||
|
break;
|
||||||
|
case GRADIENT_DIAMOND:
|
||||||
|
printf("GRADIENT_DIAMOND\n");
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
case GRADIENT_CONIC:
|
||||||
|
printf("GRADIENT_CONIC\n");
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
case GRADIENT_XY:
|
||||||
|
printf("GRADIENT_XY\n");
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
case GRADIENT_SQRT_XY:
|
||||||
|
printf("GRADIENT_SQRT_XY\n");
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < style->num_stops; ++i) {
|
||||||
|
printf("stop %f\n", style->offsets[i]);
|
||||||
|
hvif_color c = style->colors[i];
|
||||||
|
cairo_pattern_add_color_stop_rgba(pat, style->offsets[i],
|
||||||
|
COLOR_GET_RED(c) / 255.0,
|
||||||
|
COLOR_GET_GREEN(c) / 255.0,
|
||||||
|
COLOR_GET_BLUE(c) / 255.0,
|
||||||
|
COLOR_GET_ALPHA(c) / 255.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_matrix_t transformation;
|
||||||
|
cairo_matrix_init_from_matrix(&transformation, &style->transformation);
|
||||||
|
if (cairo_matrix_invert(&transformation) != CAIRO_STATUS_SUCCESS) {
|
||||||
|
printf("could not invert style transformation\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
cairo_pattern_set_matrix(pat, &transformation);
|
||||||
|
|
||||||
|
cairo_rectangle(cr, 0, 0, 64, 64);
|
||||||
|
cairo_set_source(cr, pat);
|
||||||
|
cairo_fill(cr);
|
||||||
|
cairo_pattern_destroy(pat);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
hvif_render_image(const char* filename, hvif_image* image)
|
hvif_render_image(const char* filename, hvif_image* image)
|
||||||
{
|
{
|
||||||
cairo_surface_t* surface =
|
cairo_surface_t* surface =
|
||||||
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 254, 254);
|
/* cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 254, 254); */
|
||||||
|
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 65, 64);
|
||||||
cairo_t* cr = cairo_create(surface);
|
cairo_t* cr = cairo_create(surface);
|
||||||
cairo_scale(cr, 4.0, 4.0);
|
/* cairo_scale(cr, 4.0, 4.0); */
|
||||||
|
cairo_scale(cr, 1.0, 1.0);
|
||||||
|
|
||||||
cairo_set_line_width(cr, 0.2);
|
cairo_set_line_width(cr, 0.2);
|
||||||
|
|
||||||
double r = 0;
|
double r = 0;
|
||||||
double delta = 1.0 / image->num_shapes;
|
double delta = 1.0 / image->num_shapes;
|
||||||
|
|
||||||
|
printf("styles %u\n", image->num_styles);
|
||||||
|
create_style(cr, &image->styles[0]);
|
||||||
|
|
||||||
|
/*
|
||||||
for (unsigned i = 0; i < image->num_shapes; ++i) {
|
for (unsigned i = 0; i < image->num_shapes; ++i) {
|
||||||
cairo_set_source_rgb(cr, r, 0, 0);
|
cairo_set_source_rgb(cr, r, 0, 0);
|
||||||
r = r + delta;
|
r = r + delta;
|
||||||
|
@ -57,6 +145,7 @@ hvif_render_image(const char* filename, hvif_image* image)
|
||||||
cairo_stroke(cr);
|
cairo_stroke(cr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
cairo_destroy(cr);
|
cairo_destroy(cr);
|
||||||
|
|
||||||
|
|
|
@ -101,20 +101,18 @@ typedef enum hvif_line_cap
|
||||||
typedef struct hvif_matrix hvif_matrix;
|
typedef struct hvif_matrix hvif_matrix;
|
||||||
struct hvif_matrix
|
struct hvif_matrix
|
||||||
{
|
{
|
||||||
double v1;
|
double xx;
|
||||||
double v2;
|
double yx;
|
||||||
double v3;
|
double xy;
|
||||||
double v4;
|
double yy;
|
||||||
double v5;
|
double x0;
|
||||||
double v6;
|
double y0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TODO: This is most likely wrong */
|
|
||||||
#define MATRIX_ID \
|
#define MATRIX_ID \
|
||||||
(hvif_matrix) { 1.0, 0.0, 0.0, 0.0, 1.0, 0.0 }
|
(hvif_matrix) { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }
|
||||||
/* TODO: This is most likely wrong */
|
|
||||||
#define MATRIX_TRANSLATION(P) \
|
#define MATRIX_TRANSLATION(P) \
|
||||||
(hvif_matrix) { P.x, 0.0, 0.0, 0.0, P.y, 0.0 }
|
(hvif_matrix) { 1.0, 0.0, 0.0, 1.0, P.x, P.y }
|
||||||
|
|
||||||
typedef struct hvif_point hvif_point;
|
typedef struct hvif_point hvif_point;
|
||||||
struct hvif_point
|
struct hvif_point
|
||||||
|
@ -211,20 +209,29 @@ struct hvif_image
|
||||||
hvif_shape* shapes;
|
hvif_shape* shapes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline uint8_t
|
||||||
|
path_command_at(hvif_path* path, uint8_t index)
|
||||||
|
{
|
||||||
|
uint8_t byte = path->commands[index / 4];
|
||||||
|
uint8_t byte_idx = index % 4;
|
||||||
|
return (byte >> (2 * byte_idx)) & 0x03;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef INTERNAL_DATASTRUCTURES
|
#ifndef INTERNAL_DATASTRUCTURES
|
||||||
|
|
||||||
#define hvif_decode(V, BUFFER) \
|
#define hvif_decode(V, BUFFER) \
|
||||||
V = _Generic((V), uint32_t \
|
V = _Generic((V), uint32_t \
|
||||||
: hvif_decode_uint32, float \
|
: hvif_decode_uint32, float \
|
||||||
: hvif_decode_float, hvif_matrix \
|
: hvif_decode_float, hvif_matrix \
|
||||||
: hvif_decode_hvif_matrix)(BUFFER)
|
: hvif_decode_hvif_matrix)(BUFFER)
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
hvif_decode_uint32(char buffer[static 1])
|
hvif_decode_uint32(uint8_t buffer[static 1])
|
||||||
{
|
{
|
||||||
return (buffer[0] << 0) | (buffer[1] << 8) | (buffer[2] << 16) |
|
return (buffer[0] << 0) | (buffer[1] << 8) | (buffer[2] << 16) |
|
||||||
(buffer[3] << 24);
|
(buffer[3] << 24);
|
||||||
}
|
}
|
||||||
static inline float
|
static inline float
|
||||||
hvif_decode_float(char buffer[static 1])
|
hvif_decode_float(uint8_t buffer[static 1])
|
||||||
{
|
{
|
||||||
int shortValue = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
int shortValue = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
|
||||||
int sign = (shortValue & 0x800000) >> 23;
|
int sign = (shortValue & 0x800000) >> 23;
|
||||||
|
@ -234,12 +241,13 @@ hvif_decode_float(char buffer[static 1])
|
||||||
if (shortValue == 0)
|
if (shortValue == 0)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
else {
|
else {
|
||||||
|
/* TODO: float might not be IEEE 754 compatible */
|
||||||
uint32_t value = (sign << 31) | ((exponent + 127) << 23) | mantissa;
|
uint32_t value = (sign << 31) | ((exponent + 127) << 23) | mantissa;
|
||||||
return (float)value;
|
return *((float*)&value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static inline hvif_matrix
|
static inline hvif_matrix
|
||||||
hvif_decode_hvif_matrix(char buffer[static 1])
|
hvif_decode_hvif_matrix(uint8_t buffer[static 1])
|
||||||
{
|
{
|
||||||
return (hvif_matrix){
|
return (hvif_matrix){
|
||||||
hvif_decode_float(buffer), hvif_decode_float(&buffer[3]),
|
hvif_decode_float(buffer), hvif_decode_float(&buffer[3]),
|
||||||
|
@ -248,16 +256,8 @@ hvif_decode_hvif_matrix(char buffer[static 1])
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
|
||||||
path_command_at(hvif_path* path, uint8_t index)
|
|
||||||
{
|
|
||||||
uint8_t byte = path->commands[index / 4];
|
|
||||||
uint8_t byte_idx = index % 4;
|
|
||||||
return (byte >> (2 * byte_idx)) & 0x03;
|
|
||||||
}
|
|
||||||
|
|
||||||
hvif_color
|
hvif_color
|
||||||
decode_color(char* buffer, bool gray, bool alpha)
|
decode_color(uint8_t* buffer, bool gray, bool alpha)
|
||||||
{
|
{
|
||||||
/* On disk a color is:
|
/* On disk a color is:
|
||||||
red, green, blue, alpha
|
red, green, blue, alpha
|
||||||
|
@ -286,7 +286,7 @@ decode_color(char* buffer, bool gray, bool alpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
hvif_status
|
hvif_status
|
||||||
read_color_style(hvif_style* style, char* buffer, bool gray, bool alpha)
|
read_color_style(hvif_style* style, uint8_t* buffer, bool gray, bool alpha)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("%s: start.\n", __func__);
|
printf("%s: start.\n", __func__);
|
||||||
|
@ -303,7 +303,7 @@ read_color_style(hvif_style* style, char* buffer, bool gray, bool alpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
hvif_status
|
hvif_status
|
||||||
read_gradient_style(hvif_style* style, FILE* file, char* style_buffer)
|
read_gradient_style(hvif_style* style, FILE* file, uint8_t* style_buffer)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("%s: start.\n", __func__);
|
printf("%s: start.\n", __func__);
|
||||||
|
@ -328,7 +328,7 @@ read_gradient_style(hvif_style* style, FILE* file, char* style_buffer)
|
||||||
printf("%s: read transfomation matrix.\n", __func__);
|
printf("%s: read transfomation matrix.\n", __func__);
|
||||||
#endif
|
#endif
|
||||||
/* The transformation matrix is 6 hvif-floats: 18 bytes */
|
/* The transformation matrix is 6 hvif-floats: 18 bytes */
|
||||||
char buffer[18];
|
uint8_t buffer[18];
|
||||||
if (fread(buffer, 1, 18, file) != 18) { return ERROR_EOF; }
|
if (fread(buffer, 1, 18, file) != 18) { return ERROR_EOF; }
|
||||||
hvif_decode(transformation, buffer);
|
hvif_decode(transformation, buffer);
|
||||||
} else {
|
} else {
|
||||||
|
@ -345,7 +345,7 @@ read_gradient_style(hvif_style* style, FILE* file, char* style_buffer)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("%s: read %u stops.\n", __func__, gradient_stops);
|
printf("%s: read %u stops.\n", __func__, gradient_stops);
|
||||||
#endif
|
#endif
|
||||||
char buffer[4];
|
uint8_t buffer[4];
|
||||||
for (unsigned i = 0; i < gradient_stops; ++i) {
|
for (unsigned i = 0; i < gradient_stops; ++i) {
|
||||||
if (fread(buffer, 1, 1, file) != 1) { return ERROR_EOF; }
|
if (fread(buffer, 1, 1, file) != 1) { return ERROR_EOF; }
|
||||||
float offset = buffer[0] / 255.0;
|
float offset = buffer[0] / 255.0;
|
||||||
|
@ -379,7 +379,7 @@ read_style(FILE* file, hvif_style* style)
|
||||||
{
|
{
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
if (fread(&type, 1, 1, file) != 1) { return ERROR_EOF; }
|
if (fread(&type, 1, 1, file) != 1) { return ERROR_EOF; }
|
||||||
char buffer[4];
|
uint8_t buffer[4];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case STYLE_TYPE_SOLID_COLOR:
|
case STYLE_TYPE_SOLID_COLOR:
|
||||||
if (fread(buffer, 1, 4, file) != 4) { return ERROR_EOF; }
|
if (fread(buffer, 1, 4, file) != 4) { return ERROR_EOF; }
|
||||||
|
@ -565,7 +565,7 @@ read_transformer(FILE* file, hvif_transformer* transformer)
|
||||||
switch (byte) {
|
switch (byte) {
|
||||||
case TRANSFORMER_TYPE_AFFINE:
|
case TRANSFORMER_TYPE_AFFINE:
|
||||||
transformer->transformer_type = byte;
|
transformer->transformer_type = byte;
|
||||||
char buffer[18];
|
uint8_t buffer[18];
|
||||||
hvif_matrix matrix;
|
hvif_matrix matrix;
|
||||||
if (fread(buffer, 1, 18, file) != 18) return ERROR_EOF;
|
if (fread(buffer, 1, 18, file) != 18) return ERROR_EOF;
|
||||||
hvif_decode(matrix, buffer);
|
hvif_decode(matrix, buffer);
|
||||||
|
@ -645,7 +645,7 @@ read_shape(FILE* file, hvif_image const* const image, hvif_shape* shape)
|
||||||
|
|
||||||
hvif_matrix transformation;
|
hvif_matrix transformation;
|
||||||
if (shape_flags & SHAPE_FLAG_TRANSFORM) {
|
if (shape_flags & SHAPE_FLAG_TRANSFORM) {
|
||||||
char buffer[18];
|
uint8_t buffer[18];
|
||||||
if (fread(buffer, 1, 18, file) != 18) { return ERROR_EOF; }
|
if (fread(buffer, 1, 18, file) != 18) { return ERROR_EOF; }
|
||||||
hvif_decode(transformation, buffer);
|
hvif_decode(transformation, buffer);
|
||||||
} else if (shape_flags & SHAPE_FLAG_TRANSLATION) {
|
} else if (shape_flags & SHAPE_FLAG_TRANSLATION) {
|
||||||
|
@ -700,7 +700,7 @@ hvif_from_file(FILE* file)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("%s: checking magic number.\n", __func__);
|
printf("%s: checking magic number.\n", __func__);
|
||||||
#endif
|
#endif
|
||||||
char magic_buffer[4];
|
uint8_t magic_buffer[4];
|
||||||
if (fread(magic_buffer, 1, 4, file) != 4) return ERROR_RESULT(ERROR_EOF);
|
if (fread(magic_buffer, 1, 4, file) != 4) return ERROR_RESULT(ERROR_EOF);
|
||||||
uint32_t read_magic;
|
uint32_t read_magic;
|
||||||
hvif_decode(read_magic, magic_buffer);
|
hvif_decode(read_magic, magic_buffer);
|
||||||
|
|
Loading…
Reference in New Issue