...
 
Commits (2)
  • Boudewijn Rempt's avatar
    Check whether we are using the best-quality image on the clipboard · 09d3bdbe
    Boudewijn Rempt authored
    Firefox can put multiple versions of an image on the clipboard. From
    tests, there's always a fairly useless JPG, and sometimes a decent
    PNG, but of the formats it advertises, in my tests, only these two
    are present. It seems a bit timing dependent, in that if Krita is running,
    chances for getting the PNG clip are a bit better, but still not 100%.
    
    There's nothing more we can do that check whether we've got the best
    image type, in the order PNG, TIFF, BMP, JPEG, and use that.
    
    This is debug output that shows what's on the clipboard if we're lucky:
    
    Format "TIMESTAMP"
    Format "TARGETS"
    Format "MULTIPLE"
    Format "SAVE_TARGETS"
    Format "text/html"
    Format "text/_moz_htmlinfo"
    Format "text/_moz_htmlcontext"
    Format "image/png"
    data 290949 mime "image/png"
    Loaded image succesfully QImage::Format_ARGB32 true
    Format "image/bmp"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/bmp"
    Format "image/x-bmp"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/x-bmp"
    Format "image/x-MS-bmp"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/x-MS-bmp"
    Format "image/x-icon"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/x-icon"
    Format "image/x-ico"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/x-ico"
    Format "image/x-win-bitmap"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/x-win-bitmap"
    Format "image/vnd.microsoft.icon"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/vnd.microsoft.icon"
    Format "application/ico"
    Format "image/ico"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/ico"
    Format "image/icon"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/icon"
    Format "text/ico"
    Format "image/jpeg"
    data 33290 mime "image/jpeg"
    Loaded image succesfully QImage::Format_RGB32 false
    Format "image/tiff"
    data 0 mime "application/x-zerosize"
    Could not load image of type "image/tiff"
    Format "application/x-qt-image"
    Final QImage QImage::Format_ARGB32 true
    
    We cannot do more than this, so I'm closing
    
    BUG:406781
    09d3bdbe
  • Kuntal  Majumder's avatar
    Add pixel snap mode to canvas · 06c3c826
    Kuntal Majumder authored
    This patch adds a Pixel snap mode to the global snapping menu.
    Pixel snapping is just snapping to every next pixel, think of it
    as Grid Snapping with a Grid of 1px width and 0px offset.
    
    BUG:390952
    
    Reviewed By: @dkazakov
    Reference : kde/krita!9
    06c3c826
