File indexing completed on 2024-04-28 05:41:34

0001 /*
0002     This file is part of KCachegrind.
0003 
0004     SPDX-FileCopyrightText: 2003-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
0005 
0006     SPDX-License-Identifier: GPL-2.0-only
0007 */
0008 
0009 /*
0010  * Some helper functions for QListViewItem derivates
0011  */
0012 
0013 #include "listutils.h"
0014 
0015 #include <QPainter>
0016 #include <QPixmap>
0017 
0018 #include "globalguiconfig.h"
0019 
0020 #define COSTPIX_WIDTH 25
0021 
0022 QPixmap colorPixmap(int w, int h, QColor c)
0023 {
0024     static QPixmap* pixs[37];
0025     static QColor cols[37];
0026     static bool inited = false;
0027 
0028     if (!inited) {
0029         for (int i=0;i<37;i++) pixs[i]=nullptr;
0030         inited = true;
0031     }
0032     int hash = (w+h+c.red()+c.green()+c.blue()) % 37;
0033     if (pixs[hash]) {
0034         if ((pixs[hash]->width() == w) &&
0035             (pixs[hash]->height() == h) &&
0036             (cols[hash] == c))
0037             return *pixs[hash];
0038 
0039         delete pixs[hash];
0040     }
0041 
0042 
0043     QPixmap* pix = new QPixmap(w, h);
0044     pix->fill(c);
0045     QPainter p(pix);
0046     p.setPen(c.lighter());
0047     p.drawLine(0, 0, w-1, 0);
0048     p.drawLine(0, 0, 0, h-1);
0049     p.setPen(c.darker());
0050     p.drawLine(w-1, 0, w-1, h-1);
0051     p.drawLine(0, h-1, w-1, h-1);
0052 
0053     pixs[hash] = pix;
0054     cols[hash] = c;
0055     return *pix;
0056 }
0057 
0058 /**
0059  * Create a percentage pixmap with a filling rate of p percent (0-100).
0060  * When withFrame==false, the pixmap is truncated to only the filled portion.
0061  */
0062 QPixmap percentagePixmap(int w, int h, int percent, QColor c, bool framed)
0063 {
0064     int iw, ix1, ih, iy1, iy2;
0065 
0066     // at max, draw 100%
0067     if (percent > 100) percent = 100;
0068 
0069     // inner rectangle to fill with bar
0070     if (framed) {
0071         iw = w-2, ix1 = 1;
0072         ih = h-2, iy1 = 1, iy2 = h-2;
0073     }
0074     else {
0075         iw = w; ix1 = 0;
0076         ih = h; iy1 = 0; iy2 = h-1;
0077     }
0078 
0079     int filled = iw*percent/100+1;
0080     if (!framed) w=filled;
0081     if (w<3) return QPixmap();
0082 
0083     QPixmap pix(w, h);
0084     pix.fill(Qt::white);
0085     QPainter p(&pix);
0086     p.setPen(Qt::black);
0087     if (framed)
0088         p.drawRect(0, 0, w-1, h-1);
0089 
0090     // inside
0091     p.setPen(Qt::NoPen);
0092     p.setBrush(c);
0093     p.drawRect(ix1, iy1, filled-1,ih-1);
0094 
0095     // last right pix column
0096     int lastY = ih-(filled*ih - iw*ih*percent/100);
0097     int lastX1 = ix1+filled-2 + ((lastY>1) ? 1: 0);
0098     int lastX2 = ix1+filled-2;
0099 
0100     // frame
0101     p.setPen(c.lighter());
0102     p.drawLine(ix1, iy1, lastX1, iy1);
0103     p.drawLine(ix1, iy1, ix1, iy2);
0104     p.setPen(c.darker());
0105     p.drawLine(lastX1, iy1, lastX1, iy1+lastY);
0106     p.drawLine(lastX2, iy1+lastY, lastX2, iy2);
0107     p.drawLine(ix1+1, iy2, lastX2, iy2);
0108 
0109     return pix;
0110 }
0111 
0112 inline QColor partitionColor(int d, int max)
0113 {
0114     return QColor::fromHsv((720*d/max) % 360, 255-(128*d/max), 192);
0115 }
0116 
0117 
0118 QPixmap partitionPixmap(int w, int h,
0119                         double* hist, EventTypeSet* set, int maxIndex, bool framed)
0120 {
0121     int lastPos = 0, nextPos;
0122     double val=0.0, sum=0.0;
0123     int d, dmin=maxIndex, dmax=0;
0124     for (d = 0;d<maxIndex;d++)
0125         if (hist[d]>0.0) {
0126             sum += hist[d];
0127             if (dmin>d) dmin = d;
0128             if (dmax<d) dmax = d;
0129         }
0130 
0131     // inner rectangle to fill with bar
0132     int iw, ix1, ih, iy1, iy2;
0133     if (framed) {
0134         iw = w-2, ix1 = 1;
0135         ih = h-2, iy1 = 1, iy2 = h-2;
0136     }
0137     else {
0138         iw = w; ix1 = 0;
0139         ih = h; iy1 = 0; iy2 = h-1;
0140     }
0141 
0142     int filled = (int)(iw*sum+1);
0143     if (!framed) w=filled;
0144     if (w<3) return QPixmap();
0145 
0146     QPixmap pix(w, h);
0147     pix.fill(Qt::white);
0148     QPainter p(&pix);
0149     p.setPen(Qt::black);
0150     if (framed)
0151         p.drawRect(0, 0, w-1, h-1);
0152 
0153     //qDebug("Sum %f, dw %d", sum,dw);
0154 
0155     QColor c, cLast;
0156     bool leftDrawn = false;
0157     int x1, x2=0;
0158     int diff;
0159     d=dmin;
0160     while (d<dmax+1) {
0161         val += hist[d];
0162         nextPos = (int)(filled * val/sum);
0163 
0164         //qDebug(" hist[%d] %f, val %f, nextPos %d", d, hist[d], val, nextPos);
0165 
0166         diff = nextPos-lastPos;
0167         if (diff==0) { d++; continue; }
0168 
0169         if (set)
0170             c = GlobalGUIConfig::eventTypeColor(set->realType(d));
0171         else
0172             c = partitionColor(d,maxIndex);
0173 
0174         x1 = ix1+lastPos;
0175         x2 = ix1+nextPos;
0176         if (x2>=iw) x2=iw-1;
0177 
0178         // inside
0179         p.setPen(Qt::NoPen);
0180         p.setBrush(c);
0181         p.drawRect(x1, iy1, x2-x1, ih-1);
0182 
0183         // lighter top border
0184         p.setPen(c.lighter());
0185         p.drawLine(x1, iy1, x2-1, iy1);
0186 
0187         // when width for last and current distance >2, draw full 3D effect...
0188         if (!leftDrawn) {
0189             p.drawLine(x1, iy1+1, x1, iy2);
0190             leftDrawn = true;
0191         }
0192 
0193         // darker bottom border
0194         p.setPen(c.darker());
0195         p.drawLine(x1, iy2, x2-1, iy2);
0196 
0197         lastPos = nextPos;
0198         cLast = c;
0199         d++;
0200     }
0201 
0202     // right border (in last color)
0203     if (x2>0)
0204         p.drawLine(x2, iy1, x2, iy2);
0205 
0206     return pix;
0207 }
0208 
0209 
0210 QPixmap costPixmap(EventType* ct, ProfileCostArray* cost,
0211                    double total, bool framed)
0212 {
0213     if (!ct) return QPixmap();
0214 
0215     if (ct->isReal()) {
0216         QColor color = GlobalGUIConfig::eventTypeColor(ct);
0217         double p = 100.0 * cost->subCost(ct) / total;
0218         return percentagePixmap(COSTPIX_WIDTH, 10, (int)(p+.5), color, framed);
0219     }
0220 
0221     int maxIndex;
0222     double h[MaxRealIndexValue];
0223     maxIndex = ct->histCost(cost, total, h);
0224 
0225     if (maxIndex ==0) return QPixmap();
0226     return partitionPixmap(COSTPIX_WIDTH, 10, h, ct->set(), maxIndex, framed);
0227 }
0228 
0229 
0230 
0231