1 /*****************************************************************************
2  *   Copyright 2003 - 2010 Craig Drummond <craig.p.drummond@gmail.com>       *
3  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
4  *                                                                           *
5  *   This program is free software; you can redistribute it and/or modify    *
6  *   it under the terms of the GNU Lesser General Public License as          *
7  *   published by the Free Software Foundation; either version 2.1 of the    *
8  *   License, or (at your option) version 3, or any later version accepted   *
9  *   by the membership of KDE e.V. (or its successor approved by the         *
10  *   membership of KDE e.V.), which shall act as a proxy defined in          *
11  *   Section 6 of version 3 of the license.                                  *
12  *                                                                           *
13  *   This program is distributed in the hope that it will be useful,         *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
16  *   Lesser General Public License for more details.                         *
17  *                                                                           *
18  *   You should have received a copy of the GNU Lesser General Public        *
19  *   License along with this library. If not,                                *
20  *   see <http://www.gnu.org/licenses/>.                                     *
21  *****************************************************************************/
22 
23 #include "pixcache.h"
24 #include "check_on-png.h"
25 #include "check_x_on-png.h"
26 #include "blank16x16-png.h"
27 #include "qt_settings.h"
28 
29 #include <qtcurve-utils/gtkutils.h>
30 
31 #include <unordered_map>
32 
33 namespace QtCurve {
34 
35 struct PixKey {
36     GdkColor col;
37     double shade;
38 };
39 
40 struct PixHash {
41     size_t
operator ()QtCurve::PixHash42     operator()(const PixKey &key) const
43     {
44         const GdkColor &col = key.col;
45         return (std::hash<int>()(col.red) ^
46                 (std::hash<int>()(col.green) << 1) ^
47                 (std::hash<int>()(col.blue) << 2) ^
48                 (std::hash<double>()(key.shade) << 3));
49     }
50 };
51 
52 struct PixEqual {
53     bool
operator ()QtCurve::PixEqual54     operator()(const PixKey &lhs, const PixKey &rhs) const
55     {
56         return memcmp(&lhs, &rhs, sizeof(PixKey)) == 0;
57     }
58 };
59 
60 static std::unordered_map<PixKey, GObjPtr<GdkPixbuf>,
61                           PixHash, PixEqual> pixbufMap;
62 #pragma GCC diagnostic push
63 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
64 // Replacement isn't available until the version it is deprecated
65 // (gdk-pixbuf-2.0 2.32)
66 static GObjPtr<GdkPixbuf> blankPixbuf =
67     gdk_pixbuf_new_from_inline(-1, blank16x16, true, nullptr);
68 #pragma GCC diagnostic pop
69 
70 static GdkPixbuf*
pixbufCacheValueNew(const PixKey & key)71 pixbufCacheValueNew(const PixKey &key)
72 {
73 #pragma GCC diagnostic push
74 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
75     // Replacement isn't available until the version it is deprecated
76     // (gdk-pixbuf-2.0 2.32)
77     GdkPixbuf *res = gdk_pixbuf_new_from_inline(-1, opts.xCheck ? check_x_on :
78                                                 check_on, true, nullptr);
79 #pragma GCC diagnostic pop
80     qtcAdjustPix(gdk_pixbuf_get_pixels(res), gdk_pixbuf_get_n_channels(res),
81                  gdk_pixbuf_get_width(res), gdk_pixbuf_get_height(res),
82                  gdk_pixbuf_get_rowstride(res),
83                  key.col.red >> 8, key.col.green >> 8,
84                  key.col.blue >> 8, key.shade, QTC_PIXEL_GDK);
85     return res;
86 }
87 
88 GdkPixbuf*
getPixbuf(GdkColor * widgetColor,EPixmap p,double shade)89 getPixbuf(GdkColor *widgetColor, EPixmap p, double shade)
90 {
91     if (p != PIX_CHECK) {
92         return blankPixbuf.get();
93     }
94     const PixKey key = {*widgetColor, shade};
95     auto &pixbuf = pixbufMap[key];
96     if (pixbuf.get() == nullptr) {
97         pixbuf = pixbufCacheValueNew(key);
98     }
99     return pixbuf.get();
100 }
101 
102 }
103