Example #1
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::selectPixelSelection(KisPixelSelectionSP selection, SelectionAction action)
{
    KisViewManager* view = m_canvas->viewManager();

    if (selection->selectedExactRect().isEmpty()) {
        m_canvas->viewManager()->selectionManager()->deselect();
        return;
    }

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

    applicator.applyCommand(new LazyInitGlobalSelection(view));

    struct ApplyToPixelSelection : public KisTransactionBasedCommand {
        ApplyToPixelSelection(KisViewManager *view,
                              KisPixelSelectionSP selection,
                              SelectionAction action) : m_view(view),
                                                        m_selection(selection),
                                                        m_action(action) {}
        KisViewManager *m_view;
        KisPixelSelectionSP m_selection;
        SelectionAction m_action;

        KUndo2Command* paint() {

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

            bool hasSelection = !pixelSelection->isEmpty();

            KisSelectionTransaction transaction(pixelSelection);

            if (!hasSelection && m_action == SELECTION_SUBTRACT) {
                pixelSelection->invert();
            }

            pixelSelection->applySelection(m_selection, m_action);

            QRect dirtyRect = m_view->image()->bounds();
            if (hasSelection && m_action != SELECTION_REPLACE && m_action != SELECTION_INTERSECT) {
                dirtyRect = m_selection->selectedRect();
            }
            m_view->selection()->updateProjection(dirtyRect);

            KUndo2Command *savedCommand = transaction.endAndTake();
            pixelSelection->setDirty(dirtyRect);

            return savedCommand;
        }
    };

    applicator.applyCommand(new ApplyToPixelSelection(view, selection, action));
    applicator.end();
}
void KisSelectionToolHelper::selectPixelSelection(KisPixelSelectionSP selection, SelectionAction action)
{
    KisView2* view = m_canvas->view();
    if (selection->selectedRect().isEmpty()) {
        m_canvas->view()->selectionManager()->deselect();
        return;
    }

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

    bool hasSelection = view->selection();

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

    KisSelectionTransaction transaction(m_name, m_image->undoAdapter(), view->selection());

    KisPixelSelectionSP pixelSelection = view->selection()->getOrCreatePixelSelection();

    if (!hasSelection && action == SELECTION_SUBTRACT) {
        pixelSelection->invert();
    }

    pixelSelection->applySelection(selection, action);

    QRect dirtyRect = m_image->bounds();
    if (hasSelection && action != SELECTION_REPLACE && action != SELECTION_INTERSECT) {
        dirtyRect = selection->selectedRect();
    }
    view->selection()->updateProjection(dirtyRect);

    transaction.commit(undoAdapter);
    undoAdapter->endMacro();

    pixelSelection->setDirty(dirtyRect);
    m_canvas->view()->selectionManager()->selectionChanged();
}
Example #4
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();
    }
}
Example #5
0
void KisSelectionToolHelper::selectPixelSelection(KisPixelSelectionSP selection, SelectionAction action)
{
    KisViewManager* view = m_canvas->viewManager();

    if (selection->selectedExactRect().isEmpty()) {
        m_canvas->viewManager()->selectionManager()->deselect();
        return;
    }

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

    applicator.applyCommand(new LazyInitGlobalSelection(view));

    struct ApplyToPixelSelection : public KisTransactionBasedCommand {
        ApplyToPixelSelection(KisViewManager *view,
                              KisPixelSelectionSP selection,
                              SelectionAction action) : m_view(view),
                                                        m_selection(selection),
                                                        m_action(action) {}
        KisViewManager *m_view;
        KisPixelSelectionSP m_selection;
        SelectionAction m_action;

        KUndo2Command* paint() override {

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

            bool hasSelection = !pixelSelection->isEmpty();

            KisSelectionTransaction transaction(pixelSelection);

            if (!hasSelection && m_action == SELECTION_SUBTRACT) {
                pixelSelection->invert();
            }

            pixelSelection->applySelection(m_selection, m_action);

            const QRect imageBounds = m_view->image()->bounds();
            QRect selectionExactRect = m_view->selection()->selectedExactRect();

            if (!imageBounds.contains(selectionExactRect)) {
                pixelSelection->crop(imageBounds);
                if (pixelSelection->outlineCacheValid()) {
                    QPainterPath cache = pixelSelection->outlineCache();
                    QPainterPath imagePath;
                    imagePath.addRect(imageBounds);
                    cache &= imagePath;
                    pixelSelection->setOutlineCache(cache);
                }
                selectionExactRect &= imageBounds;
            }

            QRect dirtyRect = imageBounds;
            if (hasSelection && m_action != SELECTION_REPLACE && m_action != SELECTION_INTERSECT) {
                dirtyRect = m_selection->selectedRect();
            }
            m_view->selection()->updateProjection(dirtyRect);

            KUndo2Command *savedCommand = transaction.endAndTake();
            pixelSelection->setDirty(dirtyRect);

            if (selectionExactRect.isEmpty()) {
                KisCommandUtils::CompositeCommand *cmd = new KisCommandUtils::CompositeCommand();
                cmd->addCommand(savedCommand);
                cmd->addCommand(new KisDeselectGlobalSelectionCommand(m_view->image()));
                savedCommand = cmd;
            }

            return savedCommand;
        }
    };

    applicator.applyCommand(new ApplyToPixelSelection(view, selection, action));
    applicator.end();
}