269
295
// filter all hidden shapes from the list
296
// also filter shapes with a parent which has filter effects applied
270
297
QList<KoShape*> sortedShapes;
271
foreach(KoShape * shape, unsortedShapes) {
272
if (shape->isVisible(true))
298
foreach (KoShape *shape, unsortedShapes) {
299
if (!shape->isVisible(true))
301
bool addShapeToList = true;
302
// check if one of the shapes ancestors have filter effects
303
KoShapeContainer *parent = shape->parent();
305
// parent must be part of the shape manager to be taken into account
306
if (!d->shapes.contains(parent))
308
if (parent->filterEffectStack() && !parent->filterEffectStack()->isEmpty()) {
309
addShapeToList = false;
312
parent = parent->parent();
314
if (addShapeToList) {
273
315
sortedShapes.append(shape);
317
sortedShapes.append(parent);
276
321
qSort(sortedShapes.begin(), sortedShapes.end(), KoShape::compareShapeZIndex);
278
foreach(KoShape * shape, sortedShapes) {
323
foreach (KoShape *shape, sortedShapes) {
279
324
if (shape->parent() != 0 && shape->parent()->childClipped(shape))
282
328
d->strategy->paint(shape, painter, converter, forPrint);
285
332
#ifdef KOFFICE_RTREE_DEBUG
297
344
d->selection->paint(painter, converter);
300
void KoShapeManager::paintShape(KoShape * shape, QPainter &painter, const KoViewConverter &converter, bool forPrint)
347
void KoShapeManager::paintShape(KoShape *shape, QPainter &painter, const KoViewConverter &converter, bool forPrint)
350
qreal transparency = shape->transparency(true);
351
if (transparency > 0.0) {
352
painter.setOpacity(1.0-transparency);
302
355
if (shape->shadow()) {
304
357
shape->shadow()->paint(shape, painter, converter);
305
358
painter.restore();
307
if(!shape->filterEffectStack() || shape->filterEffectStack()->filterEffects().isEmpty()) {
360
if (!shape->filterEffectStack() || shape->filterEffectStack()->isEmpty()) {
309
362
shape->paint(painter, converter);
310
363
painter.restore();
311
364
if (shape->border()) {
313
shape->border()->paintBorder(shape, painter, converter);
366
shape->border()->paint(shape, painter, converter);
314
367
painter.restore();
317
// There are filter effets, then we need to prerender the shape on an image, to filter it
370
// There are filter effects, then we need to prerender the shape on an image, to filter it
318
371
QRectF shapeBound(QPointF(), shape->size());
319
372
// First step, compute the rectangle used for the image
320
373
QRectF clipRegion = shape->filterEffectStack()->clipRectForBoundingRect(shapeBound);
323
376
// determine the offset of the clipping rect from the shapes origin
324
377
QPointF clippingOffset = zoomedClipRegion.topLeft();
326
// Init the buffer image
379
// Initialize the buffer image
327
380
QImage sourceGraphic(zoomedClipRegion.size().toSize(), QImage::Format_ARGB32_Premultiplied);
328
381
sourceGraphic.fill(qRgba(0,0,0,0));
330
// Init the buffer painter
331
QPainter imagePainter(&sourceGraphic);
332
imagePainter.translate(-1.0f*clippingOffset);
333
imagePainter.setPen(Qt::NoPen);
334
imagePainter.setBrush(Qt::NoBrush);
335
imagePainter.setRenderHint(QPainter::Antialiasing, painter.testRenderHint(QPainter::Antialiasing));
337
// Paint the shape on the image
339
shape->paint(imagePainter, converter);
340
imagePainter.restore();
341
if (shape->border()) {
343
shape->border()->paintBorder(shape, imagePainter, converter);
344
imagePainter.restore();
348
QImage sourceAlpha = sourceGraphic;
349
sourceAlpha.fill(qRgba(0,0,0,255));
350
sourceAlpha.setAlphaChannel(sourceGraphic.alphaChannel());
352
383
QHash<QString, QImage> imageBuffers;
385
QSet<QString> requiredStdInputs = shape->filterEffectStack()->requiredStandarsInputs();
387
if (requiredStdInputs.contains("SourceGraphic") || requiredStdInputs.contains("SourceAlpha")) {
388
// Init the buffer painter
389
QPainter imagePainter(&sourceGraphic);
390
imagePainter.translate(-1.0f*clippingOffset);
391
imagePainter.setPen(Qt::NoPen);
392
imagePainter.setBrush(Qt::NoBrush);
393
imagePainter.setRenderHint(QPainter::Antialiasing, painter.testRenderHint(QPainter::Antialiasing));
395
// Paint the shape on the image
396
KoShapeGroup *group = dynamic_cast<KoShapeGroup*>(shape);
398
// the childrens matrix contains the groups matrix as well
399
// so we have to compensate for that before painting the children
400
imagePainter.setMatrix(group->absoluteTransformation(&converter).inverted(), true);
401
d->paintGroup(group, imagePainter, converter, forPrint);
404
shape->paint(imagePainter, converter);
405
imagePainter.restore();
406
if (shape->border()) {
408
shape->border()->paint(shape, imagePainter, converter);
409
imagePainter.restore();
414
if (requiredStdInputs.contains("SourceAlpha")) {
415
QImage sourceAlpha = sourceGraphic;
416
sourceAlpha.fill(qRgba(0,0,0,255));
417
sourceAlpha.setAlphaChannel(sourceGraphic.alphaChannel());
418
imageBuffers.insert("SourceAlpha", sourceAlpha);
420
if (requiredStdInputs.contains("FillPaint")) {
421
QImage fillPaint = sourceGraphic;
422
if (shape->background()) {
423
QPainter fillPainter(&fillPaint);
424
QPainterPath fillPath;
425
fillPath.addRect(fillPaint.rect().adjusted(-1,-1,1,1));
426
shape->background()->paint(fillPainter, fillPath);
428
fillPaint.fill(qRgba(0,0,0,0));
430
imageBuffers.insert("FillPaint", fillPaint);
353
433
imageBuffers.insert("SourceGraphic", sourceGraphic);
354
434
imageBuffers.insert(QString(), sourceGraphic);
355
imageBuffers.insert("SourceAlpha", sourceAlpha);
357
QMatrix coordTransform = QMatrix().scale(shapeBound.width(), shapeBound.height());
358
436
KoFilterEffectRenderContext renderContext(converter);
359
renderContext.setCoordinateTransformation(coordTransform);
437
renderContext.setShapeBoundingBox(shapeBound);
361
440
QList<KoFilterEffect*> filterEffects = shape->filterEffectStack()->filterEffects();
363
foreach(KoFilterEffect* filterEffect, filterEffects) {
364
QRectF filterRegion = filterEffect->filterRectForBoundingRect(clipRegion);
442
foreach (KoFilterEffect *filterEffect, filterEffects) {
443
QRectF filterRegion = filterEffect->filterRectForBoundingRect(shapeBound);
365
444
filterRegion = converter.documentToView(filterRegion);
366
QPointF filterOffset = filterRegion.topLeft()-2*clippingOffset;
367
QRect subRegion = filterRegion.translated(filterOffset).toRect();
445
QRect subRegion = filterRegion.translated(-clippingOffset).toRect();
369
446
// set current filter region
370
renderContext.setFilterRegion(subRegion);
372
if (filterEffect->maximalInputCount() == 1) {
447
renderContext.setFilterRegion(subRegion & sourceGraphic.rect());
449
if (filterEffect->maximalInputCount() <= 1) {
373
450
QList<QString> inputs = filterEffect->inputs();
374
451
QString input = inputs.count() ? inputs.first() : QString();
375
// get input image from image buffers
376
QImage inputImage = imageBuffers.value(input);
377
// apply the filter effect
378
QImage result = filterEffect->processImage(inputImage, renderContext);
379
// store result of effect
380
imageBuffers.insert(filterEffect->output(), result);
452
// get input image from image buffers and apply the filter effect
453
QImage image = imageBuffers.value(input);
454
if (!image.isNull()) {
455
result = filterEffect->processImage(imageBuffers.value(input), renderContext);
382
458
QList<QImage> inputImages;
383
459
foreach(const QString &input, filterEffect->inputs()) {
384
inputImages.append(imageBuffers.value(input));
460
QImage image = imageBuffers.value(input);
462
inputImages.append(imageBuffers.value(input));
386
464
// apply the filter effect
387
QImage result = filterEffect->processImages(inputImages, renderContext);
388
// store result of effect
389
imageBuffers.insert(filterEffect->output(), result);
465
if (filterEffect->inputs().count() == inputImages.count())
466
result = filterEffect->processImages(inputImages, renderContext);
468
// store result of effect
469
imageBuffers.insert(filterEffect->output(), result);
393
KoFilterEffect * lastEffect = filterEffects.last();
472
KoFilterEffect *lastEffect = filterEffects.last();
395
474
// Paint the result