ladybird/Libraries/LibWeb/Painting/PaintStyle.h

117 lines
3.8 KiB
C
Raw Normal View History

/*
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/RefCounted.h>
#include <AK/Variant.h>
#include <LibGfx/PaintStyle.h>
namespace Web::Painting {
struct ColorStop {
Color color;
float position = AK::NaN<float>;
Optional<float> transition_hint = {};
};
class SVGGradientPaintStyle : public RefCounted<SVGGradientPaintStyle> {
public:
enum class SpreadMethod {
Pad,
Repeat,
Reflect
};
Optional<Gfx::AffineTransform> const& gradient_transform() const { return m_gradient_transform; }
void set_gradient_transform(Gfx::AffineTransform transform) { m_gradient_transform = transform; }
SpreadMethod spread_method() const { return m_spread_method; }
void set_spread_method(SpreadMethod spread_method) { m_spread_method = spread_method; }
void add_color_stop(float position, Color color, Optional<float> transition_hint = {})
{
return add_color_stop(ColorStop { color, position, transition_hint });
}
void add_color_stop(ColorStop stop, bool sort = true)
{
m_color_stops.append(stop);
if (sort)
quick_sort(m_color_stops, [](auto& a, auto& b) { return a.position < b.position; });
}
ReadonlySpan<ColorStop> color_stops() const { return m_color_stops; }
Optional<float> repeat_length() const { return m_repeat_length; }
virtual ~SVGGradientPaintStyle() { }
protected:
Vector<ColorStop, 4> m_color_stops;
Optional<float> m_repeat_length;
Optional<Gfx::AffineTransform> m_gradient_transform {};
SpreadMethod m_spread_method { SpreadMethod::Pad };
};
class SVGLinearGradientPaintStyle final : public SVGGradientPaintStyle {
public:
static NonnullRefPtr<SVGLinearGradientPaintStyle> create(Gfx::FloatPoint start_point, Gfx::FloatPoint end_point)
{
return adopt_ref(*new SVGLinearGradientPaintStyle(start_point, end_point));
}
LibWeb: Add Skia painting command executor This change introduces Skia painter available under a flag. It's not yet match capabilities of Gfx::Painter and is not ready to replace it. Motivation: - The current CPU painter is a performance bottleneck on most websites. Our own GPU painter implementation is very immature and has received relatively little attention. - There is ongoing effort on building painter that supports affine transforms (AffineCommandExecutorCPU) but it is far from being on par with the default CPU painter. Skia will allow us to immediately get full transformation support for all painting commands. GPU painting: I experimented with Ganesh GPU-backend, however profiling revealed that without sharing viewport texture between WebContent and Browser processes, it won't bring much performance improvement compared to CPU-backend. Therefore, I decided to keep this PR focused on implementing most of painting commands and switch to GPU-backend in future changes. Text rendring: Skia painter uses glyph bitmaps produced by LibGfx. Using Skia for text rendering will require large refactoring of the font rendering subsystem. Currently, it's impossible to construct SkFont right before rendering because Gfx::VectorFont can't be serialized back into sequence of bytes. There is a problem with ugly include paths like: `#include <core/SkBitmap.h>`. I would prefer to have skia prefix in the path. There was an attempt to fix that but PR was rejected https://github.com/microsoft/vcpkg/pull/32660 Regressions compared to Gfx::Painter: - DrawText is not implemented - PaintTextShadow is not implemented - PaintRadialGradient and PaintLinearGradient do not support "transition hints" and repeat length - PaintConicGradient is not implemented - DrawTriangleWave is not implemented - DrawLine does not account for line style property - DrawScaledBitmap and DrawScaledImmutableBitmap do not account for scaling mode property
2024-06-10 14:22:04 +03:00
Gfx::FloatPoint start_point() const { return m_start_point; }
Gfx::FloatPoint end_point() const { return m_end_point; }
void set_start_point(Gfx::FloatPoint start_point) { m_start_point = start_point; }
void set_end_point(Gfx::FloatPoint end_point) { m_end_point = end_point; }
private:
SVGLinearGradientPaintStyle(Gfx::FloatPoint start_point, Gfx::FloatPoint end_point)
: m_start_point(start_point)
, m_end_point(end_point)
{
}
Gfx::FloatPoint m_start_point;
Gfx::FloatPoint m_end_point;
};
class SVGRadialGradientPaintStyle final : public SVGGradientPaintStyle {
public:
static NonnullRefPtr<SVGRadialGradientPaintStyle> create(Gfx::FloatPoint start_center, float start_radius, Gfx::FloatPoint end_center, float end_radius)
{
return adopt_ref(*new SVGRadialGradientPaintStyle(start_center, start_radius, end_center, end_radius));
}
Gfx::FloatPoint start_center() const { return m_start_center; }
float start_radius() const { return m_start_radius; }
Gfx::FloatPoint end_center() const { return m_end_center; }
float end_radius() const { return m_end_radius; }
void set_start_center(Gfx::FloatPoint start_center) { m_start_center = start_center; }
void set_start_radius(float start_radius) { m_start_radius = start_radius; }
void set_end_center(Gfx::FloatPoint end_center) { m_end_center = end_center; }
void set_end_radius(float end_radius) { m_end_radius = end_radius; }
private:
SVGRadialGradientPaintStyle(Gfx::FloatPoint start_center, float start_radius, Gfx::FloatPoint end_center, float end_radius)
: m_start_center(start_center)
, m_start_radius(start_radius)
, m_end_center(end_center)
, m_end_radius(end_radius)
{
}
Gfx::FloatPoint m_start_center;
float m_start_radius { 0.0f };
Gfx::FloatPoint m_end_center;
float m_end_radius { 0.0f };
};
}