Commit 8c66e587 authored by Wolthera van Hövell's avatar Wolthera van Hövell 🛍

Add options to allow rotation and scale of geometric pattern fill.

parent 999b37ef
......@@ -114,6 +114,7 @@ void KisPainter::init()
d->paramInfo = KoCompositeOp::ParameterInfo();
d->renderingIntent = KoColorConversionTransformation::internalRenderingIntent();
d->conversionFlags = KoColorConversionTransformation::internalConversionFlags();
d->patternTransform = QTransform();
}
KisPainter::~KisPainter()
......@@ -1456,7 +1457,7 @@ void KisPainter::Private::fillPainterPathImpl(const QPainterPath& path, const QR
break;
case FillStylePattern:
if (pattern) { // if the user hasn't got any patterns installed, we shouldn't crash...
fillPainter->fillRect(fillRect, pattern, QTransform());
fillPainter->fillRect(fillRect, pattern, patternTransform);
}
break;
case FillStyleGenerator:
......@@ -2597,6 +2598,16 @@ KisPainter::FillStyle KisPainter::fillStyle() const
return d->fillStyle;
}
void KisPainter::setPatternTransform(QTransform transform)
{
d->patternTransform = transform;
}
QTransform KisPainter::patternTransform()
{
return d->patternTransform;
}
void KisPainter::setAntiAliasPolygonFill(bool antiAliasPolygonFill)
{
d->antiAliasPolygonFill = antiAliasPolygonFill;
......
......@@ -738,6 +738,12 @@ public:
/// Returns the current fill style
FillStyle fillStyle() const;
/// Set the transform on the pattern.
void setPatternTransform(QTransform transform);
/// get the current transform on the pattern.
QTransform patternTransform();
/// Set whether a polygon's filled area should be anti-aliased or not. The default is true.
void setAntiAliasPolygonFill(bool antiAliasPolygonFill);
......
......@@ -75,6 +75,7 @@ struct Q_DECL_HIDDEN KisPainter::Private {
KoColorConversionTransformation::ConversionFlags conversionFlags;
KisRunnableStrokeJobsInterface *runnableStrokeJobsInterface = 0;
QScopedPointer<KisRunnableStrokeJobsInterface> fakeRunnableStrokeJobsInterface;
QTransform patternTransform;
bool tryReduceSourceRect(const KisPaintDevice *srcDev,
QRect *srcRect,
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>185</width>
<height>46</height>
<width>287</width>
<height>167</height>
</rect>
</property>
<property name="windowTitle">
......@@ -35,15 +35,15 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="2" column="0">
<widget class="QLabel" name="textLabelOutline">
<item row="1" column="0">
<widget class="QLabel" name="textLabelFill">
<property name="text">
<string>Outline:</string>
<string>Fill:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cmbOutline">
<item row="1" column="1">
<widget class="QComboBox" name="cmbFill">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -52,30 +52,35 @@
</property>
<item>
<property name="text">
<string>No Outline</string>
<string>Not Filled</string>
</property>
</item>
<item>
<property name="text">
<string>Brush</string>
<string>Foreground Color</string>
</property>
</item>
<item>
<property name="text">
<string>Brush (Background Color)</string>
<string>Background Color</string>
</property>
</item>
<item>
<property name="text">
<string>Pattern</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="textLabelFill">
<item row="2" column="0">
<widget class="QLabel" name="textLabelOutline">
<property name="text">
<string>Fill:</string>
<string>Outline:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cmbFill">
<item row="2" column="1">
<widget class="QComboBox" name="cmbOutline">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -84,28 +89,60 @@
</property>
<item>
<property name="text">
<string>Not Filled</string>
</property>
</item>
<item>
<property name="text">
<string>Foreground Color</string>
<string>No Outline</string>
</property>
</item>
<item>
<property name="text">
<string>Background Color</string>
<string>Brush</string>
</property>
</item>
<item>
<property name="text">
<string>Pattern</string>
<string>Brush (Background Color)</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="gbPatternTransform">
<property name="title">
<string>Pattern Transform</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Rotate:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Scale:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="KisDoubleSliderSpinBox" name="sldRotation" native="true"/>
</item>
<item row="1" column="1">
<widget class="KisDoubleSliderSpinBox" name="sldScale" native="true"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KisDoubleSliderSpinBox</class>
<extends>QWidget</extends>
<header>kis_slider_spin_box.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
......@@ -33,7 +33,8 @@ KisFigurePaintingToolHelper::KisFigurePaintingToolHelper(const KUndo2MagicString
KisNodeSP currentNode,
KoCanvasResourceProvider *resourceManager,
KisToolShapeUtils::StrokeStyle strokeStyle,
KisToolShapeUtils::FillStyle fillStyle)
KisToolShapeUtils::FillStyle fillStyle,
QTransform fillTransform)
{
m_strokesFacade = image.data();
......@@ -42,7 +43,7 @@ KisFigurePaintingToolHelper::KisFigurePaintingToolHelper(const KUndo2MagicString
currentNode,
resourceManager);
setupPaintStyles(m_resources, strokeStyle, fillStyle);
setupPaintStyles(m_resources, strokeStyle, fillStyle, fillTransform);
KisFreehandStrokeInfo *strokeInfo = new KisFreehandStrokeInfo();
......@@ -54,7 +55,8 @@ KisFigurePaintingToolHelper::KisFigurePaintingToolHelper(const KUndo2MagicString
void KisFigurePaintingToolHelper::setupPaintStyles(KisResourcesSnapshotSP resources,
KisToolShapeUtils::StrokeStyle strokeStyle,
KisToolShapeUtils::FillStyle fillStyle)
KisToolShapeUtils::FillStyle fillStyle,
QTransform fillTransform)
{
using namespace KisToolShapeUtils;
......@@ -97,6 +99,8 @@ void KisFigurePaintingToolHelper::setupPaintStyles(KisResourcesSnapshotSP resour
resources->setFillStyle(KisPainter::FillStyleNone);
break;
}
resources->setFillTransform(fillTransform);
}
KisFigurePaintingToolHelper::~KisFigurePaintingToolHelper()
......
......@@ -36,7 +36,8 @@ public:
KisNodeSP currentNode,
KoCanvasResourceProvider *resourceManager,
KisToolShapeUtils::StrokeStyle strokeStyle,
KisToolShapeUtils::FillStyle fillStyle);
KisToolShapeUtils::FillStyle fillStyle,
QTransform fillTransform = QTransform());
~KisFigurePaintingToolHelper();
void paintLine(const KisPaintInformation &pi0,
......@@ -56,7 +57,8 @@ public:
private:
void setupPaintStyles(KisResourcesSnapshotSP resources,
KisToolShapeUtils::StrokeStyle strokeStyle,
KisToolShapeUtils::FillStyle fillStyle);
KisToolShapeUtils::FillStyle fillStyle,
QTransform fillTransform);
private:
KisStrokeId m_strokeId;
......
......@@ -66,6 +66,7 @@ struct KisResourcesSnapshot::Private {
KisPainter::StrokeStyle strokeStyle = KisPainter::StrokeStyleBrush;
KisPainter::FillStyle fillStyle = KisPainter::FillStyleForegroundColor;
QTransform fillTransform = QTransform();
bool globalAlphaLock = false;
qreal effectiveZoom = 1.0;
......@@ -198,6 +199,8 @@ void KisResourcesSnapshot::setupPainter(KisPainter* painter)
painter->setStrokeStyle(m_d->strokeStyle);
painter->setFillStyle(m_d->fillStyle);
painter->setPatternTransform(m_d->fillTransform);
/**
* The paintOp should be initialized the last, because it may
......@@ -260,6 +263,11 @@ void KisResourcesSnapshot::setFillStyle(KisPainter::FillStyle fillStyle)
m_d->fillStyle = fillStyle;
}
void KisResourcesSnapshot::setFillTransform(QTransform transform)
{
m_d->fillTransform = transform;
}
KisNodeSP KisResourcesSnapshot::currentNode() const
{
return m_d->currentNode;
......
......@@ -52,6 +52,7 @@ public:
void setCurrentNode(KisNodeSP node);
void setStrokeStyle(KisPainter::StrokeStyle strokeStyle);
void setFillStyle(KisPainter::FillStyle fillStyle);
void setFillTransform(QTransform transform);
KisNodeSP currentNode() const;
KisImageSP image() const;
......
......@@ -87,12 +87,24 @@ QWidget * KisToolShape::createOptionWidget()
m_shapeOptionsWidget->cmbOutline->setCurrentIndex(KisPainter::StrokeStyleBrush);
m_shapeOptionsWidget->sldRotation->setSuffix(QChar(Qt::Key_degree));
m_shapeOptionsWidget->sldRotation->setRange(0.0, 360.0, 2);
m_shapeOptionsWidget->sldRotation->setSingleStep(1.0);
m_shapeOptionsWidget->sldScale->setSuffix("%");
m_shapeOptionsWidget->sldScale->setRange(0.0, 500.0, 2);
m_shapeOptionsWidget->sldScale->setSingleStep(1.0);
//connect two combo box event. Inherited classes can call the slots to make appropriate changes
connect(m_shapeOptionsWidget->cmbOutline, SIGNAL(currentIndexChanged(int)), this, SLOT(outlineSettingChanged(int)));
connect(m_shapeOptionsWidget->cmbFill, SIGNAL(currentIndexChanged(int)), this, SLOT(fillSettingChanged(int)));
connect(m_shapeOptionsWidget->sldRotation, SIGNAL(valueChanged(qreal)), this, SLOT(patternRotationSettingChanged(qreal)));
connect(m_shapeOptionsWidget->sldScale, SIGNAL(valueChanged(qreal)), this, SLOT(patternScaleSettingChanged(qreal)));
m_shapeOptionsWidget->cmbOutline->setCurrentIndex(m_configGroup.readEntry("outlineType", 0));
m_shapeOptionsWidget->cmbFill->setCurrentIndex(m_configGroup.readEntry("fillType", 0));
m_shapeOptionsWidget->sldScale->setValue(m_configGroup.readEntry("patternTransformScale", 100));
m_shapeOptionsWidget->sldRotation->setValue(m_configGroup.readEntry("patternTransformRotation", 0));
//if both settings are empty, force the outline to brush so the tool will work when first activated
if ( m_shapeOptionsWidget->cmbFill->currentIndex() == 0 &&
......@@ -101,6 +113,9 @@ QWidget * KisToolShape::createOptionWidget()
m_shapeOptionsWidget->cmbOutline->setCurrentIndex(1); // brush
}
bool enablePatternTransform = (m_shapeOptionsWidget->cmbFill->currentIndex() == int(KisToolShapeUtils::FillStylePattern));
m_shapeOptionsWidget->gbPatternTransform->setEnabled(enablePatternTransform);
return m_shapeOptionsWidget;
}
......@@ -112,6 +127,18 @@ void KisToolShape::outlineSettingChanged(int value)
void KisToolShape::fillSettingChanged(int value)
{
m_configGroup.writeEntry("fillType", value);
bool enable = (value == int(KisToolShapeUtils::FillStylePattern));
m_shapeOptionsWidget->gbPatternTransform->setEnabled(enable);
}
void KisToolShape::patternRotationSettingChanged(qreal value)
{
m_configGroup.writeEntry("patternTransformRotation", value);
}
void KisToolShape::patternScaleSettingChanged(qreal value)
{
m_configGroup.writeEntry("patternTransformScale", value);
}
KisToolShapeUtils::FillStyle KisToolShape::fillStyle()
......@@ -132,6 +159,19 @@ KisToolShapeUtils::StrokeStyle KisToolShape::strokeStyle()
}
}
QTransform KisToolShape::fillTransform()
{
QTransform transform;
if (m_shapeOptionsWidget) {
transform.rotate(m_shapeOptionsWidget->sldRotation->value());
qreal scale = m_shapeOptionsWidget->sldScale->value()*0.01;
transform.scale(scale, scale);
}
return transform;
}
qreal KisToolShape::currentStrokeWidth() const
{
const qreal sizeInPx =
......@@ -180,6 +220,7 @@ void KisToolShape::addShape(KoShape* shape)
QSharedPointer<KoPatternBackground> fill(new KoPatternBackground(imageCollection));
if (currentPattern()) {
fill->setPattern(currentPattern()->pattern());
fill->setTransform(fillTransform());
shape->setBackground(fill);
}
} else {
......@@ -243,7 +284,8 @@ void KisToolShape::addPathShape(KoPathShape* pathShape, const KUndo2MagicString&
node,
canvas()->resourceManager(),
strokeStyle(),
fillStyle());
fillStyle(),
fillTransform());
helper.paintPainterPath(mapedOutline);
} else if (node->inherits("KisShapeLayer")) {
pathShape->normalize();
......
......@@ -64,12 +64,15 @@ public Q_SLOTS:
void activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes) override;
virtual void outlineSettingChanged(int value);
virtual void fillSettingChanged(int value);
virtual void patternRotationSettingChanged(qreal value);
virtual void patternScaleSettingChanged(qreal value);
protected:
QWidget* createOptionWidget() override;
KisToolShapeUtils::FillStyle fillStyle();
KisToolShapeUtils::StrokeStyle strokeStyle();
QTransform fillTransform();
qreal currentStrokeWidth() const;
......
......@@ -66,7 +66,8 @@ void KisToolEllipse::finishRect(const QRectF& rect, qreal roundCornersX, qreal r
currentNode(),
canvas()->resourceManager(),
strokeStyle(),
fillStyle());
fillStyle(),
fillTransform());
helper.paintEllipse(rect);
} else {
QRectF r = convertToPt(rect);
......
......@@ -67,7 +67,8 @@ void KisToolRectangle::finishRect(const QRectF &rect, qreal roundCornersX, qreal
currentNode(),
canvas()->resourceManager(),
strokeStyle(),
fillStyle());
fillStyle(),
fillTransform());
QPainterPath path;
......
......@@ -59,7 +59,8 @@ void KisToolPolygon::finishPolyline(const QVector<QPointF>& points)
currentNode(),
canvas()->resourceManager(),
strokeStyle(),
fillStyle());
fillStyle(),
fillTransform());
helper.paintPolygon(points);
} else {
// remove the last point if it overlaps with the first
......
......@@ -63,7 +63,8 @@ void KisToolPolyline::finishPolyline(const QVector<QPointF>& points)
currentNode(),
canvas()->resourceManager(),
strokeStyle(),
fillStyle());
fillStyle(),
fillTransform());
helper.paintPolyline(points);
} else {
KoPathShape* path = new KoPathShape();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment