summaryrefslogtreecommitdiff
path: root/libs/litehtml/src/background.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/litehtml/src/background.cpp')
-rw-r--r--libs/litehtml/src/background.cpp304
1 files changed, 117 insertions, 187 deletions
diff --git a/libs/litehtml/src/background.cpp b/libs/litehtml/src/background.cpp
index b7ae75c6b6..3ef69b862d 100644
--- a/libs/litehtml/src/background.cpp
+++ b/libs/litehtml/src/background.cpp
@@ -1,4 +1,5 @@
#include <cmath>
+
#include "html.h"
#include "background.h"
#include "render_item.h"
@@ -7,6 +8,9 @@
# define M_PI 3.14159265358979323846
#endif
+namespace litehtml
+{
+
bool litehtml::background::get_layer(int idx, position pos, const element* el, const std::shared_ptr<render_item>& ri, background_layer& layer) const
{
if(idx < 0 || idx >= get_layers_number())
@@ -175,9 +179,9 @@ std::unique_ptr<litehtml::background_layer::image> litehtml::background::get_ima
{
if(idx >= 0 && idx < (int) m_image.size())
{
- if(m_image[idx].type == background_image::bg_image_type_url)
+ if(m_image[idx].type == image::type_url)
{
- auto ret = std::unique_ptr<background_layer::image>(new background_layer::image());
+ auto ret = std::make_unique<background_layer::image>();
ret->url = m_image[idx].url;
ret->base_url = m_baseurl;
return ret;
@@ -190,7 +194,7 @@ std::unique_ptr<litehtml::background_layer::color> litehtml::background::get_col
{
if(idx == (int) m_image.size())
{
- auto ret = std::unique_ptr<background_layer::color>(new background_layer::color());
+ auto ret = std::make_unique<background_layer::color>();
ret->color = m_color;
return ret;
}
@@ -280,24 +284,24 @@ static float distance(const litehtml::pointF& p1, const litehtml::pointF& p2)
std::unique_ptr<litehtml::background_layer::linear_gradient> litehtml::background::get_linear_gradient_layer(int idx, const background_layer& layer) const
{
if(idx < 0 || idx >= (int) m_image.size()) return {};
- if(m_image[idx].type != background_image::bg_image_type_gradient) return {};
- if(m_image[idx].gradient.m_type != background_gradient::linear_gradient &&
- m_image[idx].gradient.m_type != background_gradient::repeating_linear_gradient) return {};
+ if(m_image[idx].type != image::type_gradient) return {};
+ if(m_image[idx].m_gradient.m_type != _linear_gradient_ &&
+ m_image[idx].m_gradient.m_type != _repeating_linear_gradient_) return {};
- auto ret = std::unique_ptr<background_layer::linear_gradient>(new background_layer::linear_gradient());
+ auto ret = std::make_unique<background_layer::linear_gradient>();
float angle;
- if(m_image[idx].gradient.m_side == 0)
+ if(m_image[idx].m_gradient.m_side == 0)
{
- angle = m_image[idx].gradient.angle;
+ angle = m_image[idx].m_gradient.angle;
} else
{
auto rise = (float) layer.origin_box.width;
auto run = (float) layer.origin_box.height;
- if(m_image[idx].gradient.m_side & background_gradient::gradient_side_left)
+ if(m_image[idx].m_gradient.m_side & gradient_side_left)
{
run *= -1;
}
- if(m_image[idx].gradient.m_side & background_gradient::gradient_side_bottom)
+ if(m_image[idx].m_gradient.m_side & gradient_side_bottom)
{
rise *= -1;
}
@@ -312,7 +316,7 @@ std::unique_ptr<litehtml::background_layer::linear_gradient> litehtml::backgroun
auto line_len = distance(ret->start, ret->end);
- if(!ret->prepare_color_points(line_len, m_image[idx].gradient.m_type, m_image[idx].gradient.m_colors))
+ if(!ret->prepare_color_points(line_len, m_image[idx].m_gradient.m_type, m_image[idx].m_gradient.m_colors))
{
return {};
}
@@ -392,51 +396,51 @@ static inline litehtml::pointF find_corner(const litehtml::pointF& center, const
std::unique_ptr<litehtml::background_layer::radial_gradient> litehtml::background::get_radial_gradient_layer(int idx, const background_layer& layer) const
{
if(idx < 0 || idx >= (int) m_image.size()) return {};
- if(m_image[idx].type != background_image::bg_image_type_gradient) return {};
- if(m_image[idx].gradient.m_type != background_gradient::radial_gradient &&
- m_image[idx].gradient.m_type != background_gradient::repeating_radial_gradient) return {};
+ if(m_image[idx].type != image::type_gradient) return {};
+ if(m_image[idx].m_gradient.m_type != _radial_gradient_ &&
+ m_image[idx].m_gradient.m_type != _repeating_radial_gradient_) return {};
- auto ret = std::unique_ptr<background_layer::radial_gradient>(new background_layer::radial_gradient());
+ auto ret = std::make_unique<background_layer::radial_gradient>();
ret->position.x = (float) layer.origin_box.x + (float) layer.origin_box.width / 2.0f;
ret->position.y = (float) layer.origin_box.y + (float) layer.origin_box.height / 2.0f;
- if(m_image[idx].gradient.m_side & background_gradient::gradient_side_left)
+ if(m_image[idx].m_gradient.m_side & gradient_side_left)
{
ret->position.x = (float) layer.origin_box.left();
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_right)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_right)
{
ret->position.x = (float) layer.origin_box.right();
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_x_center)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_x_center)
{
ret->position.x = (float) layer.origin_box.left() + (float) layer.origin_box.width / 2.0f;
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_x_length)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_x_length)
{
- ret->position.x = (float) layer.origin_box.left() + (float) m_image[idx].gradient.radial_position_x.calc_percent(layer.origin_box.width);
+ ret->position.x = (float) layer.origin_box.left() + (float) m_image[idx].m_gradient.position_x.calc_percent(layer.origin_box.width);
}
- if(m_image[idx].gradient.m_side & background_gradient::gradient_side_top)
+ if(m_image[idx].m_gradient.m_side & gradient_side_top)
{
ret->position.y = (float) layer.origin_box.top();
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_bottom)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_bottom)
{
ret->position.y = (float) layer.origin_box.bottom();
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_y_center)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_y_center)
{
ret->position.y = (float) layer.origin_box.top() + (float) layer.origin_box.height / 2.0f;
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_y_length)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_y_length)
{
- ret->position.y = (float) layer.origin_box.top() + (float) m_image[idx].gradient.radial_position_y.calc_percent(layer.origin_box.height);
+ ret->position.y = (float) layer.origin_box.top() + (float) m_image[idx].m_gradient.position_y.calc_percent(layer.origin_box.height);
}
- if(m_image[idx].gradient.radial_extent)
+ if(m_image[idx].m_gradient.radial_extent)
{
- switch (m_image[idx].gradient.radial_extent)
+ switch (m_image[idx].m_gradient.radial_extent)
{
- case background_gradient::radial_extent_closest_corner:
+ case radial_extent_closest_corner:
{
- if (m_image[idx].gradient.radial_shape == background_gradient::radial_shape_circle)
+ if (m_image[idx].m_gradient.radial_shape == radial_shape_circle)
{
float corner1 = distance(ret->position, {(float) layer.origin_box.left(), (float) layer.origin_box.top()});
float corner2 = distance(ret->position, {(float) layer.origin_box.right(), (float) layer.origin_box.top()});
@@ -461,8 +465,8 @@ std::unique_ptr<litehtml::background_layer::radial_gradient> litehtml::backgroun
}
}
break;
- case background_gradient::radial_extent_closest_side:
- if (m_image[idx].gradient.radial_shape == background_gradient::radial_shape_circle)
+ case radial_extent_closest_side:
+ if (m_image[idx].m_gradient.radial_shape == radial_shape_circle)
{
ret->radius.x = ret->radius.y = std::min(
{
@@ -483,9 +487,9 @@ std::unique_ptr<litehtml::background_layer::radial_gradient> litehtml::backgroun
);
}
break;
- case background_gradient::radial_extent_farthest_corner:
+ case radial_extent_farthest_corner:
{
- if (m_image[idx].gradient.radial_shape == background_gradient::radial_shape_circle)
+ if (m_image[idx].m_gradient.radial_shape == radial_shape_circle)
{
float corner1 = distance(ret->position, {(float) layer.origin_box.left(), (float) layer.origin_box.top()});
float corner2 = distance(ret->position, {(float) layer.origin_box.right(), (float) layer.origin_box.top()});
@@ -510,8 +514,8 @@ std::unique_ptr<litehtml::background_layer::radial_gradient> litehtml::backgroun
}
}
break;
- case background_gradient::radial_extent_farthest_side:
- if (m_image[idx].gradient.radial_shape == background_gradient::radial_shape_circle)
+ case radial_extent_farthest_side:
+ if (m_image[idx].m_gradient.radial_shape == radial_shape_circle)
{
ret->radius.x = ret->radius.y = std::max(
{
@@ -536,16 +540,16 @@ std::unique_ptr<litehtml::background_layer::radial_gradient> litehtml::backgroun
break;
}
}
- if(!m_image[idx].gradient.radial_length_x.is_predefined())
+ if(!m_image[idx].m_gradient.radial_radius_x.is_predefined())
{
- ret->radius.x = (float) m_image[idx].gradient.radial_length_x.calc_percent(layer.origin_box.width);
+ ret->radius.x = (float) m_image[idx].m_gradient.radial_radius_x.calc_percent(layer.origin_box.width);
}
- if(!m_image[idx].gradient.radial_length_y.is_predefined())
+ if(!m_image[idx].m_gradient.radial_radius_y.is_predefined())
{
- ret->radius.y = (float) m_image[idx].gradient.radial_length_y.calc_percent(layer.origin_box.height);
+ ret->radius.y = (float) m_image[idx].m_gradient.radial_radius_y.calc_percent(layer.origin_box.height);
}
- if(ret->prepare_color_points(ret->radius.x, m_image[idx].gradient.m_type, m_image[idx].gradient.m_colors))
+ if(ret->prepare_color_points(ret->radius.x, m_image[idx].m_gradient.m_type, m_image[idx].m_gradient.m_colors))
{
return ret;
}
@@ -556,47 +560,48 @@ std::unique_ptr<litehtml::background_layer::radial_gradient> litehtml::backgroun
std::unique_ptr<litehtml::background_layer::conic_gradient> litehtml::background::get_conic_gradient_layer(int idx, const background_layer& layer) const
{
if(idx < 0 || idx >= (int) m_image.size()) return {};
- if(m_image[idx].type != background_image::bg_image_type_gradient) return {};
- if(m_image[idx].gradient.m_type != background_gradient::conic_gradient) return {};
+ if(m_image[idx].type != image::type_gradient) return {};
+ if (m_image[idx].m_gradient.m_type != _conic_gradient_ &&
+ m_image[idx].m_gradient.m_type != _repeating_conic_gradient_) return {};
- auto ret = std::unique_ptr<background_layer::conic_gradient>(new background_layer::conic_gradient());
+ auto ret = std::make_unique<background_layer::conic_gradient>();
ret->position.x = (float) layer.origin_box.x + (float) layer.origin_box.width / 2.0f;
ret->position.y = (float) layer.origin_box.y + (float) layer.origin_box.height / 2.0f;
- if(m_image[idx].gradient.m_side & background_gradient::gradient_side_left)
+ if(m_image[idx].m_gradient.m_side & gradient_side_left)
{
ret->position.x = (float) layer.origin_box.left();
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_right)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_right)
{
ret->position.x = (float) layer.origin_box.right();
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_x_center)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_x_center)
{
ret->position.x = (float) layer.origin_box.left() + (float) layer.origin_box.width / 2.0f;
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_x_length)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_x_length)
{
- ret->position.x = (float) layer.origin_box.left() + (float) m_image[idx].gradient.radial_position_x.calc_percent(layer.origin_box.width);
+ ret->position.x = (float) layer.origin_box.left() + (float) m_image[idx].m_gradient.position_x.calc_percent(layer.origin_box.width);
}
- if(m_image[idx].gradient.m_side & background_gradient::gradient_side_top)
+ if(m_image[idx].m_gradient.m_side & gradient_side_top)
{
ret->position.y = (float) layer.origin_box.top();
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_bottom)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_bottom)
{
ret->position.y = (float) layer.origin_box.bottom();
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_y_center)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_y_center)
{
ret->position.y = (float) layer.origin_box.top() + (float) layer.origin_box.height / 2.0f;
- } else if(m_image[idx].gradient.m_side & background_gradient::gradient_side_y_length)
+ } else if(m_image[idx].m_gradient.m_side & gradient_side_y_length)
{
- ret->position.y = (float) layer.origin_box.top() + (float) m_image[idx].gradient.radial_position_y.calc_percent(layer.origin_box.height);
+ ret->position.y = (float) layer.origin_box.top() + (float) m_image[idx].m_gradient.position_y.calc_percent(layer.origin_box.height);
}
- ret->angle = m_image[idx].gradient.conic_from_angle;
- ret->color_space = m_image[idx].gradient.conic_color_space;
- ret->interpolation = m_image[idx].gradient.conic_interpolation;
+ ret->angle = m_image[idx].m_gradient.conic_from_angle;
+ ret->color_space = m_image[idx].m_gradient.color_space;
+ ret->hue_interpolation = m_image[idx].m_gradient.hue_interpolation;
- if(ret->prepare_angle_color_points(m_image[idx].gradient.m_type, m_image[idx].gradient.m_colors))
+ if(ret->prepare_color_points(0, m_image[idx].m_gradient.m_type, m_image[idx].m_gradient.m_colors))
{
return ret;
}
@@ -611,19 +616,19 @@ litehtml::background::layer_type litehtml::background::get_layer_type(int idx) c
switch (m_image[idx].type)
{
- case background_image::bg_image_type_url:
+ case image::type_url:
return type_image;
- case background_image::bg_image_type_gradient:
- switch (m_image[idx].gradient.m_type)
+ case image::type_gradient:
+ switch (m_image[idx].m_gradient.m_type)
{
- case background_gradient::linear_gradient:
- case background_gradient::repeating_linear_gradient:
+ case _linear_gradient_:
+ case _repeating_linear_gradient_:
return type_linear_gradient;
- case background_gradient::radial_gradient:
- case background_gradient::repeating_radial_gradient:
+ case _radial_gradient_:
+ case _repeating_radial_gradient_:
return type_radial_gradient;
- case background_gradient::conic_gradient:
- case background_gradient::repeating_conic_gradient:
+ case _conic_gradient_:
+ case _repeating_conic_gradient_:
return type_conic_gradient;
default:
break;
@@ -653,6 +658,7 @@ void litehtml::background::draw_layer(uint_ptr hdc, int idx, const background_la
}
break;
case background::type_image:
+ if(layer.origin_box.width != 0 && layer.origin_box.height != 0)
{
auto image_layer = get_image_layer(idx);
if(image_layer)
@@ -662,6 +668,7 @@ void litehtml::background::draw_layer(uint_ptr hdc, int idx, const background_la
}
break;
case background::type_linear_gradient:
+ if(layer.origin_box.width != 0 && layer.origin_box.height != 0)
{
auto gradient_layer = get_linear_gradient_layer(idx, layer);
if(gradient_layer)
@@ -671,6 +678,7 @@ void litehtml::background::draw_layer(uint_ptr hdc, int idx, const background_la
}
break;
case background::type_radial_gradient:
+ if(layer.origin_box.width != 0 && layer.origin_box.height != 0)
{
auto gradient_layer = get_radial_gradient_layer(idx, layer);
if(gradient_layer)
@@ -680,6 +688,7 @@ void litehtml::background::draw_layer(uint_ptr hdc, int idx, const background_la
}
break;
case background::type_conic_gradient:
+ if(layer.origin_box.width != 0 && layer.origin_box.height != 0)
{
auto gradient_layer = get_conic_gradient_layer(idx, layer);
if(gradient_layer)
@@ -693,14 +702,14 @@ void litehtml::background::draw_layer(uint_ptr hdc, int idx, const background_la
}
}
-static void repeat_color_points(std::vector<litehtml::background_layer::color_point>& color_points, float max_val)
+static void repeat_color_points(std::vector<litehtml::background_layer::color_point>& color_points)
{
auto old_points = color_points;
- if(color_points.back().offset < max_val)
+ if(color_points.back().offset < 1)
{
float gd_size = color_points.back().offset - old_points.front().offset;
auto iter = old_points.begin();
- while (color_points.back().offset < max_val)
+ while (color_points.back().offset < 1)
{
color_points.emplace_back(iter->offset + gd_size, iter->color);
std::advance(iter, 1);
@@ -763,13 +772,27 @@ void litehtml::background_layer::gradient_base::color_points_transparent_fix()
}
}
-bool litehtml::background_layer::gradient_base::prepare_color_points(float line_len, background_gradient::gradient_type g_type, const std::vector<background_gradient::gradient_color> &colors)
+// normalize length into value between 0 and 1
+float normalize_length(css_length length, float line_len)
+{
+ if (length.units() == css_units_percentage)
+ {
+ return length.val() / 100.0f;
+ }
+ else if (line_len != 0)
+ {
+ return length.val() / line_len;
+ }
+ return length.val();
+}
+
+bool litehtml::background_layer::gradient_base::prepare_color_points(float line_len, string_id g_type, const std::vector<gradient::color_stop> &colors)
{
bool repeating;
- if(g_type == background_gradient::linear_gradient || g_type == background_gradient::radial_gradient)
+ if(g_type == _linear_gradient_ || g_type == _radial_gradient_ || g_type == _conic_gradient_)
{
repeating = false;
- } else if(g_type == background_gradient::repeating_linear_gradient || g_type == background_gradient::repeating_radial_gradient)
+ } else if(g_type == _repeating_linear_gradient_ || g_type == _repeating_radial_gradient_ || g_type == _repeating_conic_gradient_)
{
repeating = true;
} else
@@ -780,22 +803,31 @@ bool litehtml::background_layer::gradient_base::prepare_color_points(float line_
bool has_transparent = false;
for(const auto& item : colors)
{
- if(item.color.alpha == 0)
+ if (item.is_color_hint)
+ {
+ if (!color_points.empty())
+ {
+ color_points.back().hint = item.length ?
+ normalize_length(*item.length, line_len) :
+ *item.angle / 360;
+ }
+ continue;
+ }
+ if (item.color.alpha == 0)
{
has_transparent = true;
}
- if(item.length.units() == css_units_percentage)
+ if (item.length)
{
- color_points.emplace_back(item.length.val() / 100.0f, item.color);
- } else if(item.length.units() != css_units_none)
+ color_points.emplace_back(normalize_length(*item.length, line_len), item.color);
+ }
+ else if (item.angle)
{
- if(line_len != 0)
- {
- color_points.emplace_back(item.length.val() / line_len, item.color);
- }
- } else
+ color_points.emplace_back(*item.angle / 360, item.color);
+ }
+ else
{
- if(!color_points.empty())
+ if (!color_points.empty())
{
none_units++;
}
@@ -868,112 +900,10 @@ bool litehtml::background_layer::gradient_base::prepare_color_points(float line_
if(repeating)
{
- repeat_color_points(color_points, 1.0f);
+ repeat_color_points(color_points);
}
return true;
}
-bool litehtml::background_layer::gradient_base::prepare_angle_color_points(background_gradient::gradient_type g_type, const std::vector<background_gradient::gradient_color> &colors)
-{
- bool repeating;
- if(g_type != background_gradient::conic_gradient)
- {
- repeating = false;
- } else if(g_type != background_gradient::repeating_conic_gradient)
- {
- repeating = true;
- } else
- {
- return false;
- }
- int none_units = 0;
- bool has_transparent = false;
- for(const auto& item : colors)
- {
- if(item.color.alpha == 0)
- {
- has_transparent = true;
- }
- if(item.angle.is_default())
- {
- if(!color_points.empty())
- {
- none_units++;
- }
- color_points.emplace_back(0.0f, item.color);
- } else
- {
- color_points.emplace_back(item.angle, item.color);
- }
- }
- if(color_points.empty())
- {
- return false;
- }
-
- if(!repeating)
- {
- // Add color point with offset 0 if not exists
- if (color_points[0].offset != 0)
- {
- color_points.emplace(color_points.begin(), 0.0f, color_points[0].color);
- }
- // Add color point with offset 1.0 if not exists
- if (color_points.back().offset < 360.0f)
- {
- if (color_points.back().offset == 0)
- {
- color_points.back().offset = 360.0f;
- none_units--;
- } else
- {
- color_points.emplace_back(360.0f, color_points.back().color);
- }
- }
- } else
- {
- if (color_points.back().offset == 0)
- {
- color_points.back().offset = 360.0f;
- none_units--;
- }
- }
-
- if(none_units > 0)
- {
- size_t i = 1;
- while(i < color_points.size())
- {
- if(color_points[i].offset != 0)
- {
- i++;
- continue;
- }
- // Find next defined offset
- size_t j = i + 1;
- while (color_points[j].offset == 0) j++;
- size_t num = j - i;
- float sum = color_points[i - 1].offset + color_points[j].offset;
- float offset = sum / (float) (num + 1);
- while(i < j)
- {
- color_points[i].offset = color_points[i - 1].offset + offset;
- i++;
- }
- }
- }
-
- // process transparent
- if(has_transparent)
- {
- color_points_transparent_fix();
- }
-
- if(repeating)
- {
- repeat_color_points(color_points, 1.0f);
- }
-
- return true;
-}
+} // namespace litehtml \ No newline at end of file