File indexing completed on 2024-05-26 04:33:11
0001 /* 0002 * This file is part of Krita 0003 * 0004 * SPDX-FileCopyrightText: 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de> 0005 * 0006 * ported from Gimp, SPDX-FileCopyrightText: 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp> 0007 * original pixelize.c for GIMP 0.54 by Tracy Scott 0008 * 0009 * SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #include "kis_round_corners_filter.h" 0013 0014 #include <stdlib.h> 0015 #include <vector> 0016 #include <math.h> 0017 0018 #include <QPoint> 0019 0020 #include <klocalizedstring.h> 0021 #include <kpluginfactory.h> 0022 0023 #include <KoUpdater.h> 0024 0025 #include <kis_debug.h> 0026 #include <KisDocument.h> 0027 #include <filter/kis_filter_registry.h> 0028 #include <kis_global.h> 0029 #include <kis_image.h> 0030 #include <kis_layer.h> 0031 #include <widgets/kis_multi_integer_filter_widget.h> 0032 #include <kis_selection.h> 0033 #include <filter/kis_filter_category_ids.h> 0034 #include <filter/kis_filter_configuration.h> 0035 #include <kis_processing_information.h> 0036 #include <kis_types.h> 0037 #include <KisSequentialIteratorProgress.h> 0038 #include <kis_algebra_2d.h> 0039 #include <KoProgressUpdater.h> 0040 0041 0042 KisRoundCornersFilter::KisRoundCornersFilter() : KisFilter(id(), FiltersCategoryMapId, i18n("&Round Corners...")) 0043 { 0044 setSupportsPainting(false); 0045 0046 } 0047 0048 void fadeOneCorner(KisPaintDeviceSP device, 0049 const QPoint &basePoint, 0050 const QRect &processRect, 0051 const qreal thresholdSq, 0052 KoUpdater* progressUpdater) 0053 { 0054 const KoColorSpace *cs = device->colorSpace(); 0055 KisSequentialIteratorProgress dstIt(device, processRect, progressUpdater); 0056 0057 while (dstIt.nextPixel()) { 0058 const QPointF point(dstIt.x(), dstIt.y()); 0059 0060 const qreal distanceSq = kisSquareDistance(point, basePoint); 0061 if (distanceSq >= thresholdSq) { 0062 cs->setOpacity(dstIt.rawData(), OPACITY_TRANSPARENT_U8, 1); 0063 } 0064 } 0065 } 0066 0067 0068 void KisRoundCornersFilter::processImpl(KisPaintDeviceSP device, 0069 const QRect& applyRect, 0070 const KisFilterConfigurationSP config, 0071 KoUpdater* progressUpdater 0072 ) const 0073 { 0074 Q_UNUSED(config); 0075 Q_ASSERT(!device.isNull()); 0076 0077 if (!device || !config) { 0078 warnKrita << "Invalid parameters for round corner filter"; 0079 dbgPlugins << device << " " << config; 0080 return; 0081 } 0082 0083 const QRect bounds = device->defaultBounds()->imageBorderRect(); 0084 0085 const qint32 radius = qMin(KisAlgebra2D::minDimension(bounds) / 2, qMax(1, config->getInt("radius" , 30))); 0086 const qreal radiusSq = pow2(radius); 0087 0088 struct CornerJob { 0089 QRect rc; 0090 QPoint pt; 0091 KoUpdater *progressUpdater; 0092 }; 0093 0094 QVector<CornerJob> jobs; 0095 0096 KoProgressUpdater compositeUpdater(progressUpdater, KoProgressUpdater::Unthreaded); 0097 0098 { 0099 QRect rc(bounds.x(), bounds.y(), radius, radius); 0100 QPoint pt(rc.bottomRight()); 0101 jobs << CornerJob({rc, pt, compositeUpdater.startSubtask()}); 0102 } 0103 0104 { 0105 QRect rc(bounds.x() + bounds.width() - radius, bounds.y(), radius, radius); 0106 QPoint pt(rc.bottomLeft()); 0107 jobs << CornerJob({rc, pt, compositeUpdater.startSubtask()}); 0108 } 0109 0110 { 0111 QRect rc(bounds.x(), bounds.y() + bounds.height() - radius, radius, radius); 0112 QPoint pt(rc.topRight()); 0113 jobs << CornerJob({rc, pt, compositeUpdater.startSubtask()}); 0114 } 0115 0116 { 0117 QRect rc(bounds.x() + bounds.width() - radius, bounds.y() + bounds.height() - radius, radius, radius); 0118 QPoint pt(rc.topLeft()); 0119 jobs << CornerJob({rc, pt, compositeUpdater.startSubtask()}); 0120 } 0121 0122 Q_FOREACH (const CornerJob &job, jobs) { 0123 const QRect processRect = job.rc & applyRect; 0124 if (!processRect.isEmpty()) { 0125 fadeOneCorner(device, job.pt, processRect, radiusSq, job.progressUpdater); 0126 } 0127 } 0128 } 0129 0130 KisConfigWidget * KisRoundCornersFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP, bool) const 0131 { 0132 vKisIntegerWidgetParam param; 0133 param.push_back(KisIntegerWidgetParam(2, 100, 30, i18n("Radius"), "radius")); 0134 return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); 0135 0136 } 0137 0138 KisFilterConfigurationSP KisRoundCornersFilter::defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const 0139 { 0140 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface); 0141 config->setProperty("radius", 30); 0142 return config; 0143 }