/*
7 * Tomasz Boczkowski <penginsbacon@gmail.com>
9 * Copyright (C) 2014 Authors
10 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
13#include <cairomm/region.h>
32 cairo_surface_set_device_scale(
surface->cobj(), device_scale, device_scale);
88 auto const idt = dt.inverse();
90 auto const screen_to_tile =
_ctm.
inverse() * pattern_to_tile;
94 for (
int i = 0; i < 2; i++) {
106 auto check = [&] (
int i) {
108 if (a[i].extent() >= period)
return true;
109 if (b[i].extent() > a[i].extent())
return false;
112 return check(0) && check(1);
117 auto check = [&] (
int i) {
119 if (a[i].extent() >= period)
return true;
120 if (b[i].extent() >= period)
return true;
123 return check(0) && check(1);
129 for (
int i = 0; i < 2; i++) {
133 return std::make_pair(min, max);
137 auto wrapped_paint = [&,
this] (
Surface const &a,
Geom::IntRect &b, Cairo::RefPtr<Cairo::Context>
const &cr, Cairo::RefPtr<Cairo::Region>
const &dirty) {
138 auto const [min, max] = overlapping_translates(a.rect, b);
143 cr->set_source(a.surface, rect.
left(), rect.top());
150 auto const area_orig = (
Geom::Rect(area) * screen_to_tile).roundOutwards();
151 auto const area_tile = canonicalised(area_orig);
155 auto lock = std::lock_guard(
mutables);
157 auto get_surface = [&,
this] () -> std::pair<
Surface*, Cairo::RefPtr<Cairo::Region>> {
160 if (wrapped_contains(s.rect, area_tile)) {
166 std::vector<Surface> merged;
167 auto expanded = area_tile;
170 bool modified =
false;
173 if (wrapped_touches(expanded, it->rect)) {
175 merged.emplace_back(std::move(*it));
184 if (!modified)
break;
188 expanded = canonicalised(expanded);
192 auto cr = Cairo::Context::create(
surface.surface);
198 for (
auto &m : merged) {
199 wrapped_paint(m, expanded, cr, dirty);
204 return std::make_pair(&
surfaces.back(), std::move(dirty));
208 auto [
surface, dirty] = get_surface();
212 if (
rc.antialiasing_override) {
237 for (
int i = 0; i < dirty->get_num_rectangles(); i++) {
239 for (
int x = 0; x <= 1; x++) {
240 for (
int y = 0; y <= 1; y++) {
243 if (!rect2)
continue;
250 paint(*rect2 - wrap);
252 if (opacity < 1.0 - 1e-3) {
267 auto cp = cairo_pattern_create_for_surface(
surface->surface->cobj());
270 cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT);
272 cairo_pattern_set_filter(cp, CAIRO_FILTER_NEAREST);
286 double const det_ctm = ctx.
ctm.
det();
288 double scale = std::sqrt(std::abs(det_ctm * det_ps2user));
void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m)
Cairo integration helpers.
Cairo::RefPtr< Cairo::ImageSurface > surface
3x3 matrix representing an affine transformation.
Coord det() const
Calculate the determinant.
bool isIdentity(Coord eps=EPSILON) const
Check whether this matrix is an identity matrix.
Affine inverse() const
Compute the inverse matrix.
bool hasZeroArea() const
Check whether the rectangle has zero area.
Axis aligned, non-empty, generic rectangle.
C left() const
Return leftmost coordinate of the rectangle (+X is to the right).
static CRect infinite()
Create infinite rectangle.
CPoint max() const
Get the corner of the rectangle with largest coordinate values.
Two-dimensional point with integer coordinates.
constexpr IntCoord x() const noexcept
constexpr IntCoord y() const noexcept
Axis aligned, non-empty rectangle.
RAII idiom for saving the state of DrawingContext.
Minimal wrapper over Cairo.
void setSource(cairo_pattern_t *source)
void transform(Geom::Affine const &trans)
void paint(double alpha=1.0)
void rectangle(Geom::Rect const &r)
void setOperator(cairo_operator_t op)
void translate(Geom::Point const &t)
unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset) override
unsigned render(DrawingContext &dc, RenderContext &rc, Geom::IntRect const &area, unsigned flags=0, DrawingItem const *stop_at=nullptr) const
Rasterize items.
Drawing & drawing() const
void _markForUpdate(unsigned state, bool propagate)
Marks the item as needing a recomputation of internal data.
Geom::Affine _ctm
Total transform from item coords to display coords.
void _markForRendering()
Marks the current visual bounding box of the item for redrawing.
Geom::Affine transform() const
void _dropPatternCache() override
void setTileRect(Geom::Rect const &)
Set the tile rect position and dimensions in content coordinate system.
void setPatternToUserTransform(Geom::Affine const &)
Set the transformation from pattern to user coordinate systems.
std::unique_ptr< Geom::Affine > _pattern_to_user
std::vector< Surface > surfaces
void setOverflow(Geom::Affine const &initial_transform, int steps, Geom::Affine const &step_transform)
Turn on overflow rendering.
unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset) override
Geom::Affine _overflow_step_transform
Geom::Affine _overflow_initial_transform
cairo_pattern_t * renderPattern(RenderContext &rc, Geom::IntRect const &area, float opacity, int device_scale) const
Render the pattern.
DrawingPattern(Drawing &drawing)
Geom::IntPoint _pattern_resolution
static char const *const current
Cairo drawing context with Inkscape extensions.
Canvas item belonging to an SVG drawing element.
Canvas belonging to SVG pattern.
_cairo_pattern cairo_pattern_t
Cairo surface that remembers its origin.
Specific geometry functions for Inkscape, not provided my lib2geom.
auto round_down(Geom::IntPoint const &a, Geom::IntPoint const &b)
void shift(T &a, T &b, T const &c)
Control handle rendering/caching.
GenericRect< IntCoord > IntRect
Affine identity()
Create an identity matrix.
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
T constexpr round_down(T a, T b)
Returns a rounded down to the nearest multiple of b, assuming b >= 1.
T constexpr round_up(T a, T b)
Returns a rounded up to the nearest multiple of b, assuming b >= 1.
Helper class to stream background task notifications as a series of messages.
void apply_antialias(DrawingContext &dc, Antialiasing antialias)
Apply antialias setting to Cairo.
auto constexpr PATTERN_MATRIX_EPSILON
Cairo::RefPtr< Cairo::ImageSurface > surface
Surface(Geom::IntRect const &rect, int device_scale)
Cairo::RectangleInt geom_to_cairo(const Geom::IntRect &rect)
Geom::IntRect cairo_to_geom(const Cairo::RectangleInt &rect)