File indexing completed on 2024-05-19 04:23:09
0001 0002 /* 0003 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0004 All rights reserved. 0005 0006 Redistribution and use in source and binary forms, with or without 0007 modification, are permitted provided that the following conditions 0008 are met: 0009 0010 1. Redistributions of source code must retain the above copyright 0011 notice, this list of conditions and the following disclaimer. 0012 2. Redistributions in binary form must reproduce the above copyright 0013 notice, this list of conditions and the following disclaimer in the 0014 documentation and/or other materials provided with the distribution. 0015 0016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0020 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0021 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0022 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0023 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0025 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0026 */ 0027 0028 0029 #define DEBUG_KP_COLOR_SIMILARITY_CUBE 0 0030 0031 0032 #include "kpColorSimilarityCubeRenderer.h" 0033 0034 #include <QtMath> 0035 0036 #include <QPainter> 0037 #include <QPolygonF> 0038 0039 #include "kpLogCategories.h" 0040 0041 #include "widgets/colorSimilarity/kpColorSimilarityHolder.h" 0042 #include "kpDefs.h" 0043 0044 //--------------------------------------------------------------------- 0045 0046 static QColor Color (int redOrGreenOrBlue, 0047 int baseBrightness, 0048 double colorSimilarity, 0049 int similarityDirection, 0050 int highlight) 0051 { 0052 int brightness = int (baseBrightness + 0053 similarityDirection * 0054 0.5 * colorSimilarity * kpColorSimilarityHolder::ColorCubeDiagonalDistance); 0055 0056 if (brightness < 0) { 0057 brightness = 0; 0058 } 0059 else if (brightness > 255) { 0060 brightness = 255; 0061 } 0062 0063 switch (redOrGreenOrBlue) 0064 { 0065 default: 0066 case 0: return {brightness, highlight, highlight}; 0067 case 1: return {highlight, brightness, highlight}; 0068 case 2: return {highlight, highlight, brightness}; 0069 } 0070 } 0071 0072 //--------------------------------------------------------------------- 0073 0074 static QPointF PointBetween(const QPointF &p, const QPointF &q) 0075 { 0076 return {(p.x() + q.x()) / 2.0, (p.y() + q.y()) / 2.0}; 0077 } 0078 0079 //--------------------------------------------------------------------- 0080 0081 static void DrawQuadrant(QPaintDevice *target, 0082 const QColor &col, 0083 const QPointF &p1, const QPointF &p2, const QPointF &p3, 0084 const QPointF &pointNotOnOutline) 0085 { 0086 QPolygonF points (4); 0087 points [0] = p1; 0088 points [1] = p2; 0089 points [2] = p3; 0090 points [3] = pointNotOnOutline; 0091 0092 QPainter p(target); 0093 p.setRenderHints(QPainter::Antialiasing, true); 0094 0095 // Polygon fill. 0096 p.setPen(col); 0097 p.setBrush(col); 0098 p.drawPolygon(points); 0099 0100 // do not draw a black border. It looks ugly 0101 } 0102 0103 //--------------------------------------------------------------------- 0104 0105 static void DrawFace (QPaintDevice *target, 0106 double colorSimilarity, 0107 int redOrGreenOrBlue, 0108 const QPointF &tl, const QPointF &tr, 0109 const QPointF &bl, const QPointF &br, 0110 int highlight) 0111 { 0112 #if DEBUG_KP_COLOR_SIMILARITY_CUBE 0113 qCDebug(kpLogWidgets) << "kpColorSimilarityCubeRenderer.cpp:DrawFace(RorGorB=" << redOrGreenOrBlue 0114 << ",tl=" << tl 0115 << ",tr=" << tr 0116 << ",bl=" << bl 0117 << ",br=" << br 0118 << ")" 0119 << endl; 0120 #endif 0121 0122 // tl --- tm --- tr 0123 // | | | 0124 // | | | 0125 // ml --- mm --- mr 0126 // | | | 0127 // | | | 0128 // bl --- bm --- br 0129 0130 const QPointF tm (::PointBetween (tl, tr)); 0131 const QPointF bm (::PointBetween (bl, br)); 0132 0133 const QPointF ml (::PointBetween (tl, bl)); 0134 const QPointF mr (::PointBetween (tr, br)); 0135 const QPointF mm (::PointBetween (ml, mr)); 0136 0137 0138 const int baseBrightness = 0139 qMax (127, 0140 255 - int (kpColorSimilarityHolder::MaxColorSimilarity * 0141 kpColorSimilarityHolder::ColorCubeDiagonalDistance / 2)); 0142 QColor colors [2] = 0143 { 0144 ::Color (redOrGreenOrBlue, baseBrightness, colorSimilarity, -1, highlight), 0145 ::Color (redOrGreenOrBlue, baseBrightness, colorSimilarity, +1, highlight) 0146 }; 0147 0148 #if DEBUG_KP_COLOR_SIMILARITY_CUBE 0149 qCDebug(kpLogWidgets) << "\tmaxColorSimilarity=" << kpColorSimilarityHolder::MaxColorSimilarity 0150 << " colorCubeDiagDist=" << kpColorSimilarityHolder::ColorCubeDiagonalDistance 0151 << "\n" 0152 << "\tbaseBrightness=" << baseBrightness 0153 << " color[0]=" << ((colors [0].rgba() & RGB_MASK) >> ((2 - redOrGreenOrBlue) * 8)) 0154 << " color[1]=" << ((colors [1].rgba() & RGB_MASK) >> ((2 - redOrGreenOrBlue) * 8)) 0155 << endl; 0156 #endif 0157 0158 0159 ::DrawQuadrant(target, colors [0], tm, tl, ml, mm); 0160 ::DrawQuadrant(target, colors [1], tm, tr, mr, mm); 0161 ::DrawQuadrant(target, colors [1], ml, bl, bm, mm); 0162 ::DrawQuadrant(target, colors [0], bm, br, mr, mm); 0163 } 0164 0165 //--------------------------------------------------------------------- 0166 0167 // public static 0168 void kpColorSimilarityCubeRenderer::Paint(QPaintDevice *target, 0169 int x, int y, int cubeRectSize, 0170 double colorSimilarity, 0171 int highlight) 0172 { 0173 Q_ASSERT (highlight >= 0 && highlight <= 255); 0174 0175 // 0176 // P------- Q --- --- 0177 // / / | | | 0178 // /A / | side | 0179 // R-------S T --- cubeRectSize 0180 // | | / / | 0181 // S | | / side | 0182 // U-------V --- --- 0183 // |-------| 0184 // side 0185 // |-----------| 0186 // cubeRectSize 0187 // 0188 // 0189 0190 const double angle = qDegreesToRadians (45.0); 0191 // S + S sin A = cubeRectSize 0192 // (1 + sin A) x S = cubeRectSize 0193 const double side = double(cubeRectSize) / (1.0 + std::sin(angle)); 0194 0195 0196 const QPointF pointP(x + (side * std::cos (angle)), 0197 y); 0198 const QPointF pointQ(x + cubeRectSize - 1, 0199 y); 0200 const QPointF pointR(x, 0201 y + (side * std::sin (angle))); 0202 const QPointF pointS(x + (side), 0203 y + (side * std::sin (angle))); 0204 const QPointF pointT(x + cubeRectSize - 1, 0205 y + (side)); 0206 const QPointF pointU(x, 0207 y + cubeRectSize - 1); 0208 const QPointF pointV(x + (side), 0209 y + cubeRectSize - 1); 0210 0211 0212 // Top Face 0213 ::DrawFace(target, 0214 colorSimilarity, 0/*red*/, 0215 pointP, pointQ, 0216 pointR, pointS, 0217 highlight); 0218 0219 0220 // Front Face 0221 ::DrawFace(target, 0222 colorSimilarity, 1/*green*/, 0223 pointR, pointS, 0224 pointU, pointV, 0225 highlight); 0226 0227 0228 // Right Face 0229 ::DrawFace(target, 0230 colorSimilarity, 2/*blue*/, 0231 pointS, pointQ, 0232 pointV, pointT, 0233 highlight); 0234 } 0235 0236 //---------------------------------------------------------------------