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 //---------------------------------------------------------------------