33 , m_imageDevice(paintNode)
35 , m_precisePainterWrapper(painter->device())
36 , m_dab(m_precisePainterWrapper.createPreciseCompositionSourceDevice())
37 , m_tempPainter(new
KisPainter(m_precisePainterWrapper.overlay()))
38 , m_backgroundPainter(new
KisPainter(m_precisePainterWrapper.createPreciseCompositionSourceDevice()))
68 float color_b,
float opaque,
float hardness,
float color_a,
69 float aspect_ratio,
float angle,
float lock_alpha,
float colorize) {
74 return surface->m_owner->drawDabImpl<quint8>(self, x, y, radius, color_r, color_g,
75 color_b, opaque, hardness, color_a,
76 aspect_ratio, angle, lock_alpha, colorize);
79 return surface->m_owner->drawDabImpl<quint16>(self, x, y, radius, color_r, color_g,
80 color_b, opaque, hardness, color_a,
81 aspect_ratio, angle, lock_alpha, colorize);
83#if defined HAVE_OPENEXR
85 return surface->m_owner->drawDabImpl<half>(self, x, y, radius, color_r, color_g,
86 color_b, opaque, hardness, color_a,
87 aspect_ratio, angle, lock_alpha, colorize);
91 return surface->m_owner->drawDabImpl<
float>(self, x, y, radius, color_r, color_g,
92 color_b, opaque, hardness, color_a,
93 aspect_ratio, angle, lock_alpha, colorize);
98 float * color_r,
float * color_g,
float * color_b,
float * color_a) {
102 surface->m_owner->getColorImpl<quint8>(self, x, y, radius, color_r, color_g, color_b, color_a);
105 surface->m_owner->getColorImpl<quint16>(self, x, y, radius, color_r, color_g, color_b, color_a);
107#if defined HAVE_OPENEXR
109 surface->m_owner->getColorImpl<half>(self, x, y, radius, color_r, color_g, color_b, color_a);
113 surface->m_owner->getColorImpl<
float>(self, x, y, radius, color_r, color_g, color_b, color_a);
119template <
typename channelType>
121 float color_b,
float opaque,
float hardness,
float color_a,
122 float aspect_ratio,
float angle,
float lock_alpha,
float colorize) {
125 Q_UNUSED(lock_alpha);
126 const float one_over_radius2 = 1.0f / (radius * radius);
128 const float cs = cos(angle_rad);
129 const float sn = sin(angle_rad);
131 float segment1_slope;
132 float segment2_slope;
135 hardness =
CLAMP (hardness, 0.0f, 1.0f);
136 segment1_slope = -(1.0f / hardness - 1.0f);
137 segment2_slope = -hardness / (1.0f - hardness);
138 aspect_ratio = max(1.0f, aspect_ratio);
140 r_aa_start = radius - 1.0f;
141 r_aa_start = max(r_aa_start, 0.0f);
142 r_aa_start = (r_aa_start * r_aa_start) / aspect_ratio;
144 normal_mode = opaque * (1.0f - colorize);
145 colorize = opaque * colorize;
147 const QPoint pt = QPoint(x - radius - 1, y - radius - 1);
148 const QSize sz = QSize(2 * (radius+1), 2 * (radius+1));
150 const QRect dabRectAligned = QRect(pt, sz);
151 const QPointF center = QPointF(x, y);
179 QPoint pt(it.
x(), it.
y());
181 if(outer.
fadeSq(pt) > 1.0f) {
186 float rr, base_alpha, alpha, dst_alpha, r, g, b, a;
192 rr =
calculate_rr (it.
x(), it.
y(), x, y, aspect_ratio, sn, cs, one_over_radius2);
198 alpha = base_alpha * normal_mode;
201 if (alpha > minValue) {
202 *maskPointer = (quint8)(maskUnitValue);
205 channelType* nativeArray =
reinterpret_cast<channelType*
>(it.
rawData());
207 b = nativeArray[0]/unitValue;
208 g = nativeArray[1]/unitValue;
209 r = nativeArray[2]/unitValue;
210 dst_alpha = nativeArray[3]/unitValue;
212 if (unitValue == 1.0f) {
216 a = alpha * (color_a - dst_alpha) + dst_alpha;
219 alpha = 1 - (opaque*base_alpha);
220 a = dst_alpha * alpha ;
223 float src_term = (alpha * color_a) / a;
224 float dst_term = 1.0f - src_term;
225 r = color_r * src_term + r * dst_term;
226 g = color_g * src_term + g * dst_term;
227 b = color_b * src_term + b * dst_term;
230 if (colorize > 0.0f && base_alpha > 0.0f) {
232 alpha = base_alpha * colorize;
233 a = alpha + dst_alpha - alpha * dst_alpha;
237 float pixel_h, pixel_s, pixel_l, out_h, out_s, out_l;
238 float out_r = r, out_g = g, out_b = b;
240 float src_term = alpha / a;
241 float dst_term = 1.0f - src_term;
243 RGBToHSL(color_r, color_g, color_b, &pixel_h, &pixel_s, &pixel_l);
244 RGBToHSL(out_r, out_g, out_b, &out_h, &out_s, &out_l);
249 HSLToRGB(out_h, out_s, out_l, &out_r, &out_g, &out_b);
251 r = (float)out_r * src_term + r * dst_term;
252 g = (float)out_g * src_term + g * dst_term;
253 b = (float)out_b * src_term + b * dst_term;
258 if (unitValue == 1.0f) {
270 m_tempPainter->bitBltWithFixedSelection(dabRectAligned.x(), dabRectAligned.y(),
m_dab,
m_maskDevice, dabRectAligned.x(), dabRectAligned.y(), dabRectAligned.x(), dabRectAligned.y(), dabRectAligned.width(), dabRectAligned.height());
278template <
typename channelType>
280 float * color_r,
float * color_g,
float * color_b,
float * color_a) {
290 const QPoint pt = QPoint(x - radius, y - radius);
291 const QSize sz = QSize(2 * radius, 2 * radius);
294 const QRect dabRectAligned = QRect(pt, sz);
295 const QPointF center = QPointF(x, y);
298 const float one_over_radius2 = 1.0f / (radius * radius);
299 quint32 sum_weight = 0.0f;
321 quint32 size = dabRectAligned.width() * dabRectAligned.height();
326 qint16* weights =
new qint16[size];
327 quint32 num_colors = 0;
333 QPointF pt(it.
x(), it.
y());
336 if(outer.
fadeSq(pt) <= 1.0) {
338 float yy = (it.
y() + 0.5f - y);
339 float xx = (it.
x() + 0.5f - x);
341 rr = qMax((yy * yy + xx * xx) * one_over_radius2, 0.0f);
344 weights[num_colors] = qRound((1.0f - rr) * 255);
345 sum_weight += weights[num_colors];
352 if (sum_weight > 0.0f) {
354 channelType* nativeArray =
reinterpret_cast<channelType*
>(color.
data());
356 if (unitValue == 1.0f) {
357 *color_r = nativeArray[0];
358 *color_g = nativeArray[1];
359 *color_b = nativeArray[2];
360 *color_a = nativeArray[3];
362 b = nativeArray[0]/maxValue;
363 g = nativeArray[1]/maxValue;
364 r = nativeArray[2]/maxValue;
365 a = nativeArray[3]/maxValue;
366 *color_r =
CLAMP(r, 0.0f, 1.0f);
367 *color_g =
CLAMP(g, 0.0f, 1.0f);
368 *color_b =
CLAMP(b, 0.0f, 1.0f);
369 *color_a =
CLAMP(a, 0.0f, 1.0f);
386 float xp,
float yp,
float aspect_ratio,
float radius) {
388 qreal cs = cos(angle/360*2*
M_PI);
389 qreal sn = sin(angle/360*2*
M_PI);
393 qreal dyr = (dy*cs-dx*sn)*aspect_ratio;
394 qreal dxr = (dy*sn+dx*cs);
395 qreal dd = (dyr*dyr + dxr*dxr) / (radius*radius);
400 else if (dd < hardness)
401 opa = dd + 1-(dd/hardness);
403 opa = hardness/(1-hardness)*(1-dd);
405 qreal pixel_opacity = opa * opaque;
406 return pixel_opacity;
416 float one_over_radius2) {
418 const float yy = (yp + 0.5f - y);
419 const float xx = (xp + 0.5f - x);
420 const float yyr=(yy*cs-xx*sn)*aspect_ratio;
421 const float xxr=yy*sn+xx*cs;
422 const float rr = (yyr*yyr + xxr*xxr) * one_over_radius2;
430 const float yyr=(y*cs-x*sn)*aspect_ratio;
431 const float xxr=y*sn+x*cs;
432 const float r = (yyr*yyr + xxr*xxr);
439 return (px - vx) * (-vy) - (vx) * (py - vy);
445 const float l2 = lx*lx + ly*ly;
446 const float ltp_dot = px*lx + py*ly;
447 const float t = ltp_dot / l2;
463 float aspect_ratio,
float sn,
float cs,
float one_over_radius2,
468 float pixel_right = x - (float)xp;
469 float pixel_bottom = y - (float)yp;
470 float pixel_center_x = pixel_right - 0.5f;
471 float pixel_center_y = pixel_bottom - 0.5f;
472 float pixel_left = pixel_right - 1.0f;
473 float pixel_top = pixel_bottom - 1.0f;
475 float nearest_x, nearest_y;
476 float farthest_x, farthest_y;
477 float r_near, r_far, rr_near, rr_far;
478 float center_sign, rad_area_1, visibilityNear, delta, delta2;
481 if( pixel_left<0 && pixel_right>0 &&
482 pixel_top<0 && pixel_bottom>0 )
486 r_near = rr_near = 0;
491 nearest_x =
CLAMP( nearest_x, pixel_left, pixel_right );
492 nearest_y =
CLAMP( nearest_y, pixel_top, pixel_bottom );
499 rr_near = r_near * one_over_radius2;
513 rad_area_1 = sqrtf( 1.0f /
M_PI );
516 if( center_sign < 0 )
518 farthest_x = nearest_x - sn*rad_area_1;
519 farthest_y = nearest_y + cs*rad_area_1;
524 farthest_x = nearest_x + sn*rad_area_1;
525 farthest_y = nearest_y - cs*rad_area_1;
529 rr_far = r_far * one_over_radius2;
532 if( r_far < r_aa_start )
533 return (rr_far+rr_near) * 0.5f;
536 visibilityNear = 1.0f - rr_near;
537 delta = rr_far - rr_near;
538 delta2 = 1.0f + delta;
539 visibilityNear /= delta2;
541 return 1.0f - visibilityNear;
549 else if (rr <= hardness)
550 return 1.0f + rr * slope1;
552 return rr * slope2 - slope2;
void RGBToHSL(float r, float g, float b, float *h, float *s, float *l)
void HSLToRGB(float h, float sl, float l, float *r, float *g, float *b)
const QString COMPOSITE_COPY
const QString COMPOSITE_ERASE
static void closest_point_to_line(float lx, float ly, float px, float py, float *ox, float *oy)
void destroy_internal_surface_callback(MyPaintSurface *surface)
static float sign_point_in_line(float px, float py, float vx, float vy)
static float calculate_r_sample(float x, float y, float aspect_ratio, float sn, float cs)
qreal fadeSq(const QPointF &pt) const
void setRect(const QRect &rc)
void lazyGrowBufferWithoutInitialization()
KisPaintDeviceSP m_imageDevice
float calculate_alpha_for_rr(float rr, float hardness, float slope1, float slope2)
float calculate_rr_antialiased(int xp, int yp, float x, float y, float aspect_ratio, float sn, float cs, float one_over_radius2, float r_aa_start)
qreal calculateOpacity(float angle, float hardness, float opaque, float x, float y, float xp, float yp, float aspect_ratio, float radius)
MyPaintSurface * surface()
void getColorImpl(MyPaintSurface *self, float x, float y, float radius, float *color_r, float *color_g, float *color_b, float *color_a)
static void get_color(MyPaintSurface *self, float x, float y, float radius, float *color_r, float *color_g, float *color_b, float *color_a)
KisOverlayPaintDeviceWrapper m_precisePainterWrapper
KisFixedPaintDeviceSP m_maskDevice
KisFixedPaintDeviceSP m_blendDevice
QScopedPointer< KisPainter > m_tempPainter
QScopedPointer< KisPainter > m_backgroundPainter
static int draw_dab(MyPaintSurface *self, float x, float y, float radius, float color_r, float color_g, float color_b, float opaque, float hardness, float color_a, float aspect_ratio, float angle, float lock_alpha, float colorize)
KisMyPaintSurface(KisPainter *painter, KisPaintDeviceSP paintNode=nullptr, KisImageSP image=nullptr)
float calculate_rr(int xp, int yp, float x, float y, float aspect_ratio, float sn, float cs, float one_over_radius2)
MyPaintSurfaceInternal * m_surface
int drawDabImpl(MyPaintSurface *self, float x, float y, float radius, float color_r, float color_g, float color_b, float opaque, float hardness, float color_a, float aspect_ratio, float angle, float lock_alpha, float colorize)
void writeRects(const QVector< QRect > &rects, int index=0)
void readRect(const QRect &rc)
KisPaintDeviceSP overlay(int index=0) const
void readRects(const QVector< QRect > &rects)
const KoColorSpace * overlayColorSpace() const
const KoColorSpace * colorSpace() const
void readBytes(quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h) const
void addDirtyRects(const QVector< QRect > &rects)
ALWAYS_INLINE quint8 * rawData()
ALWAYS_INLINE int x() const
ALWAYS_INLINE int y() const
@ UINT8
use this for an unsigned integer 8bits channel
@ UINT16
use this for an integer 16bits channel
@ FLOAT16
use this for a float 16bits channel
static _Tdst scaleToA(_T a)
QList< KoChannelInfo * > channels
KoMixColorsOp * mixColorsOp
static KoColor createTransparent(const KoColorSpace *cs)
virtual void mixColors(const quint8 *const *colors, const qint16 *weights, int nColors, quint8 *dst, int weightSum=255) const =0
T kisDegreesToRadians(T degrees)
KisSharedPtr< KisFixedPaintDevice > KisFixedPaintDeviceSP
KisMyPaintSurface * m_owner
KoChannelInfo::enumChannelValueType bitDepth
static KoColorSpaceRegistry * instance()
const KoColorSpace * alpha8()