1
0
Fork 0

Compare commits

...

2 Commits

Author SHA1 Message Date
Hans-Joerg Schurr 50305e7f5e Use color expressed as a struct
This is nicer for the external API.
2021-04-25 20:53:40 +02:00
Hans-Joerg Schurr a22aea9293 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.
2021-04-25 20:32:26 +02:00
4 changed files with 212 additions and 65 deletions

View File

@ -20,8 +20,8 @@
* - Color space -> leave it a this for now since cairo doesn't support
* - Contour -> We don't support this for now
* - Multiple strokes -> We don't support this for now
* - Check miter limit -> why unit8_t for something that can well be a float
* in (0, 1)
* - Check miter limit -> why unit8_t for something that can be a float
* in (0, 1)?
*/
void
@ -45,10 +45,10 @@ print_matrix(const hvif_matrix* matrix)
}
#endif /* DEBUG */
#define R(c) (COLOR_GET_RED(c) / 255.0)
#define G(c) (COLOR_GET_GREEN(c) / 255.0)
#define B(c) (COLOR_GET_BLUE(c) / 255.0)
#define A(c) (COLOR_GET_ALPHA(c) / 255.0)
#define R(c) (c.red / 255.0)
#define G(c) (c.green / 255.0)
#define B(c) (c.blue / 255.0)
#define A(c) (c.alpha / 255.0)
/**
* \brief Create a patch for a diamond gradient.
@ -145,7 +145,7 @@ 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];
@ -153,7 +153,7 @@ create_pattern_style(cairo_pattern_t** pat, hvif_style* style)
*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];
@ -161,7 +161,7 @@ create_pattern_style(cairo_pattern_t** pat, hvif_style* style)
*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(
@ -180,7 +180,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,9 +209,9 @@ 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;
@ -222,9 +222,9 @@ create_pattern_style(cairo_pattern_t** pat, hvif_style* style)
*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;
@ -462,4 +462,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,19 +101,6 @@ struct hvif_point
#define POINT_ORIGIN \
(hvif_point) { 0.0, 0.0 }
typedef uint32_t hvif_color; /* 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)
#define COLOR_GET_ALPHA(C) ((C >> 24) & 0xff)
#define _BM8(N) (0xff << N)
#define COLOR_SET_RED(C, V) (C = ((C & (~_BM8(0))) | (V & 0xff)))
#define COLOR_SET_GREEN(C, V) (C = ((C & (~_BM8(8))) | ((V & 0xff) << 8)))
#define COLOR_SET_BLUE(C, V) (C = ((C & (~_BM8(16))) | ((V & 0xff) << 16)))
#define COLOR_SET_ALPHA(C, V) (C = ((C & (~_BM8(24))) | ((V & 0xff) << 24)))
#define COLOR_SET_RGB(C, R, G, B) \
(C = (C & (~0xffffff)) | (R & 0xff) | ((G & 0xff) << 8) | ((B & 0xff) << 16))
typedef struct hvif_transformer hvif_transformer;
struct hvif_transformer
{
@ -169,7 +133,7 @@ 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;
float* offsets;
@ -261,6 +225,13 @@ hvif_decode_hvif_matrix(uint8_t buffer[static 1])
};
}
#define COLOR_SET_RGB(C, R, G, B) \
do { \
C.red = R; \
C.green = G; \
C.blue = B; \
} while (0)
hvif_color
decode_color(uint8_t* buffer, bool gray, bool alpha)
{
@ -271,16 +242,19 @@ 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 c = (hvif_color){ 0 };
if (alpha) {
if (gray) {
COLOR_SET_RGB(c, buffer[0], buffer[0], buffer[0]);
COLOR_SET_ALPHA(c, buffer[1]);
c.alpha = buffer[1];
} else {
hvif_decode(c, buffer);
c.red = buffer[0];
c.green = buffer[1];
c.blue = buffer[2];
c.alpha = buffer[3];
}
} else {
COLOR_SET_ALPHA(c, 0xff);
c.alpha = 0xff;
if (gray) {
COLOR_SET_RGB(c, buffer[0], buffer[0], buffer[0]);
} else {
@ -303,7 +277,7 @@ read_color_style(hvif_style* style, uint8_t* buffer, bool gray, bool alpha)
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;
}
@ -806,5 +780,67 @@ 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 = 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 */