#ifndef LITEHTML_GRADIENT_H
#define LITEHTML_GRADIENT_H
#include "css_length.h"
#include "string_id.h"
#include "types.h"
#include "web_color.h"
namespace litehtml
{
enum gradient_side
{
gradient_side_none = 0,
gradient_side_left = 0x01,
gradient_side_right = 0x02,
gradient_side_top = 0x04,
gradient_side_bottom = 0x08,
gradient_side_x_center = 0x10,
gradient_side_y_center = 0x20,
gradient_side_x_length = 0x40,
gradient_side_y_length = 0x80,
};
static_assert(gradient_side_left == (1 << background_position_left), "parse_bg_position is also used to parse radial gradient position");
enum radial_shape_t
{
radial_shape_none,
radial_shape_circle,
radial_shape_ellipse,
};
#define radial_extent_strings "closest-corner;closest-side;farthest-corner;farthest-side"
enum radial_extent_t
{
radial_extent_none,
radial_extent_closest_corner,
radial_extent_closest_side,
radial_extent_farthest_corner,
radial_extent_farthest_side,
};
#define color_space_strings \
"srgb;"\
"srgb-linear;"\
"display-p3;"\
"a98-rgb;"\
"prophoto-rgb;"\
"rec2020;"\
"lab;"\
"oklab;"\
"xyz;"\
"xyz-d50;"\
"xyz-d65;"\
"hsl;"\
"hwb;"\
"lch;"\
"oklch"
enum color_space_t
{
color_space_none,
// rectangular-color-space
color_space_srgb,
color_space_srgb_linear,
color_space_display_p3,
color_space_a98_rgb,
color_space_prophoto_rgb,
color_space_rec2020,
color_space_lab,
color_space_oklab,
color_space_xyz,
color_space_xyz_d50,
color_space_xyz_d65,
// polar-color-space
color_space_hsl, color_space_polar_start = color_space_hsl,
color_space_hwb,
color_space_lch,
color_space_oklch,
};
#define hue_interpolation_strings "shorter;longer;increasing;decreasing"
enum hue_interpolation_t
{
hue_interpolation_none,
hue_interpolation_shorter,
hue_interpolation_longer,
hue_interpolation_increasing,
hue_interpolation_decreasing
};
class gradient
{
public:
// https://drafts.csswg.org/css-images-4/#typedef-color-stop-list
// color_stop represents | | |
// = {1,2}?
// =
// = {1,2}?
// =
// If two lengths/angles are specified they create two color-stops with the same color.
class color_stop
{
public:
bool is_color_hint = false;
web_color color;
optional length;
optional angle;
color_stop() {}
color_stop(web_color color) : color(color) {}
color_stop(web_color color, css_length length) : color(color), length(length) {}
color_stop(web_color color, float angle) : color(color), angle(angle) {}
color_stop(css_length length) : is_color_hint(true), length(length) {}
color_stop(float angle) : is_color_hint(true), angle(angle) {}
};
string_id m_type;
uint32_t m_side;
float angle;
vector m_colors;
css_length position_x;
css_length position_y;
radial_shape_t radial_shape;
radial_extent_t radial_extent;
css_length radial_radius_x;
css_length radial_radius_y;
float conic_from_angle;
color_space_t color_space;
hue_interpolation_t hue_interpolation;
explicit gradient(string_id type = empty_id)
{
m_type = type;
// linear gradient: m_side default is gradient_side_none (use angle)
// radial,conic gradient: m_side default is gradient_side_x_center | gradient_side_y_center (see parse_gradient)
m_side = gradient_side_none;
// linear gradient angle, used when m_side == gradient_side_none
angle = 180; // to bottom
// radial,conic position (together with m_side)
position_x.predef(0);
position_y.predef(0);
// actual default depends on the number of radii provided, see parse_radial_gradient_shape_size_position_interpolation
radial_shape = radial_shape_ellipse;
// https://drafts.csswg.org/css-images-3/#valdef-radial-gradient-radial-size
// if radius is specified radial_extent will be set to none, see parse_radial_size
radial_extent = radial_extent_farthest_corner;
radial_radius_x.predef(0);
radial_radius_y.predef(0);
conic_from_angle = 0;
// If the host syntax does not define what color space interpolation should take place in, it defaults to Oklab.
color_space = color_space_oklab;
// Unless otherwise specified, if no specific hue interpolation algorithm is selected by the host syntax, the default is shorter.
hue_interpolation = hue_interpolation_shorter;
}
bool is_empty() const
{
return m_type == empty_id || m_colors.empty();
}
bool is_linear() const { return m_type == _linear_gradient_ || m_type == _repeating_linear_gradient_; }
bool is_radial() const { return m_type == _radial_gradient_ || m_type == _repeating_radial_gradient_; }
bool is_conic() const { return m_type == _conic_gradient_ || m_type == _repeating_conic_gradient_; }
static gradient transparent;
};
class image
{
public:
enum type
{
type_none,
type_url,
type_gradient,
};
type type;
string url;
gradient m_gradient;
image() : type(type_none) {}
bool is_empty() const
{
switch (type)
{
case type_none:
return true;
case type_url:
return url.empty();
case type_gradient:
return m_gradient.is_empty();
}
return true;
}
};
bool parse_gradient(const css_token& token, gradient& gradient, document_container* container);
}
#endif //LITEHTML_GRADIENT_H