#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