diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -252,6 +252,7 @@ widgets/kis_stopgradient_slider_widget.cpp widgets/kis_spinbox_color_selector.cpp widgets/kis_screen_color_picker.cpp + widgets/kis_preset_live_preview_view.cpp widgets/KoDualColorButton.cpp widgets/kis_color_input.cpp widgets/kis_color_button.cpp @@ -264,6 +265,7 @@ widgets/KoFillConfigWidget.cpp widgets/KoShapeFillWrapper.cpp + utils/kis_document_aware_spin_box_unit_manager.cpp input/kis_input_manager.cpp diff --git a/libs/ui/forms/wdgpaintopsettings.ui b/libs/ui/forms/wdgpaintopsettings.ui --- a/libs/ui/forms/wdgpaintopsettings.ui +++ b/libs/ui/forms/wdgpaintopsettings.ui @@ -6,367 +6,21 @@ 0 0 - 1431 - 512 + 1441 + 495 Brush Editor - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 5 - - - - - - - - false - - - - 0 - - - 3 - - - 1 - - - 3 - - - 3 - - - - - - 0 - 4 - - - - - 120 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - - - - - 5 - - - 5 - - - 0 - - - 5 - - - 5 - - - - - - 0 - 0 - - - - Erase mode will use a separate brush size - - - Eraser switch size - - - false - - - - - - - - 0 - 0 - - - - Temporarily Save Tweaks To Presets - - - true - - - - - - - - 0 - 0 - - - - Erase mode will use a separate brush opacity - - - Eraser switch opacity - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 60 - 0 - - - - - - - - - - 5 - - - 5 - - - 0 - - - 5 - - - 0 - - - - - - 0 - 0 - - - - Load Engine Defaults - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Overwrite Brush - - - - - - - Save New Brush Preset... - - - - - - - - - - - - - - - false - - - - 5 - - - 5 - - - 5 - - - 5 - - - 5 - - - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 250 - 300 - - - - - - - - - - - - - - - - - - - - - - - - - - - Fill area with gradient - - - - - - - - - - Fill area with background color - - - - - - - - - - Reset area to white - - - - - - - - - - - - 10 + 5 - 10 + 1 @@ -378,14 +32,14 @@ - 30 - 30 + 55 + 55 - 30 - 30 + 55 + 55 @@ -408,107 +62,266 @@ false + + Qt::AlignHCenter|Qt::AlignTop + QPainter::Antialiasing - - - - - - - 200 - 0 - - - - Current Brush Name - - - 0 - - - 5 + + QGraphicsView::AnchorViewCenter - - - - 0 - 0 - - - - + + + 5 - + + + + + 0 + 0 + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + + - + 0 0 - - - - - - - - - - 0 - 0 - + + + 320 + 60 + - 50 - 16777215 + 320 + 60 - - + + + false + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + Qt::ScrollBarAlwaysOff - + + Qt::ScrollBarAlwaysOff + + true - - - - - - - 250 - 0 - + + QPainter::Antialiasing|QPainter::HighQualityAntialiasing|QPainter::SmoothPixmapTransform + + + QGraphicsView::AnchorViewCenter - - - - 0 - 0 - + + + 0 - - Save + + 5 - + + + + + 0 + 0 + + + + + 150 + 0 + + + + + 16777215 + 20 + + + + + 10 + 75 + true + + + + 0 + + + Current Brush Name + + + false + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + 0 + + + 5 + + + + + + + + 0 + 0 + + + + + 16777215 + 20 + + + + Current Brush Engine + + + false + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + 5 + + + + - - - Cancel - - + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + false + + + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + + @@ -531,64 +344,86 @@ - - - - 0 - 0 - - - - - 35 - 20 - - - - Presets - - - - - - - - 0 - 0 - - - - - 35 - 30 - - - - Settings - - - - - - - - 0 - 0 - - - - - 35 - 30 - - - - Scratchpad - - - true - - + + + + + + 0 + 0 + + + + + 35 + 20 + + + + + 16777215 + 20 + + + + Presets + + + + + + + + 0 + 0 + + + + + 35 + 20 + + + + + 16777215 + 20 + + + + Settings + + + + + + + + 0 + 0 + + + + + 35 + 20 + + + + + 16777215 + 20 + + + + Scratchpad + + + true + + + + @@ -614,9 +449,238 @@ 5 - + + + + + + 0 + 0 + + + + Engine: + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 350 + + + + + 1677215 + 1677215 + + + + + + + + + + + + + + false + + + + 0 + + + 3 + + + 1 + + + 3 + + + 3 + + + + + + 0 + 4 + + + + + 120 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + + + + + 5 + + + 5 + + + 0 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + Erase mode will use a separate brush size + + + Eraser switch size + + + false + + + + + + + + 0 + 0 + + + + Temporarily Save Tweaks To Presets + + + true + + + + + + + + 0 + 0 + + + + Erase mode will use a separate brush opacity + + + Eraser switch opacity + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 60 + 0 + + + + + + + + + + 5 + + + 5 + + + 0 + + + 5 + + + 0 + + + + + - + 0 @@ -624,64 +688,207 @@ - Engine: + Load Engine Defaults - + - + 0 0 + + Rename + - + + + + 250 + 0 + + + + + + - + 0 0 - + Save + + + + + + + Cancel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Overwrite Brush + + + + + + + Save New Brush Preset... + + + + + + + + + + false + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + - - - - 0 - 0 - + + + QFrame::NoFrame - - - 0 - 350 - + + QFrame::Plain - - - 1677215 - 1677215 - + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 250 + 300 + + + + + + + + + + + + + + + + + + + + + + + + + Fill area with gradient + + + + + + + + + + Fill area with background color + + + + + + + + + + Reset area to white + + + + + + + + - presetsContainer - brushEditorSettingsControls - scratchpadControls @@ -691,6 +898,12 @@ 1 + KisPresetLivePreviewView + QGraphicsView +
kis_preset_live_preview_view.h
+ 1 +
+ KisPresetSelectorStrip QWidget
kis_preset_selector_strip.h
diff --git a/libs/ui/widgets/kis_paintop_presets_popup.cpp b/libs/ui/widgets/kis_paintop_presets_popup.cpp --- a/libs/ui/widgets/kis_paintop_presets_popup.cpp +++ b/libs/ui/widgets/kis_paintop_presets_popup.cpp @@ -56,10 +56,10 @@ #include "kis_signal_auto_connection.h" #include + // ones from brush engine selector #include - - +#include struct KisPaintOpPresetsPopup::Private @@ -170,8 +170,6 @@ menu->addAction(sliderAction); - - // configure the button and assign menu m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setMenu(menu); m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setIcon(KisIconUtils::loadIcon("view-choose")); @@ -276,9 +274,6 @@ connect(m_d->uiWdgPaintOpPresetSettings.reloadPresetButton, SIGNAL(clicked()), SLOT(slotUpdatePresetSettings())); - - - m_d->detached = false; m_d->ignoreHideEvents = false; m_d->minimumSettingsWidgetSize = QSize(0, 0); @@ -305,6 +300,20 @@ connect(m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatePaintOpFilter())); + // setup things like the scene construct images, layers, etc that is a one-time thing + m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView->setup(); + + m_d->uiWdgPaintOpPresetSettings.zoomOutGraphicsViewButton->setIcon(KisIconUtils::loadIcon("view-fullscreen")); + connect(m_d->uiWdgPaintOpPresetSettings.zoomOutGraphicsViewButton, SIGNAL(clicked(bool)), + m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView, + SLOT(slotZoomToOneHundredPercent())); + + + m_d->uiWdgPaintOpPresetSettings.resetGraphicsViewButton->setIcon(KisIconUtils::loadIcon("view-refresh")); + connect(m_d->uiWdgPaintOpPresetSettings.resetGraphicsViewButton, SIGNAL(clicked(bool)), + m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView, + SLOT(slotResetViewZoom())); + } @@ -323,8 +332,6 @@ // This function doesn't really do anything except get the UI in a state to rename a brush preset m_d->uiWdgPaintOpPresetSettings.renameBrushPresetButton->setVisible(!isRenaming); - m_d->uiWdgPaintOpPresetSettings.currentBrushNameLabel->setVisible(!isRenaming); - m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setVisible(!isRenaming); m_d->uiWdgPaintOpPresetSettings.renameBrushNameTextField->setVisible(isRenaming); m_d->uiWdgPaintOpPresetSettings.updateBrushNameButton->setVisible(isRenaming); @@ -332,6 +339,9 @@ m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setEnabled(!isRenaming); m_d->uiWdgPaintOpPresetSettings.saveNewBrushPresetButton->setEnabled(!isRenaming); + + m_d->uiWdgPaintOpPresetSettings.bnDefaultPreset->setVisible(!isRenaming); + } void KisPaintOpPresetsPopup::slotSaveRenameCurrentBrush() @@ -466,29 +476,6 @@ m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->setLimitations(l); } - -void KisPaintOpPresetsPopup::slotUpdatePresetSettings() -{ - if (!m_d->resourceProvider) { - return; - } - if (!m_d->resourceProvider->currentPreset()) { - return; - } - - - bool isPresetDirty = m_d->resourceProvider->currentPreset()->isPresetDirty(); - - // don't need to reload or overwrite a clean preset - m_d->uiWdgPaintOpPresetSettings.dirtyPresetIndicatorButton->setVisible(isPresetDirty); - m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setVisible(isPresetDirty); - m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setEnabled(isPresetDirty); - - - -} - - QImage KisPaintOpPresetsPopup::cutOutOverlay() { return m_d->uiWdgPaintOpPresetSettings.scratchPad->cutoutOverlay(); @@ -556,16 +543,17 @@ } } - QString selectedBrush = resource->name().append(" (").append(currentBrushEngineName).append(" ").append("Engine").append(")"); + QString selectedBrush = resource->name(); m_d->uiWdgPaintOpPresetSettings.currentBrushNameLabel->setText(selectedBrush); + m_d->uiWdgPaintOpPresetSettings.currentBrushEngineLabel->setText(currentBrushEngineName.append(" ").append("Engine")); m_d->uiWdgPaintOpPresetSettings.renameBrushNameTextField->setText(resource->name()); // get the preset image and pop it into the thumbnail area on the top of the brush editor QGraphicsScene * thumbScene = new QGraphicsScene(this); - thumbScene->addPixmap(QPixmap::fromImage(resource->image().scaled(30, 30))); - thumbScene->setSceneRect(0, 0, 30, 30); // 30 x 30 image for thumb. this is also set in the UI + thumbScene->addPixmap(QPixmap::fromImage(resource->image().scaled(55, 55))); + thumbScene->setSceneRect(0, 0, 55, 55); // 55 x 55 image for thumb. this is also set in the UI m_d->uiWdgPaintOpPresetSettings.presetThumbnailicon->setScene(thumbScene); toggleBrushRenameUIActive(false); // reset the UI state of renaming a brush if we are changing brush presets @@ -762,3 +750,25 @@ m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setIcon(KisIconUtils::loadIcon("edit-delete")); m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setIcon(KisIconUtils::loadIcon("view-choose")); } + +void KisPaintOpPresetsPopup::slotUpdatePresetSettings() +{ + if (!m_d->resourceProvider) { + return; + } + if (!m_d->resourceProvider->currentPreset()) { + return; + } + + bool isPresetDirty = m_d->resourceProvider->currentPreset()->isPresetDirty(); + + // don't need to reload or overwrite a clean preset + m_d->uiWdgPaintOpPresetSettings.dirtyPresetIndicatorButton->setVisible(isPresetDirty); + m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setVisible(isPresetDirty); + m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setEnabled(isPresetDirty); + + + // update live preview area in here... + m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView->setCurrentPreset(m_d->resourceProvider->currentPreset()); + m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView->updateStroke(); +} diff --git a/libs/ui/widgets/kis_preset_live_preview_view.h b/libs/ui/widgets/kis_preset_live_preview_view.h new file mode 100644 --- /dev/null +++ b/libs/ui/widgets/kis_preset_live_preview_view.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2017 Scott Petrovic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _KIS_PRESET_LIVE_PREVIEW_ +#define _KIS_PRESET_LIVE_PREVIEW_ + +#include +#include +#include +#include +#include + +#include "kis_paintop_preset.h" +#include "KoColorSpaceRegistry.h" +#include "kis_paint_layer.h" +#include "kis_painter.h" +#include "kis_distance_information.h" +#include "kis_painting_information_builder.h" +#include +#include + +/** + * Widget for displaying a live brush preview of your + * selected brush. It listens for signalsetting changes + * that the brush preset outputs and updates the preview + * accordingly. This class can be added to a UI file + * similar to how a QGraphicsView is added + */ +class KisPresetLivePreviewView : public QGraphicsView +{ + Q_OBJECT + + +public: + + KisPresetLivePreviewView(QWidget *parent); + ~KisPresetLivePreviewView(); + + /** + * @brief one time setup for initialization of many variables. + * This live preview might be in a UI file, so make sure to + * call this before starting to use it + */ + void setup(); + + /** + * @brief set the current preset from resource manager for the live preview to use. + * Good to call this every stroke update in case the preset has changed + * @param the current preset from the resource manager + */ + void setCurrentPreset(KisPaintOpPresetSP preset); + void updateStroke(); + + +public Q_SLOTS: + /** + * @brief scales the view to fit the brush stroke and moves it back to the center position + */ + void slotResetViewZoom(); + + /** + * @brief sets the zoom level to full size to get a close up of larger brushes + */ + void slotZoomToOneHundredPercent(); + + + +private: + + /// internally sets the image area for brush preview + KisImageSP m_image; + + /// internally sets the layer area for brush preview + KisLayerSP m_layer; + + /// internally sets the color space for brush preview + const KoColorSpace *m_colorSpace; + + /// painter that actually paints the stroke + KisPainter *m_brushPreviewPainter; + + /// the scene that can add items like text and the brush stroke image + QGraphicsScene *m_brushPreviewScene; + + /// holds the preview brush stroke data + QGraphicsPixmapItem *m_sceneImageItem; + + /// holds the 'no preview available' text object + QGraphicsTextItem *m_noPreviewText; + + /// holds the width and height of the image of the brush preview + /// Probably can later add set functions to make this customizable + /// It is hard-coded to 1200 x 400 for right now for image size + QRect m_canvasSize; + + /// convenience variable used internally when positioning the objects + /// and points in the scene + QPointF m_canvasCenterPoint; + + /// internal variables for constructing the stroke start and end shape + /// there are two points that construct the "S" curve with this + QPen m_penSettings; + KisDistanceInformation m_currentDistance; + QPointF m_startPoint; + QPointF m_endPoint; + KisPaintInformation m_pi1; + KisPaintInformation m_pi2; + KisPaintInformation m_paintDabStart; + KisPaintInformation m_paintDabEnd; + + QPainterPath m_curvedLine; + KisPaintInformation m_curvePointPI1; + KisPaintInformation m_curvePointPI2; + + /// internally stores the current preset. + /// See setCurrentPreset(KisPaintOpPresetSP preset) + /// for setting this externally + KisPaintOpPresetSP m_currentPreset; + + /// holds the current zoom(scale) level of scene + float m_scaleFactor; + + /// internal reference for internal brush size + /// used to check if our brush size has changed + /// do zooming and other things internall if it has changed + float m_currentBrushSize = 1.0; + + /// the range of brush sizes that will control zooming in/out + const float m_minBrushVal = 10.0; + const float m_maxBrushVal = 100.0; + + /// range of scale values. 1.0 == 100% + const qreal m_minScale = 1.0; + const qreal m_maxScale = 0.3; + + /// multiplier that is used for lengthening the brush stroke points + const float m_minStrokeScale = 0.4; // for smaller brush stroke + const float m_maxStrokeScale = 1.0; // for larger brush stroke + + + /** + * @brief reads the brush size and scales the view out to fit it + * used internally when resetting the views or changing brush sizes + */ + void zoomToBrushSize(); + + /** + * @brief works as both clearing the previous stroke, providing + * striped backgrounds for smudging brushes, and text if there is no preview + */ + void paintBackground(); + + /** + * @brief creates and performs the actual stroke that goes on top of the background + * this is internally and should always be called after the paintBackground() + */ + void setupAndPaintStroke(); + + +}; + +#endif diff --git a/libs/ui/widgets/kis_preset_live_preview_view.cpp b/libs/ui/widgets/kis_preset_live_preview_view.cpp new file mode 100644 --- /dev/null +++ b/libs/ui/widgets/kis_preset_live_preview_view.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2017 Scott Petrovic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include "kis_paintop_settings.h" + +KisPresetLivePreviewView::KisPresetLivePreviewView(QWidget *parent): QGraphicsView(parent) +{ + +} + +KisPresetLivePreviewView::~KisPresetLivePreviewView() +{ + delete m_brushPreviewPainter; + delete m_noPreviewText; + delete m_brushPreviewScene; +} + +void KisPresetLivePreviewView::setup() +{ + // initializing to 0 helps check later if they actually have something in them + m_noPreviewText = 0; + m_sceneImageItem = 0; + + setCursor(Qt::SizeAllCursor); + + setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); + setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); + + + // layer image needs to be big enough to get an entire stroke of data + m_canvasSize.setWidth(1200); + m_canvasSize.setHeight(400); + + m_canvasCenterPoint.setX(m_canvasSize.width()*0.5); + m_canvasCenterPoint.setY(m_canvasSize.height()*0.5); + + m_colorSpace = KoColorSpaceRegistry::instance()->rgb8(); + m_image = new KisImage(0, m_canvasSize.width(), m_canvasSize.height(), m_colorSpace, "stroke sample image"); + + + m_layer = new KisPaintLayer(m_image, "livePreviewStrokeSample", OPACITY_OPAQUE_U8, m_colorSpace); + m_brushPreviewPainter = new KisPainter(m_layer->paintDevice()); + + // set scene for the view + m_brushPreviewScene = new QGraphicsScene(); + setScene(m_brushPreviewScene); + + zoomToBrushSize(); +} + +void KisPresetLivePreviewView::setCurrentPreset(KisPaintOpPresetSP preset) +{ + m_currentPreset = preset; +} + +void KisPresetLivePreviewView::updateStroke() +{ + paintBackground(); + + // do not paint a stroke if we are either of these two engines + if (m_currentPreset->paintOp().id() == "roundmarker" || m_currentPreset->paintOp().id() == "experimentbrush") { + return; + } + + setupAndPaintStroke(); + + + // crop the layer so a brush stroke won't go outside of the area + m_layer->paintDevice()->crop(0,0, m_layer->image()->width(), m_layer->image()->height()); + + QImage m_temp_image; + m_temp_image = m_layer->paintDevice()->convertToQImage(0); + + + // only add the object once...then just update the pixmap so we can move the preview around + if (!m_sceneImageItem) { + m_sceneImageItem = m_brushPreviewScene->addPixmap(QPixmap::fromImage(m_temp_image)); + m_sceneImageItem->setFlag(QGraphicsItem::ItemIsSelectable); + m_sceneImageItem->setFlag(QGraphicsItem::ItemIsMovable); + m_sceneImageItem->setFlag(QGraphicsItem::ItemSendsGeometryChanges); + m_sceneImageItem->setPos(-m_canvasCenterPoint.x(), -m_canvasCenterPoint.y()); // center the object + } else { + m_sceneImageItem->setPixmap(QPixmap::fromImage(m_temp_image)); + } + +} + +void KisPresetLivePreviewView::slotResetViewZoom() +{ + zoomToBrushSize(); +} + +void KisPresetLivePreviewView::slotZoomToOneHundredPercent() +{ + m_scaleFactor = 1.0; + resetMatrix(); + this->scale(m_scaleFactor, m_scaleFactor); +} + +void KisPresetLivePreviewView::paintBackground() +{ + // clean up "no preview" text object if it exists. we will add it later if we need it + if (m_noPreviewText) { + this->scene()->removeItem(m_noPreviewText); + m_noPreviewText = 0; + } + + + if (m_currentPreset->paintOp().id() == "colorsmudge" || m_currentPreset->paintOp().id() == "deformbrush") { + + // easier to see deformations and smudging with alternating stripes in the background + // paint the whole background with alternating stripes + int grayStrips = 20; + for (int i=0; i < grayStrips; i++ ) { + + float sectionPercent = 1.0 / (float)grayStrips; + bool isAlternating = i % 2; + KoColor fillColor; + + if (isAlternating) { + fillColor.fromQColor(QColor(80,80,80)); + } else { + fillColor.fromQColor(QColor(140,140,140)); + } + + + m_brushPreviewPainter->fill(m_layer->image()->width()*sectionPercent*i, + 0, + m_layer->image()->width()*(sectionPercent*i +sectionPercent), + m_layer->image()->height(), + fillColor); + + } + + m_brushPreviewPainter->setPaintColor(KoColor(Qt::white, m_colorSpace)); + + } + else if (m_currentPreset->paintOp().id() == "roundmarker" || m_currentPreset->paintOp().id() == "experimentbrush"){ + // cases where we will not show a preview for now + // roundbrush (quick) -- this isn't showing anything, disable showing preview + // experimentbrush -- this creates artifacts that carry over to other previews and messes up their display + + if(m_sceneImageItem) { + this->scene()->removeItem(m_sceneImageItem); + m_sceneImageItem = 0; + } + + QFont font; + font.setPixelSize(14); + font.setBold(false); + + slotZoomToOneHundredPercent(); // 100% zoom if we are showing the text + + m_noPreviewText = this->scene()->addText(i18n("No Preview for this engine"),font); + m_noPreviewText->setPos(-this->width()/3, -this->height()/4); // this mostly centers the text in the viewport + + return; + + } + else { + + // fill with gray first to clear out what existed from previous preview + m_brushPreviewPainter->fill(0,0, + m_layer->image()->width(), + m_layer->image()->height(), + KoColor(palette().color(QPalette::Background) , m_colorSpace)); + + m_brushPreviewPainter->setPaintColor(KoColor(palette().color(QPalette::Text), m_colorSpace)); + } +} + +void KisPresetLivePreviewView::setupAndPaintStroke() +{ + // limit the brush stroke size. larger brush strokes just don't look good and are CPU intensive + // we are making a proxy preset and setting it to the painter...otherwise setting the brush size of the original preset + // will fire off signals that make this run in an infinite loop + qreal previewSize = qBound(1.0, m_currentPreset->settings()->paintOpSize(), 150.0 ); // constrain current brush size to these values + KisPaintOpPresetSP proxy_preset = m_currentPreset->clone(); + proxy_preset->settings()->setPaintOpSize(previewSize); + m_brushPreviewPainter->setPaintOpPreset(proxy_preset, m_layer, m_image); + + + // we only need to change the zoom amount if we are changing the brush size + if (m_currentBrushSize != m_currentPreset->settings()->paintOpSize()) { + m_currentBrushSize = m_currentPreset->settings()->paintOpSize(); + zoomToBrushSize(); + } + + + + // slope-intercept is good for mapping two values. + // find the slope of the line (slope-intercept form) + float slope = (m_maxScale-m_maxStrokeScale) / (m_minScale-m_minStrokeScale); // y2-y1 / x2-x1 + float yIntercept = m_maxStrokeScale - slope * m_minStrokeScale; // y1 − m * x1 + + float strokeScaleAmount = m_scaleFactor * slope + yIntercept; // y = mx + b + strokeScaleAmount = qBound(m_minStrokeScale, strokeScaleAmount, m_maxStrokeScale); + + + // points for drawing an S curve + // we are going to paint the stroke right in the middle of the canvas to make sure + // everything is captured for big brush strokes + m_curvePointPI1.setPos(QPointF(m_canvasCenterPoint.x() - (this->width()*strokeScaleAmount), + m_canvasCenterPoint.y() + (this->height()*strokeScaleAmount))); + m_curvePointPI1.setPressure(0.0); + + m_curvePointPI2.setPos(QPointF(m_canvasCenterPoint.x() + (this->width()*strokeScaleAmount), + m_canvasCenterPoint.y())); + + m_curvePointPI2.setPressure(1.0); + + m_brushPreviewPainter->paintBezierCurve(m_curvePointPI1, + QPointF(m_canvasCenterPoint.x(), + m_canvasCenterPoint.y()-this->height()), + QPointF(m_canvasCenterPoint.x(), + m_canvasCenterPoint.y()+this->height()), + m_curvePointPI2, &m_currentDistance); + +} + +void KisPresetLivePreviewView::zoomToBrushSize() +{ + // find the slope of the line (slope-intercept form) + float slope = (m_maxScale-m_minScale) / (m_maxBrushVal-m_minBrushVal); // y2-y1 / x2-x1 + float yIntercept = m_minScale - slope * m_minBrushVal; // y1 − m * x1 + + + // finally calculate our zoom level + float thresholdValue = qBound(m_minBrushVal, m_currentBrushSize, m_maxBrushVal); + m_scaleFactor = thresholdValue * slope + yIntercept; // y = mx + b + + resetMatrix(); + this->scale(m_scaleFactor,m_scaleFactor); + + // reset position of image preview in case we moved it + if(m_sceneImageItem) { + m_sceneImageItem->setPos(-m_canvasSize.width()/2, -m_canvasSize.height()/2 ); + } +} +