Use more approriate font mentrics in graph and hex views

* fix excessive graph padding for some fonts
* refactor code to make the position calculations more maintainable
* reduce graph view padding from 2 to 1 character widths in monospace
fonts
This commit is contained in:
Kārlis Seņko 2021-05-29 17:32:31 +03:00 committed by xarkes
parent 90f5f2d4cc
commit 26c9dcc76c
5 changed files with 32 additions and 33 deletions

View File

@ -90,7 +90,6 @@ CutterGraphView::CutterGraphView(QWidget *parent)
QPoint CutterGraphView::getTextOffset(int line) const QPoint CutterGraphView::getTextOffset(int line) const
{ {
int padding = static_cast<int>(2 * charWidth);
return QPoint(padding, padding + line * charHeight); return QPoint(padding, padding + line * charHeight);
} }
@ -99,7 +98,12 @@ void CutterGraphView::initFont()
setFont(Config()->getFont()); setFont(Config()->getFont());
QFontMetricsF metrics(font()); QFontMetricsF metrics(font());
baseline = int(metrics.ascent()); baseline = int(metrics.ascent());
charWidth = metrics.maxWidth(); #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
ACharWidth = metrics.width('A');
#else
ACharWidth = metrics.horizontalAdvance('A');
#endif
padding = ACharWidth;
charHeight = static_cast<int>(metrics.height()); charHeight = static_cast<int>(metrics.height());
charOffset = 0; charOffset = 0;
mFontMetrics.reset(new CachedFontMetrics<qreal>(font())); mFontMetrics.reset(new CachedFontMetrics<qreal>(font()));

View File

@ -124,10 +124,11 @@ protected:
// Font data // Font data
std::unique_ptr<CachedFontMetrics<qreal>> mFontMetrics; std::unique_ptr<CachedFontMetrics<qreal>> mFontMetrics;
qreal charWidth; qreal ACharWidth; // width of character A
int charHeight; int charHeight;
int charOffset; int charOffset;
int baseline; int baseline;
qreal padding;
// colors // colors
QColor disassemblyBackgroundColor; QColor disassemblyBackgroundColor;

View File

