1 /*
2 * KDiff3 - Text Diff And Merge Tool
3 *
4 * SPDX-FileCopyrightText: 2002-2011 Joachim Eibl, joachim.eibl at gmx.de
5 * SPDX-FileCopyrightText: 2018-2020 Michael Reeves reeves.87@gmail.com
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "MergeFileInfos.h"
10
11 #include <QApplication>
12 #include <QIcon>
13 #include <QPainter>
14 #include <QPixmap>
15 #include <QStyle>
16
17 namespace PixMapUtils
18 {
19 namespace{
20 QPixmap* s_pm_dir = nullptr;
21 QPixmap* s_pm_file = nullptr;
22
23 QPixmap* pmNotThere;
24 QPixmap* pmNew = nullptr;
25 QPixmap* pmOld;
26 QPixmap* pmMiddle;
27
28 QPixmap* pmLink;
29
30 QPixmap* pmDirLink;
31 QPixmap* pmFileLink;
32
33 QPixmap* pmNewLink;
34 QPixmap* pmOldLink;
35 QPixmap* pmMiddleLink;
36
37 QPixmap* pmNewDir;
38 QPixmap* pmMiddleDir;
39 QPixmap* pmOldDir;
40
41 QPixmap* pmNewDirLink;
42 QPixmap* pmMiddleDirLink;
43 QPixmap* pmOldDirLink;
44 }
colorToPixmap(const QColor & inColor)45 QPixmap colorToPixmap(const QColor &inColor)
46 {
47 QPixmap pm(16, 16);
48 QPainter p(&pm);
49 p.setPen(Qt::black);
50 p.setBrush(inColor);
51 p.drawRect(0, 0, pm.width(), pm.height());
52 return pm;
53 }
54 // Copy pm2 onto pm1, but preserve the alpha value from pm1 where pm2 is transparent.
pixCombiner(const QPixmap * pm1,const QPixmap * pm2)55 QPixmap pixCombiner(const QPixmap* pm1, const QPixmap* pm2)
56 {
57 QImage img1 = pm1->toImage().convertToFormat(QImage::Format_ARGB32);
58 QImage img2 = pm2->toImage().convertToFormat(QImage::Format_ARGB32);
59
60 for(int y = 0; y < img1.height(); y++)
61 {
62 quint32* line1 = reinterpret_cast<quint32*>(img1.scanLine(y));
63 quint32* line2 = reinterpret_cast<quint32*>(img2.scanLine(y));
64 for(int x = 0; x < img1.width(); x++)
65 {
66 if(qAlpha(line2[x]) > 0)
67 line1[x] = (line2[x] | 0xff000000);
68 }
69 }
70 return QPixmap::fromImage(img1);
71 }
72
73 // like pixCombiner but let the pm1 color shine through
pixCombiner2(const QPixmap * pm1,const QPixmap * pm2)74 QPixmap pixCombiner2(const QPixmap* pm1, const QPixmap* pm2)
75 {
76 QPixmap pix = *pm1;
77 QPainter p(&pix);
78 p.setOpacity(0.5);
79 p.drawPixmap(0, 0, *pm2);
80 p.end();
81
82 return pix;
83 }
84
initPixmaps(const QColor & newest,const QColor & oldest,const QColor & middle,const QColor & notThere)85 void initPixmaps(const QColor& newest, const QColor& oldest, const QColor& middle, const QColor& notThere)
86 {
87 if(s_pm_dir == nullptr || s_pm_file == nullptr)
88 {
89 #include "xpm/file.xpm"
90 #include "xpm/folder.xpm"
91 const int smallIcon = qApp->style()->pixelMetric(QStyle::PM_SmallIconSize);
92 s_pm_dir = new QPixmap(QIcon::fromTheme(QStringLiteral("folder")).pixmap(smallIcon));
93 if(s_pm_dir->size() != QSize(16, 16))
94 {
95 delete s_pm_dir;
96 s_pm_dir = new QPixmap(folder_pm);
97 }
98 s_pm_file = new QPixmap(file_pm);
99 }
100
101 if(pmNew == nullptr)
102 {
103 #include "xpm/link_arrow.xpm"
104
105 pmNotThere = new QPixmap;
106 pmNew = new QPixmap;
107 pmOld = new QPixmap;
108 pmMiddle = new QPixmap;
109
110 pmLink = new QPixmap(link_arrow);
111
112 pmDirLink = new QPixmap;
113 pmFileLink = new QPixmap;
114
115 pmNewLink = new QPixmap;
116 pmOldLink = new QPixmap;
117 pmMiddleLink = new QPixmap;
118
119 pmNewDir = new QPixmap;
120 pmMiddleDir = new QPixmap;
121 pmOldDir = new QPixmap;
122
123 pmNewDirLink = new QPixmap;
124 pmMiddleDirLink = new QPixmap;
125 pmOldDirLink = new QPixmap;
126 }
127
128 *pmNotThere = colorToPixmap(notThere);
129 *pmNew = colorToPixmap(newest);
130 *pmOld = colorToPixmap(oldest);
131 *pmMiddle = colorToPixmap(middle);
132
133 *pmDirLink = pixCombiner(s_pm_dir, pmLink);
134 *pmFileLink = pixCombiner(s_pm_file, pmLink);
135
136 *pmNewLink = pixCombiner(pmNew, pmLink);
137 *pmOldLink = pixCombiner(pmOld, pmLink);
138 *pmMiddleLink = pixCombiner(pmMiddle, pmLink);
139
140 *pmNewDir = pixCombiner2(pmNew, s_pm_dir);
141 *pmMiddleDir = pixCombiner2(pmMiddle, s_pm_dir);
142 *pmOldDir = pixCombiner2(pmOld, s_pm_dir);
143
144 *pmNewDirLink = pixCombiner(pmNewDir, pmLink);
145 *pmMiddleDirLink = pixCombiner(pmMiddleDir, pmLink);
146 *pmOldDirLink = pixCombiner(pmOldDir, pmLink);
147 }
148
getOnePixmap(e_Age eAge,bool bLink,bool bDir)149 QPixmap getOnePixmap(e_Age eAge, bool bLink, bool bDir)
150 {
151 QPixmap* ageToPm[] = {pmNew, pmMiddle, pmOld, pmNotThere, s_pm_file};
152 QPixmap* ageToPmLink[] = {pmNewLink, pmMiddleLink, pmOldLink, pmNotThere, pmFileLink};
153 QPixmap* ageToPmDir[] = {pmNewDir, pmMiddleDir, pmOldDir, pmNotThere, s_pm_dir};
154 QPixmap* ageToPmDirLink[] = {pmNewDirLink, pmMiddleDirLink, pmOldDirLink, pmNotThere, pmDirLink};
155
156 QPixmap** ppPm = bDir ? (bLink ? ageToPmDirLink : ageToPmDir) : (bLink ? ageToPmLink : ageToPm);
157
158 return *ppPm[eAge];
159 }
160
161 } // namespace PixMapUtils
162