diff options
Diffstat (limited to 'libs/litehtml/src/background.cpp')
-rw-r--r-- | libs/litehtml/src/background.cpp | 304 |
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 |