/*
7 * Krzysztof KosiĆski <tweenk.pl@gmail.com>
9 * Copyright (C) 2010 Authors
10 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
13#ifndef SEEN_INKSCAPE_DISPLAY_CAIRO_TEMPLATES_H
14#define SEEN_INKSCAPE_DISPLAY_CAIRO_TEMPLATES_H
38 data =
reinterpret_cast<T *
>(cairo_image_surface_get_data(
surface));
43 if constexpr (
sizeof(T) == 1) {
52 if constexpr (
sizeof(T) == 1) {
60template <
typename AccOut,
typename Acc1,
typename Acc2,
typename Blend>
70 auto const pool = get_global_dispatch_pool();
72 for (
int j = 0; j <
w; ++j) {
73 acc_out.
set(j, i, blend(acc_in1.
get(j, i), acc_in2.
get(j, i)));
78template <
typename AccOut,
typename AccIn,
typename Filter>
87 auto const pool = get_global_dispatch_pool();
89 for (
int j = 0; j <
w; ++j) {
90 acc_out.
set(j, i, filter(acc_in.
get(j, i)));
95template <
typename AccOut,
typename Synth>
103 int const limit = (x1 - x0) * (y1 - y0);
104 auto const pool = get_global_dispatch_pool();
106 int const i = y0 + y;
108 for (
int j = x0; j < x1; ++j) {
109 acc_out.
set(j, i, synth(j, i));
121template <
typename Blend>
124 cairo_surface_flush(in1);
125 cairo_surface_flush(in2);
133 int w = cairo_image_surface_get_width(in2);
134 int h = cairo_image_surface_get_height(in2);
135 int bpp1 = cairo_image_surface_get_format(in1) == CAIRO_FORMAT_A8 ? 1 : 4;
136 int bpp2 = cairo_image_surface_get_format(in2) == CAIRO_FORMAT_A8 ? 1 : 4;
138 if (bpp1 == 4 && bpp2 == 4) {
139 ink_cairo_surface_blend_internal<guint32, guint32, guint32>(out, in1, in2,
w, h, blend);
140 }
else if (bpp1 == 4 && bpp2 == 1) {
141 ink_cairo_surface_blend_internal<guint32, guint32, guint8>(out, in1, in2,
w, h, blend);
142 }
else if (bpp1 == 1 && bpp2 == 4) {
143 ink_cairo_surface_blend_internal<guint32, guint8, guint32>(out, in1, in2,
w, h, blend);
145 ink_cairo_surface_blend_internal<guint8, guint8, guint8>(out, in1, in2,
w, h, blend);
148 cairo_surface_mark_dirty(out);
151template <
typename Filter>
154 cairo_surface_flush(in);
161 int w = cairo_image_surface_get_width(in);
162 int h = cairo_image_surface_get_height(in);
163 int bppin = cairo_image_surface_get_format(in) == CAIRO_FORMAT_A8 ? 1 : 4;
164 int bppout = cairo_image_surface_get_format(out) == CAIRO_FORMAT_A8 ? 1 : 4;
166 if (bppin == 4 && bppout == 4) {
167 ink_cairo_surface_filter_internal<guint32, guint32>(out, in,
w, h, filter);
168 }
else if (bppin == 4 && bppout == 1) {
170 ink_cairo_surface_filter_internal<guint8, guint32>(out, in,
w, h, filter);
171 }
else if (bppin == 1 && bppout == 4) {
173 ink_cairo_surface_filter_internal<guint32, guint8>(out, in,
w, h, filter);
175 ink_cairo_surface_filter_internal<guint8, guint8>(out, in,
w, h, filter);
178 cairo_surface_mark_dirty(out);
189template <
typename Synth>
196 int x0 = out_area.x, x1 = out_area.x + out_area.width;
197 int y0 = out_area.y, y1 = out_area.y + out_area.height;
198 int bppout = cairo_image_surface_get_format(out) == CAIRO_FORMAT_A8 ? 1 : 4;
201 ink_cairo_surface_synthesize_internal<guint32>(out, x0, y0, x1, y1, synth);
203 ink_cairo_surface_synthesize_internal<guint8>(out, x0, y0, x1, y1, synth);
206 cairo_surface_mark_dirty(out);
209template <
typename Synth>
212 int w = cairo_image_surface_get_width(out);
213 int h = cairo_image_surface_get_height(out);
215 cairo_rectangle_t area;
227 ,
_w(cairo_image_surface_get_width(
surface))
228 ,
_h(cairo_image_surface_get_height(
surface))
230 ,
_alpha(cairo_surface_get_content(
surface) == CAIRO_CONTENT_ALPHA)
241 return *
reinterpret_cast<guint32*
>(px);
251 return (p & 0xff000000) >> 24;
262 int xi = xf, yi = yf;
263 guint32 xif = round((x - xf) * 255), yif = round((y - yf) * 255);
269 p00 = *pxu; p10 = *(pxu + 1);
270 p01 = *pxl; p11 = *(pxl + 1);
274 for (
unsigned i = 0; i < 4; ++i) {
282 guint32 iu = (255-xif) * c00 + xif * c10;
283 guint32 il = (255-xif) * c01 + xif * c11;
284 comp[i] = (255-yif) * iu + yif * il;
285 comp[i] = (comp[i] + (255*255/2)) / (255*255);
288 guint32 result = comp[0] | (comp[1] << 8) | (comp[2] << 16) | (comp[3] << 24);
295 int xi = xf, yi = yf;
296 guint32 xif = round((x - xf) * 255), yif = round((y - yf) * 255);
300 unsigned char *pxl = pxu +
_stride;
301 p00 = *pxu; p10 = *(pxu + 1);
302 p01 = *pxl; p11 = *(pxl + 1);
307 p00 = (*pxu & 0xff000000) >> 24; p10 = (*(pxu + 1) & 0xff000000) >> 24;
308 p01 = (*pxl & 0xff000000) >> 24; p11 = (*(pxl + 1) & 0xff000000) >> 24;
310 guint32 iu = (255-xif) * p00 + xif * p10;
311 guint32 il = (255-xif) * p01 + xif * p11;
325 if (G_UNLIKELY(x == 0)) {
327 if (G_UNLIKELY(y == 0)) {
334 -2.0 * p00 +2.0 * p10
335 -1.0 * p01 +1.0 * p11;
337 -2.0 * p00 -1.0 * p10
338 +2.0 * p01 +1.0 * p11;
339 }
else if (G_UNLIKELY(y == (
_h - 1))) {
346 -1.0 * p00 +1.0 * p10
347 -2.0 * p01 +2.0 * p11;
349 -2.0 * p00 -1.0 * p10
350 +2.0 * p01 +1.0 * p11;
359 -1.0 * p00 +1.0 * p10
360 -2.0 * p01 +2.0 * p11
361 -1.0 * p02 +1.0 * p12;
363 -2.0 * p00 -1.0 * p10
364 +0.0 * p01 +0.0 * p11
365 +2.0 * p02 +1.0 * p12;
367 }
else if (G_UNLIKELY(x == (
_w - 1))) {
369 if (G_UNLIKELY(y == 0)) {
376 -2.0 * p00 +2.0 * p10
377 -1.0 * p01 +1.0 * p11;
379 -1.0 * p00 -2.0 * p10
380 +1.0 * p01 +2.0 * p11;
381 }
else if (G_UNLIKELY(y == (
_h - 1))) {
388 -1.0 * p00 +1.0 * p10
389 -2.0 * p01 +2.0 * p11;
391 -1.0 * p00 -2.0 * p10
392 +1.0 * p01 +2.0 * p11;
401 -1.0 * p00 +1.0 * p10
402 -2.0 * p01 +2.0 * p11
403 -1.0 * p02 +1.0 * p12;
405 -1.0 * p00 -2.0 * p10
406 +0.0 * p01 +0.0 * p11
407 +1.0 * p02 +2.0 * p12;
411 if (G_UNLIKELY(y == 0)) {
418 -2.0 * p00 +0.0 * p10 +2.0 * p20
419 -1.0 * p01 +0.0 * p11 +1.0 * p21;
421 -1.0 * p00 -2.0 * p10 -1.0 * p20
422 +1.0 * p01 +2.0 * p11 +1.0 * p21;
423 }
else if (G_UNLIKELY(y == (
_h - 1))) {
430 -1.0 * p00 +0.0 * p10 +1.0 * p20
431 -2.0 * p01 +0.0 * p11 +2.0 * p21;
433 -1.0 * p00 -2.0 * p10 -1.0 * p20
434 +1.0 * p01 +2.0 * p11 +1.0 * p21;
444 -1.0 * p00 +0.0 * p10 +1.0 * p20
445 -2.0 * p01 +0.0 * p11 +2.0 * p21
446 -1.0 * p02 +0.0 * p12 +1.0 * p22;
448 -1.0 * p00 -2.0 * p10 -1.0 * p20
449 +0.0 * p01 +0.0 * p11 +0.0 * p21
450 +1.0 * p02 +2.0 * p12 +1.0 * p22;
470 if (v < low)
return low;
471 if (v > high)
return high;
G_GNUC_CONST gint32 pxclamp(gint32 v, gint32 low, gint32 high)
void ink_cairo_surface_synthesize_internal(cairo_surface_t *out, int x0, int y0, int x1, int y1, Synth &synth)
void ink_cairo_surface_filter(cairo_surface_t *in, cairo_surface_t *out, Filter &&filter)
void ink_cairo_surface_blend(cairo_surface_t *in1, cairo_surface_t *in2, cairo_surface_t *out, Blend &&blend)
Blend two surfaces using the supplied functor.
void ink_cairo_surface_synthesize(cairo_surface_t *out, cairo_rectangle_t const &out_area, Synth &&synth)
Synthesize surface pixels based on their position.
static const int POOL_THRESHOLD
void ink_cairo_surface_filter_internal(cairo_surface_t *out, cairo_surface_t *in, int w, int h, Filter &filter)
void ink_cairo_surface_blend_internal(cairo_surface_t *out, cairo_surface_t *in1, cairo_surface_t *in2, int w, int h, Blend &blend)
Cairo integration helpers.
Cairo::RefPtr< Cairo::ImageSurface > surface
struct _cairo_surface cairo_surface_t
auto floor(Geom::Rect const &rect)
void shift(T &a, T &b, T const &c)
void normalize_vector(Fvector &v)
Normalizes a vector.
a type of 3 gdouble components vectors
guint32 alphaAt(int x, int y) const
guint32 alphaAt(double x, double y) const
NR::Fvector surfaceNormalAt(int x, int y, double scale) const
guint32 pixelAt(int x, int y) const
SurfaceSynth(cairo_surface_t *surface)
guint32 pixelAt(double x, double y) const
surface_accessor(cairo_surface_t *surface)
void set(int x, int y, guint32 value)
guint32 get(int x, int y) const