......@@ -114,6 +114,7 @@ xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0 http://www.kde.org
<text>&amp;Snap To</text>
<Action name="view_snap_to_guides"/>
<Action name="view_snap_to_grid"/>
<Action name="view_snap_to_pixel"/>
<Action name="view_snap_orthogonal" />
<Action name="view_snap_node" />
<Action name="view_snap_extension" />
......
......@@ -866,6 +866,17 @@
<statusTip></statusTip>
</Action>
<Action name="view_snap_to_pixel">
<icon></icon>
<text>Snap Pixel</text>
<whatsThis></whatsThis>
<toolTip>Snap Pixel</toolTip>
<iconText>Snap Pixel</iconText>
<activationFlags>1000</activationFlags>
<shortcut></shortcut>
<isCheckable>true</isCheckable>
<statusTip></statusTip>
</Action>
<Action name="view_snap_intersection">
<icon></icon>
<text>Snap Intersection</text>
......
......@@ -69,7 +69,8 @@ public:
GuideLineSnapping = 0x40,
DocumentBoundsSnapping = 0x80,
DocumentCenterSnapping = 0x100,
CustomSnapping = 0x200
CustomSnapping = 0x200,
PixelSnapping = 0x400
};
Q_DECLARE_FLAGS(Strategies, Strategy)
......
......@@ -43,6 +43,7 @@ set(kritaui_LIB_SRCS
canvas/kis_snap_config.cpp
canvas/kis_snap_line_strategy.cpp
canvas/KisSnapPointStrategy.cpp
canvas/KisSnapPixelStrategy.cpp
canvas/KisMirrorAxisConfig.cpp
dialogs/kis_about_application.cpp
dialogs/kis_dlg_adj_layer_props.cc
......
/*
* Copyright (c) 2019 Kuntal Majumder <hellozee@disroot.org>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1 of the License.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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 "KisSnapPixelStrategy.h"
#include <QPainterPath>
#include "kis_global.h"
#include "kis_canvas2.h"
#include "KoSnapProxy.h"
KisSnapPixelStrategy::KisSnapPixelStrategy(KoSnapGuide::Strategy type):
KoSnapStrategy(type)
{
}
KisSnapPixelStrategy::~KisSnapPixelStrategy()
{
}
bool KisSnapPixelStrategy::snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance)
{
Q_ASSERT(std::isfinite(maxSnapDistance));
KisCanvas2 *canvas2 = dynamic_cast<KisCanvas2*>(proxy->canvas());
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(canvas2, false);
QPointF spacing = canvas2->coordinatesConverter()->imageToDocument(QPointF(1,1));
// These are not my words but of Jan Hambrecht <jaham@gmx.net>
// And I have to trust them cause this works, :3
// The 1e-10 here is a workaround for some weird division problem.
// 360.00062366 / 2.83465058 gives 127 'exactly' when shown as a qreal,
// but when casting into an int, we get 126. In fact it's 127 - 5.64e-15 !
int col = static_cast<int>((mousePosition.x()) / spacing.x() + 1e-10);
int row = static_cast<int>((mousePosition.y()) / spacing.y() + 1e-10);
QPointF snappedPoint = QPointF(col * spacing.y(), row * spacing.x());
setSnappedPosition(snappedPoint);
return true;
}
QPainterPath KisSnapPixelStrategy::decoration(const KoViewConverter &converter) const
{
QSizeF unzoomedSize = converter.viewToDocument(QSizeF(5, 5));
QPainterPath decoration;
decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), 0));
decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), 0));
decoration.moveTo(snappedPosition() - QPointF(0, unzoomedSize.height()));
decoration.lineTo(snappedPosition() + QPointF(0, unzoomedSize.height()));
return decoration;
}
/*
* Copyright (c) 2019 Kuntal Majumder <hellozee@disroot.org>
*
* 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_SNAP_PIXEL_STRATEGY_H
#define __KIS_SNAP_PIXEL_STRATEGY_H
#include <QScopedPointer>
#include "KoSnapStrategy.h"
class KisSnapPixelStrategy : public KoSnapStrategy
{
public:
KisSnapPixelStrategy(KoSnapGuide::Strategy type = KoSnapGuide::PixelSnapping);
~KisSnapPixelStrategy() override;
bool snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance) override;
QPainterPath decoration(const KoViewConverter &converter) const override;
};
#endif /* __KIS_SNAP_PIXEL_STRATEGY_H */
......@@ -35,6 +35,7 @@
#include "kis_algebra_2d.h"
#include <KoSnapGuide.h>
#include "kis_snap_line_strategy.h"
#include "KisSnapPixelStrategy.h"
#include "kis_change_guides_command.h"
#include "kis_snap_config.h"
#include "kis_canvas2.h"
......@@ -211,6 +212,7 @@ void KisGuidesManager::syncActionsStatus()
m_d->syncAction("view_snap_bounding_box", m_d->snapConfig.boundingBox());
m_d->syncAction("view_snap_image_bounds", m_d->snapConfig.imageBounds());
m_d->syncAction("view_snap_image_center", m_d->snapConfig.imageCenter());
m_d->syncAction("view_snap_to_pixel",m_d->snapConfig.toPixel());
}
void KisGuidesManager::Private::updateSnappingStatus(const KisGuidesConfig &value)
......@@ -219,6 +221,7 @@ void KisGuidesManager::Private::updateSnappingStatus(const KisGuidesConfig &valu
KoSnapGuide *snapGuide = view->canvasBase()->snapGuide();
KisSnapLineStrategy *guidesSnap = 0;
KisSnapPixelStrategy *pixelSnap = new KisSnapPixelStrategy();
if (value.snapToGuides()) {
guidesSnap = new KisSnapLineStrategy(KoSnapGuide::GuideLineSnapping);
......@@ -229,6 +232,9 @@ void KisGuidesManager::Private::updateSnappingStatus(const KisGuidesConfig &valu
snapGuide->overrideSnapStrategy(KoSnapGuide::GuideLineSnapping, guidesSnap);
snapGuide->enableSnapStrategy(KoSnapGuide::GuideLineSnapping, guidesSnap);
snapGuide->overrideSnapStrategy(KoSnapGuide::PixelSnapping, pixelSnap);
snapGuide->enableSnapStrategy(KoSnapGuide::PixelSnapping, pixelSnap);
snapGuide->enableSnapStrategy(KoSnapGuide::OrthogonalSnapping, snapConfig.orthogonal());
snapGuide->enableSnapStrategy(KoSnapGuide::NodeSnapping, snapConfig.node());
snapGuide->enableSnapStrategy(KoSnapGuide::ExtensionSnapping, snapConfig.extension());
......@@ -236,6 +242,7 @@ void KisGuidesManager::Private::updateSnappingStatus(const KisGuidesConfig &valu
snapGuide->enableSnapStrategy(KoSnapGuide::BoundingBoxSnapping, snapConfig.boundingBox());
snapGuide->enableSnapStrategy(KoSnapGuide::DocumentBoundsSnapping, snapConfig.imageBounds());
snapGuide->enableSnapStrategy(KoSnapGuide::DocumentCenterSnapping, snapConfig.imageCenter());
snapGuide->enableSnapStrategy(KoSnapGuide::PixelSnapping, snapConfig.toPixel());
snapConfig.saveStaticData();
}
......@@ -332,6 +339,9 @@ void KisGuidesManager::setup(KisActionManager *actionManager)
action = actionManager->createAction("view_snap_image_center");
connect(action, SIGNAL(toggled(bool)), this, SLOT(setSnapImageCenter(bool)));
action = actionManager->createAction("view_snap_to_pixel");
connect(action, SIGNAL(toggled(bool)), this, SLOT(setSnapToPixel(bool)));
m_d->updateSnappingStatus(m_d->guidesConfig);
syncActionsStatus();
}
......@@ -746,6 +756,7 @@ void KisGuidesManager::slotShowSnapOptions()
menu.addSection(i18n("Snap to:"));
menu.addAction(m_d->createShortenedAction(i18n("Grid"), "view_snap_to_grid", &menu));
menu.addAction(m_d->createShortenedAction(i18n("Guides"), "view_snap_to_guides", &menu));
menu.addAction(m_d->createShortenedAction(i18n("Pixel"), "view_snap_to_pixel", &menu));
menu.addAction(m_d->createShortenedAction(i18n("Orthogonal"), "view_snap_orthogonal", &menu));
menu.addAction(m_d->createShortenedAction(i18n("Node"), "view_snap_node", &menu));
......@@ -800,3 +811,9 @@ void KisGuidesManager::setSnapImageCenter(bool value)
m_d->snapConfig.setImageCenter(value);
m_d->updateSnappingStatus(m_d->guidesConfig);
}
void KisGuidesManager::setSnapToPixel(bool value)
{
m_d->snapConfig.setToPixel(value);
m_d->updateSnappingStatus(m_d->guidesConfig);
}
......@@ -74,6 +74,7 @@ public Q_SLOTS:
void setSnapBoundingBox(bool value);
void setSnapImageBounds(bool value);
void setSnapImageCenter(bool value);
void setSnapToPixel(bool value);
void slotUploadConfigToDocument();
......
......@@ -27,7 +27,8 @@ KisSnapConfig::KisSnapConfig(bool loadValues)
m_intersection(false),
m_boundingBox(false),
m_imageBounds(true),
m_imageCenter(true)
m_imageCenter(true),
m_toPixel(false)
{
if (loadValues) {
loadStaticData();
......
......@@ -75,6 +75,13 @@ public:
m_imageCenter = value;
}
bool toPixel() const {
return m_toPixel;
}
void setToPixel(bool value) {
m_toPixel = value;
}
void saveStaticData() const;
void loadStaticData();
......@@ -86,6 +93,7 @@ private:
bool m_boundingBox;
bool m_imageBounds;
bool m_imageCenter;
bool m_toPixel;
};
#endif /* __KIS_SNAP_CONFIG_H */
......@@ -36,6 +36,8 @@
#include <KoColorSpaceRegistry.h>
#include <KoColorProfile.h>
#include <KisMimeDatabase.h>
// kritaimage
#include <kis_types.h>
#include <kis_paint_device.h>
......@@ -273,10 +275,76 @@ KisPaintDeviceSP KisClipboard::clip(const QRect &imageBounds, bool showPopup, Ki
}
if (!clip) {
QStringList formats = cb->mimeData()->formats();
QMap<int, QImage> qimages;
Q_FOREACH(const QString format, formats) {
// qDebug() << "Format" << format;
QImage image;
if (format.startsWith("image")) {
int priority = -1;
QByteArray ba = cb->mimeData()->data(format);
// qDebug() << "data" << ba.size() << "mime" << KisMimeDatabase::mimeTypeForData(ba);
if (ba.isEmpty()) {
continue;
}
QString qimageioFormat;
if (format == "image/png") {
qimageioFormat = "PNG";
priority = 0;
}
else if (format == "image/tiff") {
qimageioFormat = "TIFF";
priority = 1;
}
else if (format == "image/bmp"
|| format == "image/x-bmp"
|| format == "image/x-MS-bmp"
|| format == "image/x-win-bitmap") {
qimageioFormat = "BMP";
priority = 2;
}
else if (format == "image/jpeg") {
qimageioFormat = "JPG";
priority = 3;
}
if (!qimageioFormat.isEmpty()) {
image.loadFromData(ba, qimageioFormat.toLatin1());
}
if (!image.isNull()) {
// qDebug() << "Loaded image succesfully" << image.format() << image.hasAlphaChannel();
qimages[priority] = image;
}
// else {
// qDebug() << "Could not load image of type" << format;
// }
}
}
QImage qimage = cb->image();
if (qimage.isNull())
for(int i = 0; i < 4; i++) {
if (qimages.contains(i)) {
qimage = qimages[i];
break;
}
}
// qDebug() << "Final QImage" << qimage.format() << qimage.hasAlphaChannel();
if (qimage.isNull()) {
return KisPaintDeviceSP(0);
}
KisConfig cfg(true);
quint32 behaviour = cfg.pasteBehaviour();
......@@ -290,8 +358,6 @@ KisPaintDeviceSP KisClipboard::clip(const QRect &imageBounds, bool showPopup, Ki
dontPrompt.blockSignals(true);
mb.setWindowTitle(i18nc("@title:window", "Missing Color Profile"));
mb.setText(i18n("The image data you are trying to paste has no color profile information. How do you want to interpret these data? \n\n As Web (sRGB) - Use standard colors that are displayed from computer monitors. This is the most common way that images are stored. \n\nAs on Monitor - If you know a bit about color management and want to use your monitor to determine the color profile.\n\n"));
......@@ -301,8 +367,6 @@ KisPaintDeviceSP KisClipboard::clip(const QRect &imageBounds, bool showPopup, Ki
mb.addButton(i18n("Cancel"), QMessageBox::RejectRole);
mb.addButton(&dontPrompt, QMessageBox::ActionRole);
behaviour = mb.exec();
if (behaviour > 1) {
......@@ -350,15 +414,15 @@ void KisClipboard::clipboardDataChanged()
m_hasClip = false;
QClipboard *cb = QApplication::clipboard();
if (cb->mimeData()->hasImage()) {
QImage qimage = cb->image();
if (!qimage.isNull())
m_hasClip = true;
const QMimeData *cbData = cb->mimeData();
QByteArray mimeType("application/x-krita-selection");
if (cbData && cbData->hasFormat(mimeType))
m_hasClip = true;
if (!qimage.isNull())
m_hasClip = true;
}
}
if (m_hasClip) {
......
......@@ -853,6 +853,7 @@ void KisConfig::loadSnapConfig(KisSnapConfig *config, bool defaultValue) const
config->setBoundingBox(m_cfg.readEntry("globalSnapBoundingBox", defaultConfig.boundingBox()));
config->setImageBounds(m_cfg.readEntry("globalSnapImageBounds", defaultConfig.imageBounds()));
config->setImageCenter(m_cfg.readEntry("globalSnapImageCenter", defaultConfig.imageCenter()));
config->setToPixel(m_cfg.readEntry("globalSnapToPixel", defaultConfig.toPixel()));
}
void KisConfig::saveSnapConfig(const KisSnapConfig &config)
......@@ -864,6 +865,7 @@ void KisConfig::saveSnapConfig(const KisSnapConfig &config)
m_cfg.writeEntry("globalSnapBoundingBox", config.boundingBox());
m_cfg.writeEntry("globalSnapImageBounds", config.imageBounds());
m_cfg.writeEntry("globalSnapImageCenter", config.imageCenter());
m_cfg.writeEntry("globalSnapToPixel", config.toPixel());
}
qint32 KisConfig::checkSize(bool defaultValue) const
......