1
0
Fork 0

Implement API to inspect styles

- Expose necessary stucts and enums.
- Add functions to get number of styles, shapes, paths.
- Add functions to retrieve style information.
This commit is contained in:
Hans-Joerg Schurr 2021-04-25 20:32:26 +02:00
parent 0bb035050f
commit a22aea9293
4 changed files with 215 additions and 59 deletions

View File

@ -55,7 +55,8 @@ print_matrix(const hvif_matrix* matrix)
*/
void
create_diamond_patch(
cairo_pattern_t* pat, double s1, double s2, hvif_color c1, hvif_color c2)
cairo_pattern_t* pat, double s1, double s2, hvif_color_internal c1,
hvif_color_internal c2)
{
cairo_mesh_pattern_begin_patch(pat);
cairo_mesh_pattern_move_to(pat, s1, s1);
@ -104,8 +105,8 @@ create_diamond_patch(
*/
void
create_conic_patch(
cairo_pattern_t* pat, double r, double angle1, double angle2, hvif_color c1,
hvif_color c2)
cairo_pattern_t* pat, double r, double angle1, double angle2,
hvif_color_internal c1, hvif_color_internal c2)
{
double sin1 = r * sin(angle1);
double cos1 = r * cos(angle1);
@ -145,23 +146,23 @@ create_pattern_style(cairo_pattern_t** pat, hvif_style* style)
bool unsupported = false;
switch (style->gradient_type) {
case GRADIENT_LINEAR:
case HVIF_GRADIENT_LINEAR:
*pat = cairo_pattern_create_linear(-64, 32, 64, 32);
for (unsigned i = 0; i < style->num_stops; ++i) {
hvif_color c = style->colors[i];
hvif_color_internal c = style->colors[i];
cairo_pattern_add_color_stop_rgba(
*pat, style->offsets[i], R(c), G(c), B(c), A(c));
}
break;
case GRADIENT_CIRCULAR:
case HVIF_GRADIENT_CIRCULAR:
*pat = cairo_pattern_create_radial(0, 0, 0, 0, 0, 64);
for (unsigned i = 0; i < style->num_stops; ++i) {
hvif_color c = style->colors[i];
hvif_color_internal c = style->colors[i];
cairo_pattern_add_color_stop_rgba(
*pat, style->offsets[i], R(c), G(c), B(c), A(c));
}
break;
case GRADIENT_DIAMOND:
case HVIF_GRADIENT_DIAMOND:
*pat = cairo_pattern_create_mesh();
if (style->offsets[0] != 0.0) {
create_diamond_patch(
@ -171,8 +172,8 @@ create_pattern_style(cairo_pattern_t** pat, hvif_style* style)
for (unsigned i = 0; i + 1 < style->num_stops; ++i) {
double s1 = style->offsets[i] * 64.0;
double s2 = style->offsets[i + 1] * 64.0;
hvif_color c1 = style->colors[i];
hvif_color c2 = style->colors[i + 1];
hvif_color_internal c1 = style->colors[i];
hvif_color_internal c2 = style->colors[i + 1];
create_diamond_patch(*pat, s1, s2, c1, c2);
}
unsigned i = style->num_stops - 1;
@ -180,7 +181,7 @@ create_pattern_style(cairo_pattern_t** pat, hvif_style* style)
*pat, 64.0 * style->offsets[i], extremum, style->colors[i],
style->colors[i]);
break;
case GRADIENT_CONIC:
case HVIF_GRADIENT_CONIC:
*pat = cairo_pattern_create_mesh();
if (style->offsets[0] != 0.0) {
create_conic_patch(
@ -209,28 +210,28 @@ create_pattern_style(cairo_pattern_t** pat, hvif_style* style)
style->colors[i]);
}
break;
case GRADIENT_XY:
case HVIF_GRADIENT_XY:
#ifdef DEBUG
printf("GRADIENT_XY not supported\n");
printf("HVIF_GRADIENT_XY not supported\n");
exit(1);
#endif /* DEBUG */
unsupported = true;
*pat = cairo_pattern_create_radial(0, 0, 0, 0, 0, 64);
for (unsigned i = 0; i < style->num_stops; ++i) {
hvif_color c = style->colors[i];
hvif_color_internal c = style->colors[i];
cairo_pattern_add_color_stop_rgba(
*pat, style->offsets[i], R(c), G(c), B(c), A(c));
}
break;
case GRADIENT_SQRT_XY:
case HVIF_GRADIENT_SQRT_XY:
#ifdef DEBUG
printf("GRADIENT_SQRT_XY not supported\n");
printf("HVIF_GRADIENT_SQRT_XY not supported\n");
exit(1);
#endif /* DEBUG */
unsupported = true;
*pat = cairo_pattern_create_radial(0, 0, 0, 0, 0, 64);
for (unsigned i = 0; i < style->num_stops; ++i) {
hvif_color c = style->colors[i];
hvif_color_internal c = style->colors[i];
cairo_pattern_add_color_stop_rgba(
*pat, style->offsets[i], R(c), G(c), B(c), A(c));
}
@ -462,4 +463,3 @@ hvif_cairo_render(cairo_t* context, hvif_image* image, double scale)
cairo_restore(context);
return result;
}

View File

@ -86,4 +86,3 @@ hvif_cairo_status hvif_cairo_render(
cairo_t* context, hvif_image* image, double scale);
#endif /* HVIF_CAIRO_H */

View File

@ -36,17 +36,6 @@ enum
TRANSFORMER_TYPE_STROKE = 23,
};
enum gradients_type
{
GRADIENT_LINEAR = 0,
GRADIENT_CIRCULAR,
GRADIENT_DIAMOND,
GRADIENT_CONIC,
GRADIENT_XY,
GRADIENT_SQRT_XY,
HVIF_GRADIENT_TYPE_MAX
};
enum
{
GRADIENT_FLAG_TRANSFORM = 1 << 1,
@ -97,18 +86,6 @@ typedef enum hvif_line_cap
HVIF_LINE_CAP_TYPE_MAX
} hvif_line_cap;
/* An affine transformation. */
typedef struct hvif_matrix hvif_matrix;
struct hvif_matrix
{
double xx;
double yx;
double xy;
double yy;
double x0;
double y0;
};
#define MATRIX_ID \
(hvif_matrix) { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }
#define MATRIX_TRANSLATION(P) \
@ -124,7 +101,7 @@ struct hvif_point
#define POINT_ORIGIN \
(hvif_point) { 0.0, 0.0 }
typedef uint32_t hvif_color; /* 8bit each: alpha, blue, green, red */
typedef uint32_t hvif_color_internal; /* 8bit each: alpha, blue, green, red */
#define COLOR_GET_RED(C) (C & 0xff)
#define COLOR_GET_GREEN(C) ((C >> 8) & 0xff)
#define COLOR_GET_BLUE(C) ((C >> 16) & 0xff)
@ -169,9 +146,9 @@ struct hvif_transformer
typedef struct hvif_style hvif_style;
struct hvif_style
{
signed gradient_type;
hvif_gradients_type gradient_type;
uint8_t num_stops;
hvif_color* colors;
hvif_color_internal* colors;
float* offsets;
hvif_matrix transformation;
};
@ -261,7 +238,7 @@ hvif_decode_hvif_matrix(uint8_t buffer[static 1])
};
}
hvif_color
hvif_color_internal
decode_color(uint8_t* buffer, bool gray, bool alpha)
{
/* On disk a color is:
@ -271,7 +248,7 @@ decode_color(uint8_t* buffer, bool gray, bool alpha)
is `0xff`. If gray is `true` only one one byte is used for the three
colors.
*/
hvif_color c = 0;
hvif_color_internal c = 0;
if (alpha) {
if (gray) {
COLOR_SET_RGB(c, buffer[0], buffer[0], buffer[0]);
@ -296,14 +273,14 @@ read_color_style(hvif_style* style, uint8_t* buffer, bool gray, bool alpha)
#ifdef DEBUG
printf("%s: start.\n", __func__);
#endif
hvif_color color = decode_color(buffer, gray, alpha);
hvif_color_internal color = decode_color(buffer, gray, alpha);
style->num_stops = 1;
style->colors = calloc(1, sizeof(hvif_color));
style->colors = calloc(1, sizeof(hvif_color_internal));
style->offsets = calloc(1, sizeof(float));
if (!style->colors || !style->colors) return ERROR_NOMEM;
style->colors[0] = color;
style->offsets[0] = 1.0; /* TODO: Is this ok for solid colors */
style->offsets[0] = 1.0; /* TODO: Is this ok for solid colors? */
style->transformation = MATRIX_ID;
return SUCCESS;
}
@ -344,7 +321,7 @@ read_gradient_style(hvif_style* style, FILE* file, uint8_t* style_buffer)
style->num_stops = gradient_stops;
style->offsets = calloc(gradient_stops, sizeof(float));
style->colors = calloc(gradient_stops, sizeof(hvif_color));
style->colors = calloc(gradient_stops, sizeof(hvif_color_internal));
if (!style->offsets || !style->colors) return ERROR_NOMEM;
@ -355,7 +332,7 @@ read_gradient_style(hvif_style* style, FILE* file, uint8_t* style_buffer)
for (unsigned i = 0; i < gradient_stops; ++i) {
if (fread(buffer, 1, 1, file) != 1) { return ERROR_EOF; }
float offset = buffer[0] / 255.0;
hvif_color c;
hvif_color_internal c;
if (alpha) {
if (gray) {
if (fread(buffer, 1, 2, file) != 2) { return ERROR_EOF; }
@ -806,5 +783,72 @@ hvif_free(hvif_image* image)
free(image);
}
#endif /* INTERNAL_DATASTRUCTURES */
uint8_t
hvif_num_styles(hvif_image* image)
{
if (image == NULL) return 0;
return image->num_styles;
}
uint8_t
hvif_num_paths(hvif_image* image)
{
if (image == NULL) return 0;
return image->num_paths;
}
uint8_t
hvif_num_shapes(hvif_image* image)
{
if (image == NULL) return 0;
return image->num_shapes;
}
hvif_status
hvif_style_gradient_type(
hvif_image* image, uint8_t style, hvif_gradients_type* type)
{
if (image == NULL) return ERROR_STYLE;
if (style >= image->num_styles) return ERROR_STYLE;
*type = image->styles[style].gradient_type;
return SUCCESS;
}
hvif_status
hvif_style_num_stops(hvif_image* image, uint8_t style, uint8_t* num_stops)
{
if (image == NULL) return ERROR_STYLE;
if (style >= image->num_styles) return ERROR_STYLE;
*num_stops = image->styles[style].num_stops;
return SUCCESS;
}
hvif_status
hvif_style_stop(
hvif_image* image, uint8_t style, uint8_t stop,
hvif_gradient_stop* gradient_stop)
{
if (image == NULL) return ERROR_STYLE;
if (style >= image->num_styles) return ERROR_STYLE;
if (stop >= image->styles[style].num_stops) return ERROR_STYLE;
gradient_stop->color.red = COLOR_GET_RED(image->styles[style].colors[stop]);
gradient_stop->color.green =
COLOR_GET_GREEN(image->styles[style].colors[stop]);
gradient_stop->color.blue = COLOR_GET_BLUE(image->styles[style].colors[stop]);
gradient_stop->color.alpha =
COLOR_GET_ALPHA(image->styles[style].colors[stop]);
gradient_stop->offset = image->styles[style].offsets[stop];
return SUCCESS;
}
hvif_status
hvif_style_transformation(
hvif_image* image, uint8_t style, hvif_matrix* transformation)
{
if (image == NULL) return ERROR_STYLE;
if (style >= image->num_styles) return ERROR_STYLE;
*transformation = image->styles[style].transformation;
return SUCCESS;
}
#endif /* INTERNAL_DATASTRUCTURES */

View File

@ -2,7 +2,7 @@
* \file hvif-light.h
* \author Hans-Jörg Schurr
*
* \brief Parse \a hvif images.
* \brief Parse a \a hvif images.
*
* This library provides functions for parsing Haiku Vector Icon
* files. The parser should be able to parse any files generated by Haiku
@ -16,18 +16,19 @@
#define HVIF_LIGHT_H
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
/** \typedef The result of parsing an image. */
/** \typedef The general result type. */
typedef enum hvif_status
{
SUCCESS = 0, /**< The image has been parsed into memory. */
ERROR_EOF, /**< The file ended before parsing finished. */
ERROR_NOMEM, /**< Not enough memory could be allocated. */
ERROR_MAGIC, /**< The magic number of the file is wrong. */
ERROR_STYLE, /**< Parsing a style failed. */
ERROR_PATH, /**< Parsing a path failed. */
ERROR_SHAPE /**< Parsing a shape failed. */
ERROR_STYLE, /**< A style related error occurred. */
ERROR_PATH, /**< A path related error occurred. */
ERROR_SHAPE /**< A shape related error occurred. */
} hvif_status;
/**
@ -63,5 +64,117 @@ hvif_result hvif_from_file(FILE* file);
*/
void hvif_free(hvif_image* image);
#endif /* HVIF_LIGHT_H */
/**
* \defgroup Inspection API to inspect images
* @{
*/
/**
* \brief Returns the number of styles of a \a hvif image.
* \param[in] file A valid image.
* \return The number of styles in the image.
*/
uint8_t hvif_num_styles(hvif_image* image);
/**
* \brief Returns the number of paths of a \a hvif image.
* \param[in] file A valid image.
* \return The number of paths in the image.
*/
uint8_t hvif_num_paths(hvif_image* image);
/**
* \brief Returns the number of shapes of a \a hvif image.
* \param[in] file A valid image.
* \return The number of shapes in the image.
*/
uint8_t hvif_num_shapes(hvif_image* image);
/** \typedef Gradient types used by HVIF. */
typedef enum hvif_gradients_type
{
HVIF_GRADIENT_LINEAR =
0, /**< A linear gradient. A solid color is a linear gradient with only one stop */
HVIF_GRADIENT_CIRCULAR, /**< A circular gradient. */
HVIF_GRADIENT_DIAMOND, /**< A diamond gradient. */
HVIF_GRADIENT_CONIC,
HVIF_GRADIENT_XY,
HVIF_GRADIENT_SQRT_XY,
HVIF_GRADIENT_TYPE_MAX /**< The number of valid gradient types. */
} hvif_gradients_type;
/**
* \brief Returns the gradient type of a style.
* \param[in] file A valid image.
* \param[in] style The index of the style.
* \param[out] type The gradient type of the style.
* \return ERROR_STYLE if this style does not exist.
*/
hvif_status hvif_style_gradient_type(
hvif_image* image, uint8_t style, hvif_gradients_type* type);
/**
* \brief Returns the number of gradient stops of a style.
* \param[in] file A valid image.
* \param[in] style The index of the style.
* \param[out] num_stops The number of stops.
* \return ERROR_STYLE if this style does not exist.
*/
hvif_status hvif_style_num_stops(
hvif_image* image, uint8_t style, uint8_t* num_stops);
/** \typedef A color. */
typedef struct hvif_color hvif_color;
struct hvif_color
{
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t alpha;
};
/** \typedef A gradient stop: a color and an offset between 0.0 and 1.0. */
typedef struct hvif_gradient_stop hvif_gradient_stop;
struct hvif_gradient_stop
{
hvif_color color; /**< The color of the gradient stop. */
float offset; /**< The offset of the stop between 0.0 and 1.0. */
};
/**
* \brief Returns a gradient stop.
* \param[in] file A valid image.
* \param[in] style The index of the style.
* \param[in] stop The index of the stop.
* \param[out] stop The gradient stop.
* \return ERROR_STYLE if this style or stop index does not exist.
*/
hvif_status hvif_style_stop(
hvif_image* image, uint8_t style, uint8_t stop,
hvif_gradient_stop* gradient_stop);
/** \typedef An affine transformation matrix. */
typedef struct hvif_matrix hvif_matrix;
struct hvif_matrix
{
double xx;
double yx;
double xy;
double yy;
double x0;
double y0;
};
/**
* \brief Returns the transformation applied to a style.
* \param[in] file A valid image.
* \param[in] style The index of the style.
* \param[out] transformation The transformation matrix.
* \return ERROR_STYLE if this style does not exist.
*/
hvif_status hvif_style_transformation(
hvif_image* image, uint8_t style, hvif_matrix* transformation);
/**@}*/
#endif /* HVIF_LIGHT_H */