File indexing completed on 2024-04-14 03:55:15

0001 /*
0002     SPDX-FileCopyrightText: 2003-2005 Hamish Rodda <rodda@kde.org>
0003     SPDX-FileCopyrightText: 2007 Mirko Stocker <me@misto.ch>
0004     SPDX-FileCopyrightText: 2008 David Nolden <david.nolden.kdevelop@art-master.de>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "katerenderrange.h"
0010 
0011 #include <KColorUtils>
0012 
0013 void mergeAttributes(KTextEditor::Attribute::Ptr base, KTextEditor::Attribute::Ptr add)
0014 {
0015     if (!add) {
0016         return;
0017     }
0018 
0019     bool hadBg = base->hasProperty(KTextEditor::Attribute::BackgroundBrush);
0020     bool hasBg = add->hasProperty(KTextEditor::Attribute::BackgroundBrush);
0021 
0022     bool hadFg = base->hasProperty(KTextEditor::Attribute::ForegroundBrush);
0023     bool hasFg = add->hasProperty(KTextEditor::Attribute::ForegroundBrush);
0024 
0025     if (((!hadBg || !hasBg) && (!hadFg || !hasFg))) {
0026         // Nothing to blend
0027         *base += *add;
0028         return;
0029     }
0030 
0031     // We eventually have to blend
0032 
0033     QBrush baseBgBrush;
0034     QBrush baseFgBrush;
0035 
0036     if (hadBg) {
0037         baseBgBrush = base->background();
0038     }
0039 
0040     if (hadFg) {
0041         baseFgBrush = base->foreground();
0042     }
0043 
0044     *base += *add;
0045 
0046     if (hadBg && hasBg) {
0047         QBrush bg = add->background();
0048         if (!bg.isOpaque()) {
0049             QColor mixWithColor = bg.color();
0050             mixWithColor.setAlpha(255);
0051             bg.setColor(KColorUtils::mix(baseBgBrush.color(), mixWithColor, bg.color().alphaF()));
0052             base->setBackground(bg);
0053         }
0054     }
0055     if (hadFg && hasFg) {
0056         QBrush fg = add->foreground();
0057         if (!fg.isOpaque()) {
0058             QColor mixWithColor = fg.color();
0059             mixWithColor.setAlpha(255);
0060             fg.setColor(KColorUtils::mix(baseFgBrush.color(), mixWithColor, fg.color().alphaF()));
0061             base->setForeground(fg);
0062         }
0063     }
0064 }
0065 
0066 void NormalRenderRange::addRange(KTextEditor::Range range, KTextEditor::Attribute::Ptr attribute)
0067 {
0068     m_ranges.emplace_back(range, std::move(attribute));
0069 }
0070 
0071 KTextEditor::Cursor NormalRenderRange::nextBoundary() const
0072 {
0073     return m_nextBoundary;
0074 }
0075 
0076 bool NormalRenderRange::advanceTo(const KTextEditor::Cursor pos)
0077 {
0078     size_t index = m_currentRange;
0079     while (index < m_ranges.size()) {
0080         const auto &p = m_ranges[index];
0081         const auto &r = p.first;
0082         if (r.end() <= pos) {
0083             ++index;
0084         } else {
0085             bool ret = index != m_currentRange;
0086             m_currentRange = index;
0087 
0088             if (r.start() > pos) {
0089                 m_nextBoundary = r.start();
0090             } else {
0091                 m_nextBoundary = r.end();
0092             }
0093             if (r.contains(pos)) {
0094                 m_currentAttribute = p.second;
0095             } else {
0096                 m_currentAttribute.reset();
0097             }
0098 
0099             return ret;
0100         }
0101     }
0102 
0103     m_nextBoundary = KTextEditor::Cursor(INT_MAX, INT_MAX);
0104     m_currentAttribute.reset();
0105     return false;
0106 }
0107 
0108 KTextEditor::Attribute::Ptr NormalRenderRange::currentAttribute() const
0109 {
0110     return m_currentAttribute;
0111 }
0112 
0113 KTextEditor::Cursor RenderRangeVector::nextBoundary() const
0114 {
0115     KTextEditor::Cursor ret = m_currentPos;
0116     bool first = true;
0117     for (auto &r : m_ranges) {
0118         if (first) {
0119             ret = r.nextBoundary();
0120             first = false;
0121 
0122         } else {
0123             KTextEditor::Cursor nb = r.nextBoundary();
0124             if (ret > nb) {
0125                 ret = nb;
0126             }
0127         }
0128     }
0129     return ret;
0130 }
0131 
0132 NormalRenderRange &RenderRangeVector::pushNewRange()
0133 {
0134     m_ranges.push_back(NormalRenderRange());
0135     return m_ranges.back();
0136 }
0137 
0138 void RenderRangeVector::advanceTo(const KTextEditor::Cursor pos)
0139 {
0140     for (auto &r : m_ranges) {
0141         r.advanceTo(pos);
0142     }
0143 }
0144 
0145 bool RenderRangeVector::hasAttribute() const
0146 {
0147     for (auto &r : m_ranges) {
0148         if (r.currentAttribute()) {
0149             return true;
0150         }
0151     }
0152 
0153     return false;
0154 }
0155 
0156 KTextEditor::Attribute::Ptr RenderRangeVector::generateAttribute() const
0157 {
0158     KTextEditor::Attribute::Ptr a;
0159     bool ownsAttribute = false;
0160 
0161     for (auto &r : m_ranges) {
0162         if (KTextEditor::Attribute::Ptr a2 = r.currentAttribute()) {
0163             if (!a) {
0164                 a = a2;
0165             } else {
0166                 if (!ownsAttribute) {
0167                     // Make an own copy of the attribute..
0168                     ownsAttribute = true;
0169                     a = new KTextEditor::Attribute(*a);
0170                 }
0171                 mergeAttributes(a, a2);
0172             }
0173         }
0174     }
0175 
0176     return a;
0177 }