void KisSelectionTest::testSelectionActions()
{
    KisPixelSelectionSP pixelSelection = new KisPixelSelection();

    KisSelectionSP selection = new KisSelection();
    QVERIFY(selection->hasPixelSelection() == false);
    QVERIFY(selection->hasShapeSelection() == false);
    selection->setPixelSelection(pixelSelection);

    pixelSelection->select(QRect(0, 0, 20, 20));

    KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection());
    tmpSel->select(QRect(10, 0, 20, 20));

    pixelSelection->addSelection(tmpSel);
    QCOMPARE(pixelSelection->selectedExactRect(), QRect(0, 0, 30, 20));
    selection->updateProjection();
    QCOMPARE(selection->selectedExactRect(), QRect(0, 0, 30, 20));

    pixelSelection->clear();
    pixelSelection->select(QRect(0, 0, 20, 20));

    pixelSelection->subtractSelection(tmpSel);
    selection->updateProjection();
    QCOMPARE(selection->selectedExactRect(), QRect(0, 0, 10, 20));

    pixelSelection->clear();
    selection->updateProjection();
    pixelSelection->select(QRect(0, 0, 20, 20));

    pixelSelection->intersectSelection(tmpSel);
    selection->updateProjection();
    QCOMPARE(selection->selectedExactRect(), QRect(10, 0, 10, 20));
}
void KisSelectionToolHelper::addSelectionShape(KoShape* shape)
{
    KisView2* view = m_canvas->view();
    /**
     * Mark a shape that it belongs to a shape selection
     */
    if(!shape->userData()) {
        shape->setUserData(new KisShapeSelectionMarker);
    }

    KisUndoAdapter *undoAdapter = view->image()->undoAdapter();
    undoAdapter->beginMacro(m_name);

    if (!view->selection()) {
        undoAdapter->addCommand(new KisSetEmptyGlobalSelectionCommand(m_image));
    }

    KisPixelSelectionSP pixelSelection = view->selection()->pixelSelection();
    KisSelectionTransaction transaction(m_name, pixelSelection);
    pixelSelection->clear();
    transaction.commit(undoAdapter);

    undoAdapter->addCommand(m_canvas->shapeController()->addShape(shape));
    undoAdapter->endMacro();
}
示例#3
0
QUndoCommand* KisSelectionToolHelper::selectPixelSelection(KisPixelSelectionSP selection, selectionAction action)
{
    bool hasSelection = m_layer->selection();

    QUndoCommand* selectionCmd = new QUndoCommand(m_name);

    if (!hasSelection)
        new KisSetGlobalSelectionCommand(m_image, selectionCmd);

    new KisSelectionTransaction(m_name, m_image, m_layer->selection(), selectionCmd);

    KisPixelSelectionSP getOrCreatePixelSelection = m_layer->selection()->getOrCreatePixelSelection();

    if (! hasSelection || action == SELECTION_REPLACE) {
        getOrCreatePixelSelection->clear();
        if (action == SELECTION_SUBTRACT)
            getOrCreatePixelSelection->invert();
    }
    getOrCreatePixelSelection->applySelection(selection, action);

    if (hasSelection && action != SELECTION_REPLACE && action != SELECTION_INTERSECT) {
        QRect rc = selection->selectedRect();
        getOrCreatePixelSelection->setDirty(rc);
        m_layer->selection()->updateProjection(rc);
        m_canvas->view()->selectionManager()->selectionChanged();
    } else {
        getOrCreatePixelSelection->setDirty(m_image->bounds());
        m_layer->selection()->updateProjection(m_image->bounds());
        m_canvas->view()->selectionManager()->selectionChanged();
    }
    return selectionCmd;
}
void KisSelectionToolHelper::addSelectionShapes(QList< KoShape* > shapes)
{
    KisViewManager* view = m_canvas->viewManager();

    if (view->image()->wrapAroundModePermitted()) {
        view->showFloatingMessage(
            i18n("Shape selection does not fully "
                 "support wraparound mode. Please "
                 "use pixel selection instead"),
                 KisIconUtils::loadIcon("selection-info"));
    }

    KisProcessingApplicator applicator(view->image(),
                                       0 /* we need no automatic updates */,
                                       KisProcessingApplicator::NONE,
                                       KisImageSignalVector() << ModifiedSignal,
                                       m_name);

    applicator.applyCommand(new LazyInitGlobalSelection(view));

    struct ClearPixelSelection : public KisTransactionBasedCommand {
        ClearPixelSelection(KisViewManager *view) : m_view(view) {}
        KisViewManager *m_view;

        KUndo2Command* paint() {

            KisPixelSelectionSP pixelSelection = m_view->selection()->pixelSelection();
            KIS_ASSERT_RECOVER(pixelSelection) { return 0; }

            KisSelectionTransaction transaction(pixelSelection);
            pixelSelection->clear();
            return transaction.endAndTake();
        }
    };

    applicator.applyCommand(new ClearPixelSelection(view));

    struct AddSelectionShape : public KisTransactionBasedCommand {
        AddSelectionShape(KisViewManager *view, KoShape* shape) : m_view(view),
                                                            m_shape(shape) {}
        KisViewManager *m_view;
        KoShape* m_shape;

        KUndo2Command* paint() {
            /**
             * Mark a shape that it belongs to a shape selection
             */
            if(!m_shape->userData()) {
                m_shape->setUserData(new KisShapeSelectionMarker);
            }

            return m_view->canvasBase()->shapeController()->addShape(m_shape);
        }
    };

    foreach(KoShape* shape, shapes) {
        applicator.applyCommand(
            new KisGuiContextCommand(new AddSelectionShape(view, shape), view));
    }
示例#5
0
void KisLsBevelEmbossFilter::applyBevelEmboss(KisPaintDeviceSP srcDevice,
                                              KisMultipleProjection *dst,
                                              const QRect &applyRect,
                                              const psd_layer_effects_bevel_emboss *config,
                                              KisLayerStyleFilterEnvironment *env) const
{
    if (applyRect.isEmpty()) return;

    BevelEmbossRectCalculator d(applyRect, config);

    KisSelectionSP baseSelection = KisLsUtils::selectionFromAlphaChannel(srcDevice, d.initialFetchRect);
    KisPixelSelectionSP selection = baseSelection->pixelSelection();

    //selection->convertToQImage(0, QRect(0,0,300,300)).save("0_selection_initial.png");

    const int size = config->size();

    int limitingGrowSize = 0;
    KisPixelSelectionSP bumpmapSelection = new KisPixelSelection(new KisSelectionEmptyBounds(0));

    switch (config->style()) {
    case psd_bevel_outer_bevel:
        paintBevelSelection(selection, bumpmapSelection, d.applyBevelRect, size, size, false);
        limitingGrowSize = size;
        break;
    case psd_bevel_inner_bevel:
        paintBevelSelection(selection, bumpmapSelection, d.applyBevelRect, size, 0, false);
        limitingGrowSize = 0;
        break;
    case psd_bevel_emboss: {
        const int initialSize = std::ceil(qreal(size) / 2.0);
        paintBevelSelection(selection, bumpmapSelection, d.applyBevelRect, size, initialSize, false);
        limitingGrowSize = initialSize;
        break;
    }
    case psd_bevel_pillow_emboss: {
        const int halfSizeF = std::floor(qreal(size) / 2.0);
        const int halfSizeC = std::ceil(qreal(size) / 2.0);
        // TODO: probably not correct!
        paintBevelSelection(selection, bumpmapSelection, d.applyBevelRect, halfSizeC, halfSizeC, false);
        paintBevelSelection(selection, bumpmapSelection, d.applyBevelRect, halfSizeF, 0, true);
        limitingGrowSize = halfSizeC;
        break;
    }
    case psd_bevel_stroke_emboss:
        warnKrita << "WARNING: Stroke Emboss style is not implemented yet!";
        return;
    }

    KisPixelSelectionSP limitingSelection = new KisPixelSelection(*selection);
    {
        QRect changeRectUnused =
            KisLsUtils::growSelectionUniform(limitingSelection,
                                             limitingGrowSize,
                                             d.applyBevelRect);
        Q_UNUSED(changeRectUnused);
    }

    //bumpmapSelection->convertToQImage(0, QRect(0,0,300,300)).save("1_selection_xconv.png");

    if (config->textureEnabled()) {
        KisPixelSelectionSP textureSelection = new KisPixelSelection(new KisSelectionEmptyBounds(0));

        KisLsUtils::fillPattern(textureSelection, d.applyTextureRect, env,
                                config->textureScale(),
                                config->texturePattern(),
                                config->textureHorizontalPhase(),
                                config->textureVerticalPhase(),
                                config->textureAlignWithLayer());

        int contrastadj = 0;

        {
            using namespace std;

            int tex_depth = config->textureDepth();

            if (tex_depth >= 0.0) {
                if (tex_depth <= 100.0) {
                    contrastadj = int(qRound((1-(tex_depth/100.0)) * -127));
                } else {
                    contrastadj = int(qRound(((tex_depth-100.0)/900.0) * 127));
                }
            } else {
                textureSelection->invert();
                if (tex_depth >= -100.0) {
                    contrastadj = int(qRound((1-(abs(tex_depth)/100.0)) * -127));
                } else {
                    contrastadj = int(qRound(((abs(tex_depth)-100.0)/900.0) * 127));
                }
            }
        }

        qreal contrast = qBound(-1.0, qreal(contrastadj) / 127.0, 1.0);
        mapPixelValues(textureSelection, ContrastOp(contrast), d.applyTextureRect);

        {
            KisPainter gc(bumpmapSelection);
            gc.setCompositeOp(COMPOSITE_MULT);
            gc.bitBlt(d.applyTextureRect.topLeft(), textureSelection, d.applyTextureRect);
            gc.end();
        }
    }

    //bumpmapSelection->convertToQImage(0, QRect(0,0,300,300)).save("15_selection_texture.png");

    if (config->contourEnabled()) {
        if (config->range() != KisLsUtils::FULL_PERCENT_RANGE) {
            KisLsUtils::adjustRange(bumpmapSelection, d.applyContourRect, config->range());
        }

        KisLsUtils::applyContourCorrection(bumpmapSelection,
                                           d.applyContourRect,
                                           config->contourLookupTable(),
                                           config->antiAliased(),
                                           true);
    }

    bumpmap_vals_t bmvals;

    bmvals.azimuth = config->angle();
    bmvals.elevation = config->altitude();
    bmvals.depth = config->depth();
    bmvals.ambient = 0;
    bmvals.compensate = true;
    bmvals.invert = config->direction() == psd_direction_down;
    bmvals.type = LINEAR;

    bumpmap(bumpmapSelection, d.applyBumpmapRect, bmvals);

    //bumpmapSelection->convertToQImage(0, QRect(0,0,300,300)).save("3_selection_bumpmap.png");

    { // TODO: optimize!

        KisLsUtils::applyContourCorrection(bumpmapSelection,
                                           d.applyGlossContourRect,
                                           config->glossContourLookupTable(),
                                           config->glossAntiAliased(),
                                           true);

    }

    if (config->soften()) {
        KisLsUtils::applyGaussian(bumpmapSelection, d.applyGaussianRect, config->soften());
    }


    if (config->textureEnabled() && config->textureInvert()) {
        bumpmapSelection->invert();
    }

    selection->clear();
    mapPixelValues(bumpmapSelection, selection,
                   ShadowsFetchOp(), d.shadowHighlightsFinalRect);
    selection->applySelection(limitingSelection, SELECTION_INTERSECT);

    //dstDevice->convertToQImage(0, QRect(0,0,300,300)).save("4_dst_before_apply.png");
    //selection->convertToQImage(0, QRect(0,0,300,300)).save("4_shadows_sel.png");

    {
        KisPaintDeviceSP dstDevice = dst->getProjection("00_bevel_shadow", config->shadowBlendMode(), srcDevice);

        const KoColor fillColor(config->shadowColor(), dstDevice->colorSpace());
        const QRect &fillRect = d.shadowHighlightsFinalRect;
        KisPaintDeviceSP fillDevice = new KisPaintDevice(dstDevice->colorSpace());
        fillDevice->setDefaultPixel(fillColor);
        KisPainter gc(dstDevice);

        gc.setSelection(baseSelection);
        gc.setCompositeOp(COMPOSITE_OVER);
        env->setupFinalPainter(&gc, config->shadowOpacity(), QBitArray());
        gc.bitBlt(fillRect.topLeft(), fillDevice, fillRect);
        gc.end();
    }

    selection->clear();
    mapPixelValues(bumpmapSelection, selection,
                   HighlightsFetchOp(), d.shadowHighlightsFinalRect);
    selection->applySelection(limitingSelection, SELECTION_INTERSECT);

    //selection->convertToQImage(0, QRect(0,0,300,300)).save("5_highlights_sel.png");

    {
        KisPaintDeviceSP dstDevice = dst->getProjection("01_bevel_highlight", config->highlightBlendMode(), srcDevice);

        const KoColor fillColor(config->highlightColor(), dstDevice->colorSpace());
        const QRect &fillRect = d.shadowHighlightsFinalRect;
        KisPaintDeviceSP fillDevice = new KisPaintDevice(dstDevice->colorSpace());
        fillDevice->setDefaultPixel(fillColor);
        KisPainter gc(dstDevice);
        gc.setSelection(baseSelection);
        gc.setCompositeOp(COMPOSITE_OVER);
        env->setupFinalPainter(&gc, config->highlightOpacity(), QBitArray());
        gc.bitBlt(fillRect.topLeft(), fillDevice, fillRect);
        gc.end();
    }
}