File indexing completed on 2024-05-12 15:56:55

0001 /*
0002  *  SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_ACS_PIXEL_CACHE_RENDERER_H
0008 #define __KIS_ACS_PIXEL_CACHE_RENDERER_H
0009 
0010 #include "KoColorSpace.h"
0011 #include "kis_paint_device.h"
0012 #include "kis_iterator_ng.h"
0013 #include "kis_display_color_converter.h"
0014 
0015 
0016 namespace Acs {
0017 
0018     class PixelCacheRenderer {
0019     public:
0020         /**
0021          * \p Sampler class must provide one method:
0022          *     - KoColor Sampler::colorAt(float x, float y);
0023          *
0024          * How to handle High DPI:
0025          *  - sampleRect - is in device independent pixels coordinates space
0026          *     (amount of space on the widget)
0027          *  - devicePixelRatioF - the amount of UI scaling
0028          *  - pixelCache and realPixelCache gets the size of
0029          *     sampleRect.size()*devicePixelRatioF
0030          *     and sets the device pixel ratio,
0031          *     and color samplers need to take it into account.
0032          *  That way you can paint on the cache the same way you'd paint on a low dpi display
0033          *    and then just use painter->drawImage() and it works.
0034          */
0035         template <class Sampler>
0036         static void render(Sampler *sampler,
0037                            const KisDisplayColorConverter *converter,
0038                            const QRect &sampleRect,
0039                            KisPaintDeviceSP &realPixelCache,
0040                            QImage &pixelCache,
0041                            QPoint &pixelCacheOffset,
0042                            qreal devicePixelRatioF)
0043             {
0044                 const KoColorSpace *cacheColorSpace = converter->paintingColorSpace();
0045                 const int pixelSize = cacheColorSpace->pixelSize();
0046 
0047                 if (!realPixelCache || realPixelCache->colorSpace() != cacheColorSpace) {
0048                     realPixelCache = new KisPaintDevice(cacheColorSpace);
0049                 }
0050 
0051                 KoColor color;
0052 
0053                 QRect sampleRectHighDPI = QRect(sampleRect.topLeft(), sampleRect.size()*devicePixelRatioF);
0054                 KisSequentialIterator it(realPixelCache, sampleRectHighDPI);
0055 
0056                 while (it.nextPixel()) {
0057                     color = sampler->colorAt(it.x()/devicePixelRatioF, it.y()/devicePixelRatioF);
0058                     memcpy(it.rawData(), color.data(), pixelSize);
0059                 }
0060 
0061 
0062                 // NOTE: toQImage() function of the converter copies exactBounds() only!
0063                 pixelCache = converter->toQImage(realPixelCache);
0064                 pixelCache.setDevicePixelRatio(devicePixelRatioF);
0065                 pixelCacheOffset = realPixelCache->exactBounds().topLeft()/devicePixelRatioF - sampleRect.topLeft();
0066         }
0067     };
0068 }
0069 
0070 #endif /* __KIS_ACS_PIXEL_CACHE_RENDERER_H */