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 }