Loading files
a7147d491This file is pinned to the selected release. Download the original to open it in your design tool.
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
* Includes
******************************************************************************/
#include "overlinemarkupparser.h"
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
/*******************************************************************************
* Static Methods
******************************************************************************/
QVector<std::pair<int, int>> OverlineMarkupParser::extract(
const QString& input, QString& output) noexcept {
output.clear();
// Determine length of string without trailing '!'.
int inputLength = input.length();
while ((inputLength > 0) && (input.at(inputLength - 1) == '!')) {
--inputLength;
}
// Convert remaining '!' to overlines and '!!' to '!'.
QVector<std::pair<int, int>> spans;
int spanStart = -1;
for (int i = 0; i < inputLength; ++i) {
if (QStringView(input).mid(i, 2) == QLatin1String("!!")) {
// Substitutte '!!' by '!'.
output.append('!');
++i;
} else if (QStringView(input).mid(i, 2) == QLatin1String("!/")) {
// Do not end overline if '/' is prefixed with '!'.
if (spanStart < 0) {
spanStart = output.length();
}
output.append('/');
++i;
} else if ((spanStart < 0) && (input.at(i) == '!')) {
// Start overline on single '!'.
spanStart = output.length();
} else if ((spanStart >= 0) && (input.at(i) == '!')) {
// End overline on single '!'.
spans.append(std::make_pair(spanStart, output.length() - spanStart));
spanStart = -1;
} else if ((spanStart >= 0) && (input.at(i) == '/')) {
// End overline implicitly on '/'.
spans.append(std::make_pair(spanStart, output.length() - spanStart));
spanStart = -1;
output.append(input.at(i));
} else {
output.append(input.at(i));
}
}
// Append trailing '!' as-is.
while (inputLength < input.length()) {
output.append('!');
++inputLength;
}
// Finish current span.
if (spanStart >= 0) {
spans.append(std::make_pair(spanStart, output.length() - spanStart));
}
return spans;
}
QVector<QLineF> OverlineMarkupParser::calculate(
const QString& text, const QFontMetricsF& fm, int flags,
const QVector<std::pair<int, int>>& spans, QRectF& boundingRect) noexcept {
QVector<QLineF> overlines;
boundingRect = fm.boundingRect(QRectF(), flags | Qt::TextDontClip, text);
const qreal yBase = boundingRect.top() - fm.overlinePos();
foreach (const auto& span, spans) {
const QRectF prefixRect = fm.boundingRect(
QRectF(),
static_cast<int>(Qt::TextDontClip) | Qt::AlignBottom | Qt::AlignLeft,
text.left(span.first));
const QRectF suffixRect = fm.boundingRect(
QRectF(),
static_cast<int>(Qt::TextDontClip) | Qt::AlignBottom | Qt::AlignLeft,
text.mid(span.first + span.second));
overlines.append(QLineF(
boundingRect.left() + prefixRect.width(), yBase - prefixRect.top(),
boundingRect.right() - suffixRect.width(), yBase - prefixRect.top()));
}
return overlines;
}
void OverlineMarkupParser::process(const QString& input,
const QFontMetricsF& fm, int flags,
QString& output, QVector<QLineF>& overlines,
QRectF& boundingRect) noexcept {
const QVector<std::pair<int, int>> spans = extract(input, output);
overlines = calculate(output, fm, flags, spans, boundingRect);
}
qreal OverlineMarkupParser::getLineWidth(qreal heightPx) noexcept {
return heightPx / 15;
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace librepcb