mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-20 20:06:12 +00:00
Fix non-integer Font Metrics in Graph (#1545)
This commit is contained in:
parent
61b0374a82
commit
ef22f20548
@ -1,84 +1,104 @@
|
|||||||
#ifndef CACHEDFONTMETRICS_H
|
#ifndef CACHEDFONTMETRICS_H
|
||||||
#define CACHEDFONTMETRICS_H
|
#define CACHEDFONTMETRICS_H
|
||||||
|
|
||||||
#include <QObject>
|
#include "common/Metrics.h"
|
||||||
#include <QFont>
|
|
||||||
#include <QFontMetrics>
|
#include <QObject>
|
||||||
|
#include <QFont>
|
||||||
class CachedFontMetrics : public QObject
|
#include <QFontMetrics>
|
||||||
{
|
|
||||||
Q_OBJECT
|
template<typename T>
|
||||||
public:
|
class CachedFontMetrics
|
||||||
explicit CachedFontMetrics(QObject *parent, const QFont &font)
|
{
|
||||||
: QObject(parent),
|
public:
|
||||||
mFontMetrics(font)
|
explicit CachedFontMetrics(const QFont &font)
|
||||||
{
|
: mFontMetrics(font)
|
||||||
memset(mWidths, 0, sizeof(mWidths));
|
{
|
||||||
mHeight = mFontMetrics.height();
|
memset(mWidths, 0, sizeof(mWidths));
|
||||||
}
|
mHeight = mFontMetrics.height();
|
||||||
|
}
|
||||||
int width(const QChar &ch)
|
|
||||||
{
|
T width(const QChar &ch)
|
||||||
auto unicode = ch.unicode();
|
{
|
||||||
if (unicode >= 0xD800) {
|
//return mFontMetrics.width(ch);
|
||||||
if (unicode >= 0xE000)
|
auto unicode = ch.unicode();
|
||||||
unicode -= 0xE000 - 0xD800;
|
if (unicode >= 0xD800) {
|
||||||
else
|
if (unicode >= 0xE000)
|
||||||
// is lonely surrogate
|
unicode -= 0xE000 - 0xD800;
|
||||||
return mFontMetrics.width(ch);
|
else
|
||||||
}
|
// is lonely surrogate
|
||||||
if (!mWidths[unicode])
|
return fetchWidth(ch);
|
||||||
return mWidths[unicode] = mFontMetrics.width(ch);
|
}
|
||||||
return mWidths[unicode];
|
if (!mWidths[unicode])
|
||||||
}
|
return mWidths[unicode] = fetchWidth(ch);
|
||||||
|
return mWidths[unicode];
|
||||||
int width(const QString &text)
|
}
|
||||||
{
|
|
||||||
int result = 0;
|
T width(const QString &text)
|
||||||
QChar temp;
|
{
|
||||||
for (const QChar &ch : text) {
|
T result = 0;
|
||||||
if (ch.isHighSurrogate())
|
QChar temp;
|
||||||
temp = ch;
|
for (const QChar &ch : text) {
|
||||||
else if (ch.isLowSurrogate())
|
if (ch.isHighSurrogate())
|
||||||
result += mFontMetrics.width(QString(temp) + ch);
|
temp = ch;
|
||||||
else
|
else if (ch.isLowSurrogate())
|
||||||
result += width(ch);
|
result += fetchWidth(QString(temp) + ch);
|
||||||
}
|
else
|
||||||
return result;
|
result += width(ch);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
int height()
|
}
|
||||||
{
|
|
||||||
return mHeight;
|
T height()
|
||||||
}
|
{
|
||||||
|
return mHeight;
|
||||||
int position(const QString &text, int offset)
|
}
|
||||||
{
|
|
||||||
int curWidth = 0;
|
T position(const QString &text, T offset)
|
||||||
QChar temp;
|
{
|
||||||
|
T curWidth = 0;
|
||||||
for (int i = 0; i < text.length(); i++) {
|
QChar temp;
|
||||||
QChar ch = text[i];
|
|
||||||
|
for (int i = 0; i < text.length(); i++) {
|
||||||
if (ch.isHighSurrogate())
|
QChar ch = text[i];
|
||||||
temp = ch;
|
|
||||||
else if (ch.isLowSurrogate())
|
if (ch.isHighSurrogate())
|
||||||
curWidth += mFontMetrics.width(QString(temp) + ch);
|
temp = ch;
|
||||||
else
|
else if (ch.isLowSurrogate())
|
||||||
curWidth += width(ch);
|
curWidth += fetchWidth(QString(temp) + ch);
|
||||||
|
else
|
||||||
if (curWidth >= offset) {
|
curWidth += width(ch);
|
||||||
return i;
|
|
||||||
}
|
if (curWidth >= offset) {
|
||||||
}
|
return i;
|
||||||
|
}
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
return -1;
|
||||||
private:
|
}
|
||||||
QFontMetrics mFontMetrics;
|
|
||||||
uchar mWidths[0x10000 - 0xE000 + 0xD800];
|
private:
|
||||||
int mHeight;
|
typename Metrics<T>::FontMetrics mFontMetrics;
|
||||||
};
|
T mWidths[0x10000 - 0xE000 + 0xD800];
|
||||||
|
T mHeight;
|
||||||
#endif // CACHEDFONTMETRICS_H
|
|
||||||
|
T fetchWidth(QChar c)
|
||||||
|
{
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
|
||||||
|
return mFontMetrics.width(c);
|
||||||
|
#else
|
||||||
|
return mFontMetrics.horizontalAdvance(c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
T fetchWidth(const QString &s)
|
||||||
|
{
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
|
||||||
|
return mFontMetrics.width(s);
|
||||||
|
#else
|
||||||
|
return mFontMetrics.horizontalAdvance(s);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CACHEDFONTMETRICS_H
|
||||||
|
26
src/common/Metrics.h
Normal file
26
src/common/Metrics.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#ifndef METRICS_H
|
||||||
|
#define METRICS_H
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
class QRect;
|
||||||
|
class QRectF;
|
||||||
|
class QFontMetrics;
|
||||||
|
class QFontMetricsF;
|
||||||
|
|
||||||
|
template<typename T> struct Metrics {};
|
||||||
|
|
||||||
|
template<> struct Metrics<int>
|
||||||
|
{
|
||||||
|
using Rect = QRect;
|
||||||
|
using FontMetrics = QFontMetrics;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct Metrics<qreal>
|
||||||
|
{
|
||||||
|
using Rect = QRectF;
|
||||||
|
using FontMetrics = QFontMetricsF;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //METRICS_H
|
@ -1,188 +1,196 @@
|
|||||||
/* x64dbg RichTextPainter */
|
/* x64dbg RichTextPainter */
|
||||||
#include "RichTextPainter.h"
|
#include "RichTextPainter.h"
|
||||||
#include "CachedFontMetrics.h"
|
#include "CachedFontMetrics.h"
|
||||||
#include "common/Configuration.h"
|
#include "common/Configuration.h"
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
#include <QTextFragment>
|
#include <QTextFragment>
|
||||||
|
|
||||||
//TODO: fix performance (possibly use QTextLayout?)
|
//TODO: fix performance (possibly use QTextLayout?)
|
||||||
void RichTextPainter::paintRichText(QPainter *painter, int x, int y, int w, int h, int xinc,
|
|
||||||
const List &richText, CachedFontMetrics *fontMetrics)
|
|
||||||
{
|
template<typename T>
|
||||||
QPen pen;
|
void RichTextPainter::paintRichText(QPainter *painter, T x, T y, T w, T h, T xinc,
|
||||||
QPen highlightPen;
|
const List &richText, CachedFontMetrics<T> *fontMetrics)
|
||||||
QBrush brush(Qt::cyan);
|
{
|
||||||
for (const CustomRichText_t &curRichText : richText) {
|
QPen pen;
|
||||||
int textWidth = fontMetrics->width(curRichText.text);
|
QPen highlightPen;
|
||||||
int backgroundWidth = textWidth;
|
QBrush brush(Qt::cyan);
|
||||||
if (backgroundWidth + xinc > w)
|
for (const CustomRichText_t &curRichText : richText) {
|
||||||
backgroundWidth = w - xinc;
|
T textWidth = fontMetrics->width(curRichText.text);
|
||||||
if (backgroundWidth <= 0) //stop drawing when going outside the specified width
|
T backgroundWidth = textWidth;
|
||||||
break;
|
if (backgroundWidth + xinc > w)
|
||||||
switch (curRichText.flags) {
|
backgroundWidth = w - xinc;
|
||||||
case FlagNone: //defaults
|
if (backgroundWidth <= 0) //stop drawing when going outside the specified width
|
||||||
pen.setColor(ConfigColor("btext").name());
|
break;
|
||||||
painter->setPen(pen);
|
switch (curRichText.flags) {
|
||||||
break;
|
case FlagNone: //defaults
|
||||||
case FlagColor: //color only
|
pen.setColor(ConfigColor("btext").name());
|
||||||
pen.setColor(curRichText.textColor);
|
painter->setPen(pen);
|
||||||
painter->setPen(pen);
|
break;
|
||||||
break;
|
case FlagColor: //color only
|
||||||
case FlagBackground: //background only
|
pen.setColor(curRichText.textColor);
|
||||||
if (backgroundWidth > 0 && curRichText.textBackground.alpha()) {
|
painter->setPen(pen);
|
||||||
brush.setColor(curRichText.textBackground);
|
break;
|
||||||
painter->fillRect(QRect(x + xinc, y, backgroundWidth, h), brush);
|
case FlagBackground: //background only
|
||||||
}
|
if (backgroundWidth > 0 && curRichText.textBackground.alpha()) {
|
||||||
break;
|
brush.setColor(curRichText.textBackground);
|
||||||
case FlagAll: //color+background
|
painter->fillRect(QRectF(x + xinc, y, backgroundWidth, h), brush);
|
||||||
if (backgroundWidth > 0 && curRichText.textBackground.alpha()) {
|
}
|
||||||
brush.setColor(curRichText.textBackground);
|
break;
|
||||||
painter->fillRect(QRect(x + xinc, y, backgroundWidth, h), brush);
|
case FlagAll: //color+background
|
||||||
}
|
if (backgroundWidth > 0 && curRichText.textBackground.alpha()) {
|
||||||
pen.setColor(curRichText.textColor);
|
brush.setColor(curRichText.textBackground);
|
||||||
painter->setPen(pen);
|
painter->fillRect(QRectF(x + xinc, y, backgroundWidth, h), brush);
|
||||||
break;
|
}
|
||||||
}
|
pen.setColor(curRichText.textColor);
|
||||||
painter->drawText(QRect(x + xinc, y, w - xinc, h), Qt::TextBypassShaping, curRichText.text);
|
painter->setPen(pen);
|
||||||
if (curRichText.highlight && curRichText.highlightColor.alpha()) {
|
break;
|
||||||
highlightPen.setColor(curRichText.highlightColor);
|
}
|
||||||
highlightPen.setWidth(curRichText.highlightWidth);
|
painter->drawText(typename Metrics<T>::Rect(x + xinc, y, w - xinc, h), Qt::TextBypassShaping, curRichText.text);
|
||||||
painter->setPen(highlightPen);
|
if (curRichText.highlight && curRichText.highlightColor.alpha()) {
|
||||||
int highlightOffsetX = curRichText.highlightConnectPrev ? -1 : 1;
|
highlightPen.setColor(curRichText.highlightColor);
|
||||||
painter->drawLine(x + xinc + highlightOffsetX, y + h - 1, x + xinc + backgroundWidth - 1,
|
highlightPen.setWidth(curRichText.highlightWidth);
|
||||||
y + h - 1);
|
painter->setPen(highlightPen);
|
||||||
}
|
T highlightOffsetX = curRichText.highlightConnectPrev ? -1 : 1;
|
||||||
xinc += textWidth;
|
painter->drawLine(x + xinc + highlightOffsetX, y + h - 1, x + xinc + backgroundWidth - 1,
|
||||||
}
|
y + h - 1);
|
||||||
}
|
}
|
||||||
|
xinc += textWidth;
|
||||||
/**
|
}
|
||||||
* @brief RichTextPainter::htmlRichText Convert rich text in x64dbg to HTML, for use by other applications
|
}
|
||||||
* @param richText The rich text to be converted to HTML format
|
|
||||||
* @param textHtml The HTML source. Any previous content will be preserved and new content will be appended at the end.
|
template
|
||||||
* @param textPlain The plain text. Any previous content will be preserved and new content will be appended at the end.
|
void RichTextPainter::paintRichText<qreal>(QPainter *painter, qreal x, qreal y, qreal w, qreal h, qreal xinc,
|
||||||
*/
|
const List &richText, CachedFontMetrics<qreal> *fontMetrics);
|
||||||
void RichTextPainter::htmlRichText(const List &richText, QString &textHtml, QString &textPlain)
|
|
||||||
{
|
|
||||||
for (const CustomRichText_t &curRichText : richText) {
|
/**
|
||||||
if (curRichText.text == " ") { //blank
|
* @brief RichTextPainter::htmlRichText Convert rich text in x64dbg to HTML, for use by other applications
|
||||||
textHtml += " ";
|
* @param richText The rich text to be converted to HTML format
|
||||||
textPlain += " ";
|
* @param textHtml The HTML source. Any previous content will be preserved and new content will be appended at the end.
|
||||||
continue;
|
* @param textPlain The plain text. Any previous content will be preserved and new content will be appended at the end.
|
||||||
}
|
*/
|
||||||
switch (curRichText.flags) {
|
void RichTextPainter::htmlRichText(const List &richText, QString &textHtml, QString &textPlain)
|
||||||
case FlagNone: //defaults
|
{
|
||||||
textHtml += "<span>";
|
for (const CustomRichText_t &curRichText : richText) {
|
||||||
break;
|
if (curRichText.text == " ") { //blank
|
||||||
case FlagColor: //color only
|
textHtml += " ";
|
||||||
textHtml += QString("<span style=\"color:%1\">").arg(curRichText.textColor.name());
|
textPlain += " ";
|
||||||
break;
|
continue;
|
||||||
case FlagBackground: //background only
|
}
|
||||||
if (curRichText.textBackground !=
|
switch (curRichText.flags) {
|
||||||
Qt::transparent) // QColor::name() returns "#000000" for transparent color. That's not desired. Leave it blank.
|
case FlagNone: //defaults
|
||||||
textHtml += QString("<span style=\"background-color:%1\">").arg(curRichText.textBackground.name());
|
textHtml += "<span>";
|
||||||
else
|
break;
|
||||||
textHtml += QString("<span>");
|
case FlagColor: //color only
|
||||||
break;
|
textHtml += QString("<span style=\"color:%1\">").arg(curRichText.textColor.name());
|
||||||
case FlagAll: //color+background
|
break;
|
||||||
if (curRichText.textBackground !=
|
case FlagBackground: //background only
|
||||||
Qt::transparent) // QColor::name() returns "#000000" for transparent color. That's not desired. Leave it blank.
|
if (curRichText.textBackground !=
|
||||||
textHtml += QString("<span style=\"color:%1; background-color:%2\">").arg(
|
Qt::transparent) // QColor::name() returns "#000000" for transparent color. That's not desired. Leave it blank.
|
||||||
curRichText.textColor.name(), curRichText.textBackground.name());
|
textHtml += QString("<span style=\"background-color:%1\">").arg(curRichText.textBackground.name());
|
||||||
else
|
else
|
||||||
textHtml += QString("<span style=\"color:%1\">").arg(curRichText.textColor.name());
|
textHtml += QString("<span>");
|
||||||
break;
|
break;
|
||||||
}
|
case FlagAll: //color+background
|
||||||
if (curRichText.highlight) //Underline highlighted token
|
if (curRichText.textBackground !=
|
||||||
textHtml += "<u>";
|
Qt::transparent) // QColor::name() returns "#000000" for transparent color. That's not desired. Leave it blank.
|
||||||
textHtml += curRichText.text.toHtmlEscaped();
|
textHtml += QString("<span style=\"color:%1; background-color:%2\">").arg(
|
||||||
if (curRichText.highlight)
|
curRichText.textColor.name(), curRichText.textBackground.name());
|
||||||
textHtml += "</u>";
|
else
|
||||||
textHtml += "</span>"; //Close the tag
|
textHtml += QString("<span style=\"color:%1\">").arg(curRichText.textColor.name());
|
||||||
textPlain += curRichText.text;
|
break;
|
||||||
}
|
}
|
||||||
}
|
if (curRichText.highlight) //Underline highlighted token
|
||||||
|
textHtml += "<u>";
|
||||||
RichTextPainter::List RichTextPainter::fromTextDocument(const QTextDocument &doc)
|
textHtml += curRichText.text.toHtmlEscaped();
|
||||||
{
|
if (curRichText.highlight)
|
||||||
List r;
|
textHtml += "</u>";
|
||||||
|
textHtml += "</span>"; //Close the tag
|
||||||
for (QTextBlock block = doc.begin(); block != doc.end(); block = block.next()) {
|
textPlain += curRichText.text;
|
||||||
for (QTextBlock::iterator it = block.begin(); it != block.end(); ++it) {
|
}
|
||||||
QTextFragment fragment = it.fragment();
|
}
|
||||||
QTextCharFormat format = fragment.charFormat();
|
|
||||||
|
RichTextPainter::List RichTextPainter::fromTextDocument(const QTextDocument &doc)
|
||||||
CustomRichText_t text;
|
{
|
||||||
text.text = fragment.text();
|
List r;
|
||||||
text.textColor = format.foreground().color();
|
|
||||||
text.textBackground = format.background().color();
|
for (QTextBlock block = doc.begin(); block != doc.end(); block = block.next()) {
|
||||||
|
for (QTextBlock::iterator it = block.begin(); it != block.end(); ++it) {
|
||||||
bool hasForeground = format.hasProperty(QTextFormat::ForegroundBrush);
|
QTextFragment fragment = it.fragment();
|
||||||
bool hasBackground = format.hasProperty(QTextFormat::BackgroundBrush);
|
QTextCharFormat format = fragment.charFormat();
|
||||||
|
|
||||||
if (hasForeground && !hasBackground) {
|
CustomRichText_t text;
|
||||||
text.flags = FlagColor;
|
text.text = fragment.text();
|
||||||
} else if (!hasForeground && hasBackground) {
|
text.textColor = format.foreground().color();
|
||||||
text.flags = FlagBackground;
|
text.textBackground = format.background().color();
|
||||||
} else if (hasForeground && hasBackground) {
|
|
||||||
text.flags = FlagAll;
|
bool hasForeground = format.hasProperty(QTextFormat::ForegroundBrush);
|
||||||
} else {
|
bool hasBackground = format.hasProperty(QTextFormat::BackgroundBrush);
|
||||||
text.flags = FlagNone;
|
|
||||||
}
|
if (hasForeground && !hasBackground) {
|
||||||
|
text.flags = FlagColor;
|
||||||
r.push_back(text);
|
} else if (!hasForeground && hasBackground) {
|
||||||
}
|
text.flags = FlagBackground;
|
||||||
}
|
} else if (hasForeground && hasBackground) {
|
||||||
|
text.flags = FlagAll;
|
||||||
return r;
|
} else {
|
||||||
}
|
text.flags = FlagNone;
|
||||||
|
}
|
||||||
RichTextPainter::List RichTextPainter::cropped(const RichTextPainter::List &richText, int maxCols,
|
|
||||||
const QString &indicator, bool *croppedOut)
|
r.push_back(text);
|
||||||
{
|
}
|
||||||
List r;
|
}
|
||||||
r.reserve(richText.size());
|
|
||||||
|
return r;
|
||||||
int cols = 0;
|
}
|
||||||
bool cropped = false;
|
|
||||||
for (const auto &text : richText) {
|
RichTextPainter::List RichTextPainter::cropped(const RichTextPainter::List &richText, int maxCols,
|
||||||
int textLength = text.text.size();
|
const QString &indicator, bool *croppedOut)
|
||||||
if (cols + textLength <= maxCols) {
|
{
|
||||||
r.push_back(text);
|
List r;
|
||||||
cols += textLength;
|
r.reserve(richText.size());
|
||||||
} else if (cols == maxCols) {
|
|
||||||
break;
|
int cols = 0;
|
||||||
} else {
|
bool cropped = false;
|
||||||
CustomRichText_t croppedText = text;
|
for (const auto &text : richText) {
|
||||||
croppedText.text.truncate(maxCols - cols);
|
int textLength = text.text.size();
|
||||||
r.push_back(croppedText);
|
if (cols + textLength <= maxCols) {
|
||||||
cropped = true;
|
r.push_back(text);
|
||||||
break;
|
cols += textLength;
|
||||||
}
|
} else if (cols == maxCols) {
|
||||||
}
|
break;
|
||||||
|
} else {
|
||||||
if (cropped && !indicator.isEmpty()) {
|
CustomRichText_t croppedText = text;
|
||||||
int indicatorCropLength = indicator.length();
|
croppedText.text.truncate(maxCols - cols);
|
||||||
if (indicatorCropLength > maxCols) {
|
r.push_back(croppedText);
|
||||||
indicatorCropLength = maxCols;
|
cropped = true;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
while (!r.empty()) {
|
}
|
||||||
auto &text = r.back();
|
|
||||||
|
if (cropped && !indicator.isEmpty()) {
|
||||||
if (text.text.length() >= indicatorCropLength) {
|
int indicatorCropLength = indicator.length();
|
||||||
text.text.replace(text.text.length() - indicatorCropLength, indicatorCropLength, indicator);
|
if (indicatorCropLength > maxCols) {
|
||||||
break;
|
indicatorCropLength = maxCols;
|
||||||
}
|
}
|
||||||
|
|
||||||
indicatorCropLength -= text.text.length();
|
while (!r.empty()) {
|
||||||
r.pop_back();
|
auto &text = r.back();
|
||||||
}
|
|
||||||
}
|
if (text.text.length() >= indicatorCropLength) {
|
||||||
|
text.text.replace(text.text.length() - indicatorCropLength, indicatorCropLength, indicator);
|
||||||
if (croppedOut) {
|
break;
|
||||||
*croppedOut = cropped;
|
}
|
||||||
}
|
|
||||||
return r;
|
indicatorCropLength -= text.text.length();
|
||||||
}
|
r.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (croppedOut) {
|
||||||
|
*croppedOut = cropped;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
@ -1,48 +1,52 @@
|
|||||||
/* x64dbg RichTextPainter */
|
/* x64dbg RichTextPainter */
|
||||||
#ifndef RICHTEXTPAINTER_H
|
#ifndef RICHTEXTPAINTER_H
|
||||||
#define RICHTEXTPAINTER_H
|
#define RICHTEXTPAINTER_H
|
||||||
|
|
||||||
#include <QString>
|
#include "common/Metrics.h"
|
||||||
#include <QTextDocument>
|
|
||||||
#include <QColor>
|
#include <QString>
|
||||||
#include <vector>
|
#include <QTextDocument>
|
||||||
|
#include <QColor>
|
||||||
class CachedFontMetrics;
|
#include <vector>
|
||||||
class QPainter;
|
|
||||||
|
class QFontMetricsF;
|
||||||
class RichTextPainter
|
template<typename T> class CachedFontMetrics;
|
||||||
{
|
class QPainter;
|
||||||
public:
|
|
||||||
//structures
|
class RichTextPainter
|
||||||
enum CustomRichTextFlags {
|
{
|
||||||
FlagNone,
|
public:
|
||||||
FlagColor,
|
//structures
|
||||||
FlagBackground,
|
enum CustomRichTextFlags {
|
||||||
FlagAll
|
FlagNone,
|
||||||
};
|
FlagColor,
|
||||||
|
FlagBackground,
|
||||||
struct CustomRichText_t {
|
FlagAll
|
||||||
QString text;
|
};
|
||||||
QColor textColor;
|
|
||||||
QColor textBackground;
|
struct CustomRichText_t {
|
||||||
CustomRichTextFlags flags;
|
QString text;
|
||||||
bool highlight = false;
|
QColor textColor;
|
||||||
QColor highlightColor;
|
QColor textBackground;
|
||||||
int highlightWidth = 2;
|
CustomRichTextFlags flags;
|
||||||
bool highlightConnectPrev = false;
|
bool highlight = false;
|
||||||
};
|
QColor highlightColor;
|
||||||
|
int highlightWidth = 2;
|
||||||
typedef std::vector<CustomRichText_t> List;
|
bool highlightConnectPrev = false;
|
||||||
|
};
|
||||||
//functions
|
|
||||||
static void paintRichText(QPainter *painter, int x, int y, int w, int h, int xinc,
|
typedef std::vector<CustomRichText_t> List;
|
||||||
const List &richText, CachedFontMetrics *fontMetrics);
|
|
||||||
static void htmlRichText(const List &richText, QString &textHtml, QString &textPlain);
|
//functions
|
||||||
|
template<typename T = qreal>
|
||||||
static List fromTextDocument(const QTextDocument &doc);
|
static void paintRichText(QPainter *painter, T x, T y, T w, T h, T xinc,
|
||||||
|
const List &richText, CachedFontMetrics<T> *fontMetrics);
|
||||||
static List cropped(const List &richText, int maxCols, const QString &indicator = nullptr,
|
static void htmlRichText(const List &richText, QString &textHtml, QString &textPlain);
|
||||||
bool *croppedOut = nullptr);
|
|
||||||
};
|
static List fromTextDocument(const QTextDocument &doc);
|
||||||
|
|
||||||
#endif // RICHTEXTPAINTER_H
|
static List cropped(const List &richText, int maxCols, const QString &indicator = nullptr,
|
||||||
|
bool *croppedOut = nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RICHTEXTPAINTER_H
|
||||||
|
@ -377,8 +377,7 @@ void DisassemblerGraphView::initFont()
|
|||||||
charWidth = metrics.width('X');
|
charWidth = metrics.width('X');
|
||||||
charHeight = static_cast<int>(metrics.height());
|
charHeight = static_cast<int>(metrics.height());
|
||||||
charOffset = 0;
|
charOffset = 0;
|
||||||
delete mFontMetrics;
|
mFontMetrics.reset(new CachedFontMetrics<qreal>(font()));
|
||||||
mFontMetrics = new CachedFontMetrics(this, font());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
||||||
@ -464,7 +463,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
// Highlight selected tokens
|
// Highlight selected tokens
|
||||||
if (highlight_token != nullptr) {
|
if (highlight_token != nullptr) {
|
||||||
int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
|
int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
|
||||||
int tokenWidth = mFontMetrics->width(highlight_token->content);
|
qreal tokenWidth = mFontMetrics->width(highlight_token->content);
|
||||||
|
|
||||||
for (const Instr &instr : db.instrs) {
|
for (const Instr &instr : db.instrs) {
|
||||||
int pos = -1;
|
int pos = -1;
|
||||||
@ -477,19 +476,19 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int widthBefore = mFontMetrics->width(instr.plainText.left(pos));
|
qreal widthBefore = mFontMetrics->width(instr.plainText.left(pos));
|
||||||
if (charWidth * 3 + widthBefore > block.width - (10 + 2 * charWidth)) {
|
if (charWidth * 3 + widthBefore > block.width - (10 + 2 * charWidth)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int highlightWidth = tokenWidth;
|
qreal highlightWidth = tokenWidth;
|
||||||
if (charWidth * 3 + widthBefore + tokenWidth >= block.width - (10 + 2 * charWidth)) {
|
if (charWidth * 3 + widthBefore + tokenWidth >= block.width - (10 + 2 * charWidth)) {
|
||||||
highlightWidth = static_cast<int>(block.width - widthBefore - (10 + 4 * charWidth));
|
highlightWidth = block.width - widthBefore - (10 + 4 * charWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor selectionColor = ConfigColor("wordhl");
|
QColor selectionColor = ConfigColor("wordhl");
|
||||||
|
|
||||||
p.fillRect(QRect(static_cast<int>(blockX + charWidth * 3 + widthBefore), y, highlightWidth,
|
p.fillRect(QRectF(blockX + charWidth * 3 + widthBefore, y, highlightWidth,
|
||||||
charHeight), selectionColor);
|
charHeight), selectionColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,8 +534,8 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
RichTextPainter::paintRichText(&p, static_cast<int>(x), y, block.width, charHeight, 0, line,
|
RichTextPainter::paintRichText<qreal>(&p, x, y, block.width, charHeight, 0, line,
|
||||||
mFontMetrics);
|
mFontMetrics.get());
|
||||||
y += charHeight;
|
y += charHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,9 +568,9 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
QRectF bpRect(x - rectSize / 3.0, y + (charHeight - rectSize) / 2.0, rectSize, rectSize);
|
QRectF bpRect(x - rectSize / 3.0, y + (charHeight - rectSize) / 2.0, rectSize, rectSize);
|
||||||
Q_UNUSED(bpRect);
|
Q_UNUSED(bpRect);
|
||||||
|
|
||||||
RichTextPainter::paintRichText(&p, static_cast<int>(x + charWidth), y,
|
RichTextPainter::paintRichText<qreal>(&p, x + charWidth, y,
|
||||||
static_cast<int>(block.width - charWidth), charHeight, 0, line,
|
block.width - charWidth, charHeight, 0, line,
|
||||||
mFontMetrics);
|
mFontMetrics.get());
|
||||||
y += charHeight;
|
y += charHeight;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ private:
|
|||||||
|
|
||||||
Token *highlight_token;
|
Token *highlight_token;
|
||||||
// Font data
|
// Font data
|
||||||
CachedFontMetrics *mFontMetrics;
|
std::unique_ptr<CachedFontMetrics<qreal>> mFontMetrics;
|
||||||
qreal charWidth;
|
qreal charWidth;
|
||||||
int charHeight;
|
int charHeight;
|
||||||
int charOffset;
|
int charOffset;
|
||||||
|
Loading…
Reference in New Issue
Block a user