@ -347,8 +347,9 @@ void DisassemblerGraphView::prepareGraphNode(GraphBlock &block)
height += 1; height += 1;
} }
} }
int extra = static_cast<int>(4 * charWidth + 4); int extra = static_cast<int>(2 * padding + 4);
block.width = static_cast<int>(width + extra + charWidth); qreal indent = ACharWidth;
block.width = static_cast<int>(width + extra + indent);
block.height = (height * charHeight) + extra; block.height = (height * charHeight) + extra;
} }
@ -356,8 +357,6 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block,
{ {
QRectF blockRect(block.x, block.y, block.width, block.height); QRectF blockRect(block.x, block.y, block.width, block.height);
const qreal padding = 2 * charWidth;
p.setPen(Qt::black); p.setPen(Qt::black);
p.setBrush(Qt::gray); p.setBrush(Qt::gray);
p.setFont(Config()->getFont()); p.setFont(Config()->getFont());
@ -412,12 +411,14 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block,
// Stop rendering text when it's too small // Stop rendering text when it's too small
auto transform = p.combinedTransform(); auto transform = p.combinedTransform();
QRect screenChar = transform.mapRect(QRect(0, 0, charWidth, charHeight)); QRect screenChar = transform.mapRect(QRect(0, 0, ACharWidth, charHeight));
if (screenChar.width() < Config()->getGraphMinFontSize()) { if (screenChar.width() < Config()->getGraphMinFontSize()) {
return; return;
} }
qreal indent = ACharWidth;
// Highlight selected tokens // Highlight selected tokens
if (interactive && highlight_token != nullptr) { if (interactive && highlight_token != nullptr) {
int y = firstInstructionY; int y = firstInstructionY;
@ -436,20 +437,21 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block,
} }
qreal widthBefore = mFontMetrics->width(instr.plainText.left(pos)); qreal widthBefore = mFontMetrics->width(instr.plainText.left(pos));
if (charWidth * 3 + widthBefore > block.width - (10 + padding)) { qreal textOffset = padding + indent;
if (textOffset + widthBefore > block.width - (10 + padding)) {
continue; continue;
} }
qreal highlightWidth = tokenWidth; qreal highlightWidth = tokenWidth;
if (charWidth * 3 + widthBefore + tokenWidth >= block.width - (10 + padding)) { if (textOffset + widthBefore + tokenWidth >= block.width - (10 + padding)) {
highlightWidth = block.width - widthBefore - (10 + 2 * padding); highlightWidth = block.width - widthBefore - (10 + 2 * padding);
} }
QColor selectionColor = ConfigColor("wordHighlight"); QColor selectionColor = ConfigColor("wordHighlight");
p.fillRect(QRectF(block.x + charWidth * 3 + widthBefore, y, highlightWidth, p.fillRect(
charHeight), QRectF(block.x + textOffset + widthBefore, y, highlightWidth, charHeight),
selectionColor); selectionColor);
} }
y += int(instr.text.lines.size()) * charHeight; y += int(instr.text.lines.size()) * charHeight;
@ -467,7 +469,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block,
auto bih = Core()->getBIHighlighter(); auto bih = Core()->getBIHighlighter();
for (const Instr &instr : db.instrs) { for (const Instr &instr : db.instrs) {
const QRect instrRect = QRect(static_cast<int>(block.x + charWidth), y, const QRect instrRect = QRect(static_cast<int>(block.x + indent), y,
static_cast<int>(block.width - (10 + padding)), static_cast<int>(block.width - (10 + padding)),
int(instr.text.lines.size()) * charHeight); int(instr.text.lines.size()) * charHeight);
@ -489,17 +491,8 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block,
} }
for (auto &line : instr.text.lines) { for (auto &line : instr.text.lines) {
int rectSize = qRound(charWidth);
if (rectSize % 2) {
rectSize++;
}
// Assume charWidth <= charHeight
// TODO: Breakpoint/Cip stuff
QRectF bpRect(x - rectSize / 3.0, y + (charHeight - rectSize) / 2.0, rectSize,
rectSize);
Q_UNUSED(bpRect);
RichTextPainter::paintRichText<qreal>(&p, x + charWidth, y, block.width - charWidth, RichTextPainter::paintRichText<qreal>(&p, x + indent, y, block.width - padding,
charHeight, 0, line, mFontMetrics.get()); charHeight, 0, line, mFontMetrics.get());
y += charHeight; y += charHeight;
} }
@ -615,7 +608,7 @@ QRectF DisassemblerGraphView::getInstrRect(GraphView::GraphBlock &block, RVA add
} }
QPointF topLeft = getInstructionOffset(db, static_cast<int>(firstLineWithAddr)); QPointF topLeft = getInstructionOffset(db, static_cast<int>(firstLineWithAddr));
return QRectF(topLeft, return QRectF(topLeft,
QSizeF(block.width - 4 * charWidth, QSizeF(block.width - 2 * padding,
charHeight * int(currentLine - firstLineWithAddr))); charHeight * int(currentLine - firstLineWithAddr)));
} }
currentLine += instr.text.lines.size(); currentLine += instr.text.lines.size();
@ -771,7 +764,7 @@ void DisassemblerGraphView::copySelection()
DisassemblerGraphView::Token *DisassemblerGraphView::getToken(Instr *instr, int x) DisassemblerGraphView::Token *DisassemblerGraphView::getToken(Instr *instr, int x)
{ {
x -= (int)(3 * charWidth); // Ignore left margin x -= (int)(padding + ACharWidth); // Ignore left margin
if (x < 0) { if (x < 0) {
return nullptr; return nullptr;
} }

View File

@ -1168,7 +1168,11 @@ void HexWidget::updateMetrics()
{ {
QFontMetricsF fontMetrics(this->monospaceFont); QFontMetricsF fontMetrics(this->monospaceFont);
lineHeight = fontMetrics.height(); lineHeight = fontMetrics.height();
charWidth = fontMetrics.maxWidth(); #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
charWidth = fontMetrics.width('A');
#else
charWidth = fontMetrics.horizontalAdvance('A');
#endif
updateCounts(); updateCounts();
updateAreasHeight(); updateAreasHeight();

View File

@ -88,8 +88,6 @@ void SimpleTextGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block, b
{ {
QRectF blockRect(block.x, block.y, block.width, block.height); QRectF blockRect(block.x, block.y, block.width, block.height);
const qreal padding = charWidth;
p.setPen(Qt::black); p.setPen(Qt::black);
p.setBrush(Qt::gray); p.setBrush(Qt::gray);
p.setFont(Config()->getFont()); p.setFont(Config()->getFont());
@ -113,7 +111,7 @@ void SimpleTextGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block, b
// Stop rendering text when it's too small // Stop rendering text when it's too small
auto transform = p.combinedTransform(); auto transform = p.combinedTransform();
QRect screenChar = transform.mapRect(QRect(0, 0, charWidth, charHeight)); QRect screenChar = transform.mapRect(QRect(0, 0, ACharWidth, charHeight));
if (screenChar.width() < Config()->getGraphMinFontSize()) { if (screenChar.width() < Config()->getGraphMinFontSize()) {
return; return;
@ -156,9 +154,8 @@ void SimpleTextGraphView::addBlock(GraphLayout::GraphBlock block, const QString
int height = 1; int height = 1;
int width = mFontMetrics->width(text); int width = mFontMetrics->width(text);
int extra = static_cast<int>(2 * charWidth); block.width = static_cast<int>(width + padding);
block.width = static_cast<int>(width + extra); block.height = (height * charHeight) + padding;
block.height = (height * charHeight) + extra;
GraphView::addBlock(std::move(block)); GraphView::addBlock(std::move(block));
} }