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:
parent
0bb035050f
commit
a22aea9293
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,4 +86,3 @@ hvif_cairo_status hvif_cairo_render(
|
|||
cairo_t* context, hvif_image* image, double scale);
|
||||
|
||||
#endif /* HVIF_CAIRO_H */
|
||||
|
||||
|
|
112
src/hvif-light.c
112
src/hvif-light.c
|
@ -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 */
|
||||
|
|
125
src/hvif-light.h
125
src/hvif-light.h
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue