20#include <QPainterPath>
29 : offset(2, 2), color(Qt::black), blur(8), visible(true), refCount(0) {
50 void blurShadow(QImage &image,
int radius,
const QColor& shadowColor);
53void KoShapeShadow::Private::paintGroupShadow(
KoShapeGroup *group, QPainter &painter)
56 Q_FOREACH (
KoShape *child, shapes) {
63 paintShadow(child, painter);
68void KoShapeShadow::Private::paintShadow(
KoShape *shape, QPainter &painter)
71 if (!path.isEmpty()) {
73 painter.setBrush(QBrush(color));
80 painter.drawPath(path);
85 shape->
stroke()->paint(shape, painter);
92void KoShapeShadow::Private::blurShadow(QImage &image,
int radius,
const QColor& shadowColor)
94 static const int BlurSumShift = 15;
104 int channels[4] = { 3, 0, 1, 3 };
105 int dmax = radius >> 1;
106 int dmin = dmax - 1 + (radius & 1);
111 for (
int k = 0; k < 2; ++k) {
113 unsigned char* pixels = image.bits();
114 int stride = (k == 0) ? 4 : image.bytesPerLine();
115 int delta = (k == 0) ? image.bytesPerLine() : 4;
116 int jfinal = (k == 0) ? image.height() : image.width();
117 int dim = (k == 0) ? image.width() : image.height();
119 for (
int j = 0; j < jfinal; ++j, pixels += delta) {
127 for (
int step = 0; step < 3; ++step) {
128 int side1 = (step == 0) ? dmin : dmax;
129 int side2 = (step == 1) ? dmin : dmax;
130 int pixelCount = side1 + 1 + side2;
131 int invCount = ((1 << BlurSumShift) + pixelCount - 1) / pixelCount;
133 int alpha1 = pixels[channels[step]];
134 int alpha2 = pixels[(dim - 1) * stride + channels[step]];
135 unsigned char* ptr = pixels + channels[step + 1];
136 unsigned char* prev = pixels + stride + channels[step];
137 unsigned char*
next = pixels + ofs * stride + channels[step];
140 int sum = side1 * alpha1 + alpha1;
141 int limit = (dim < side2 + 1) ? dim : side2 + 1;
142 for (i = 1; i < limit; ++i, prev += stride)
145 sum += (side2 - limit + 1) * alpha2;
147 limit = (side1 < dim) ? side1 : dim;
148 for (i = 0; i < limit; ptr += stride,
next += stride, ++i, ++ofs) {
149 *ptr = (sum * invCount) >> BlurSumShift;
150 sum += ((ofs < dim) ? *next : alpha2) - alpha1;
152 prev = pixels + channels[step];
153 for (; ofs < dim; ptr += stride, prev += stride,
next += stride, ++i, ++ofs) {
154 *ptr = (sum * invCount) >> BlurSumShift;
155 sum += (*next) - (*prev);
157 for (; i < dim; ptr += stride, prev += stride, ++i) {
158 *ptr = (sum * invCount) >> BlurSumShift;
159 sum += alpha2 - (*prev);
167 p.setCompositionMode(QPainter::CompositionMode_SourceIn);
168 p.fillRect(image.rect(), shadowColor);
209 QTransform documentToView = painter.transform();
213 QRectF zoomedClipRegion = documentToView.mapRect(shadowRect);
216 QImage sourceGraphic(zoomedClipRegion.size().toSize(), QImage::Format_ARGB32_Premultiplied);
217 sourceGraphic.fill(qRgba(0,0,0,0));
219 QPainter imagePainter(&sourceGraphic);
220 imagePainter.setPen(Qt::NoPen);
221 imagePainter.setBrush(Qt::NoBrush);
222 imagePainter.setRenderHint(QPainter::Antialiasing, painter.testRenderHint(QPainter::Antialiasing));
224 imagePainter.translate(-1.0f*documentToView.map(shadowRect.topLeft()));
227 imagePainter.translate(documentToView.map(
offset()));
231 d->paintGroupShadow(group, imagePainter);
236 d->paintShadow(shape, imagePainter);
241 d->blurShadow(sourceGraphic, qRound(documentToView.m11() *
d->blur),
d->color);
248 painter.drawImage(zoomedClipRegion.topLeft(), sourceGraphic);
275 d->blur = qAbs(
blur);
305 insets.left = (
d->offset.x() < 0.0) ? qAbs(
d->offset.x()) : 0.0;
306 insets.top = (
d->offset.y() < 0.0) ? qAbs(
d->offset.y()) : 0.0;
307 insets.right = (
d->offset.x() > 0.0) ?
d->offset.x() : 0.0;
308 insets.bottom = (
d->offset.y() > 0.0) ?
d->offset.y() : 0.0;
318 return d->refCount.ref();
323 return d->refCount.deref();
void expand(ExpansionStrategy &expansionStrategy, KoUpdater *progressUpdater)
The position of a path point within a path shape.
Qt::FillRule fillRule() const
Returns the fill rule for the path object.
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule to be used for painting the background.
QList< KoShape * > shapes() const
void blurShadow(QImage &image, int radius, const QColor &shadowColor)
bool isVisible() const
Returns if shadow is visible.
KoShapeShadow & operator=(const KoShapeShadow &rhs)
void setOffset(const QPointF &offset)
void setColor(const QColor &color)
void paintShadow(KoShape *shape, QPainter &painter)
int useCount() const
Return the usage count.
void paint(KoShape *shape, QPainter &painter)
void insets(KoInsets &insets) const
Fills the insets object with the space the shadow takes around a shape.
void paintGroupShadow(KoShapeGroup *group, QPainter &painter)
void setVisible(bool visible)
Sets the shadow visibility.
virtual KoShapeStrokeModelSP stroke() const
virtual QRectF boundingRect() const
Get the bounding box of the shape.
QTransform absoluteTransformation() const
virtual QPainterPath shadowOutline() const
bool isVisible(bool recursive=true) const
QAction * next(const QObject *recvr, const char *slot, QObject *parent)