1 /*
2  *  Copyright (c) 2014 Dmitry Kazakov <dimula73@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #ifndef __KIS_ACS_PIXEL_CACHE_RENDERER_H
20 #define __KIS_ACS_PIXEL_CACHE_RENDERER_H
21 
22 #include "KoColorSpace.h"
23 #include "kis_paint_device.h"
24 #include "kis_iterator_ng.h"
25 #include "kis_display_color_converter.h"
26 
27 
28 namespace Acs {
29 
30     class PixelCacheRenderer {
31     public:
32         /**
33          * \p Picker class must provide one method:
34          *     - KoColor Picker::colorAt(float x, float y);
35          *
36          * How to handle High DPI:
37          *  - pickRect - is in device independent pixels coordinates space
38          *     (amount of space on the widget)
39          *  - devicePixelRatioF - the amount of UI scaling
40          *  - pixelCache and realPixelCache gets the size of
41          *     pickRect.size()*devicePixelRatioF
42          *     and sets the device pixel ratio,
43          *     and color pickers need to take it into account.
44          *  That way you can paint on the cache the same way you'd paint on a low dpi display
45          *    and then just use painter->drawImage() and it works.
46          */
47         template <class Picker>
render(Picker * picker,const KisDisplayColorConverter * converter,const QRect & pickRect,KisPaintDeviceSP & realPixelCache,QImage & pixelCache,QPoint & pixelCacheOffset,qreal devicePixelRatioF)48         static void render(Picker *picker,
49                            const KisDisplayColorConverter *converter,
50                            const QRect &pickRect,
51                            KisPaintDeviceSP &realPixelCache,
52                            QImage &pixelCache,
53                            QPoint &pixelCacheOffset,
54                            qreal devicePixelRatioF)
55             {
56                 const KoColorSpace *cacheColorSpace = converter->paintingColorSpace();
57                 const int pixelSize = cacheColorSpace->pixelSize();
58 
59                 if (!realPixelCache || realPixelCache->colorSpace() != cacheColorSpace) {
60                     realPixelCache = new KisPaintDevice(cacheColorSpace);
61                 }
62 
63                 KoColor color;
64 
65                 QRect pickRectHighDPI = QRect(pickRect.topLeft(), pickRect.size()*devicePixelRatioF);
66                 KisSequentialIterator it(realPixelCache, pickRectHighDPI);
67 
68                 while (it.nextPixel()) {
69                     color = picker->colorAt(it.x()/devicePixelRatioF, it.y()/devicePixelRatioF);
70                     memcpy(it.rawData(), color.data(), pixelSize);
71                 }
72 
73 
74                 // NOTE: toQImage() function of the converter copies exactBounds() only!
75                 pixelCache = converter->toQImage(realPixelCache);
76                 pixelCache.setDevicePixelRatio(devicePixelRatioF);
77                 pixelCacheOffset = realPixelCache->exactBounds().topLeft()/devicePixelRatioF - pickRect.topLeft();
78         }
79     };
80 }
81 
82 #endif /* __KIS_ACS_PIXEL_CACHE_RENDERER_H */
83