Use correct character width for hexwidget (#1607)

This commit is contained in:
karliss 2019-06-18 11:34:30 +03:00 committed by xarkes
parent 4516cf7a0c
commit bb80cbd862
2 changed files with 68 additions and 67 deletions

View File

@ -146,7 +146,7 @@ void HexWidget::setMonospaceFont(const QFont &font)
setFont(XXX); */ setFont(XXX); */
} }
QScrollArea::setFont(font); QScrollArea::setFont(font);
monospaceFont = font; monospaceFont = font.resolve(this->font());
updateMetrics(); updateMetrics();
fetchData(); fetchData();
updateCursorMeta(); updateCursorMeta();
@ -559,7 +559,8 @@ void HexWidget::onCursorBlinked()
if (!cursorEnabled) if (!cursorEnabled)
return; return;
cursor.blink(); cursor.blink();
viewport()->update(cursor.screenPos.translated(-horizontalScrollBar()->value(), 0)); QRect cursorRect(cursor.screenPos.x(), cursor.screenPos.y(), cursor.screenPos.width(), cursor.screenPos.height());
viewport()->update(cursorRect.translated(-horizontalScrollBar()->value(), 0));
} }
void HexWidget::onHexPairsModeEnabled(bool enable) void HexWidget::onHexPairsModeEnabled(bool enable)
@ -670,7 +671,7 @@ void HexWidget::drawHeader(QPainter &painter)
return; return;
int offset = 0; int offset = 0;
QRect rect(itemArea.left(), 0, itemWidth(), lineHeight); QRectF rect(itemArea.left(), 0, itemWidth(), lineHeight);
painter.setPen(addrColor); painter.setPen(addrColor);
@ -702,7 +703,7 @@ void HexWidget::drawCursor(QPainter &painter, bool shadow)
} }
painter.setPen(cursor.cachedColor); painter.setPen(cursor.cachedColor);
QRect charRect(cursor.screenPos); QRectF charRect(cursor.screenPos);
charRect.setWidth(charWidth); charRect.setWidth(charWidth);
painter.fillRect(charRect, backgroundColor); painter.fillRect(charRect, backgroundColor);
painter.drawText(charRect, Qt::AlignVCenter, cursor.cachedChar); painter.drawText(charRect, Qt::AlignVCenter, cursor.cachedChar);
@ -716,8 +717,8 @@ void HexWidget::drawAddrArea(QPainter &painter)
{ {
uint64_t offset = startAddress; uint64_t offset = startAddress;
QString addrString; QString addrString;
QSize areaSize((addrCharLen + (showExAddr ? 2 : 0)) * charWidth, lineHeight); QSizeF areaSize((addrCharLen + (showExAddr ? 2 : 0)) * charWidth, lineHeight);
QRect strRect(addrArea.topLeft(), areaSize); QRectF strRect(addrArea.topLeft(), areaSize);
painter.setPen(addrColor); painter.setPen(addrColor);
for (int line = 0; for (int line = 0;
@ -731,13 +732,13 @@ void HexWidget::drawAddrArea(QPainter &painter)
painter.setPen(borderColor); painter.setPen(borderColor);
int vLineOffset = itemArea.left() - charWidth; qreal vLineOffset = itemArea.left() - charWidth;
painter.drawLine(vLineOffset, 0, vLineOffset, viewport()->height()); painter.drawLine(QLineF(vLineOffset, 0, vLineOffset, viewport()->height()));
} }
void HexWidget::drawItemArea(QPainter &painter) void HexWidget::drawItemArea(QPainter &painter)
{ {
QRect itemRect(itemArea.topLeft(), QSize(itemWidth(), lineHeight)); QRectF itemRect(itemArea.topLeft(), QSizeF(itemWidth(), lineHeight));
QColor itemColor; QColor itemColor;
QString itemString; QString itemString;
@ -768,13 +769,13 @@ void HexWidget::drawItemArea(QPainter &painter)
painter.setPen(borderColor); painter.setPen(borderColor);
int vLineOffset = asciiArea.left() - charWidth; qreal vLineOffset = asciiArea.left() - charWidth;
painter.drawLine(vLineOffset, 0, vLineOffset, viewport()->height()); painter.drawLine(QLineF(vLineOffset, 0, vLineOffset, viewport()->height()));
} }
void HexWidget::drawAsciiArea(QPainter &painter) void HexWidget::drawAsciiArea(QPainter &painter)
{ {
QRect charRect(asciiArea.topLeft(), QSize(charWidth, lineHeight)); QRectF charRect(asciiArea.topLeft(), QSizeF(charWidth, lineHeight));
fillSelectionBackground(painter, true); fillSelectionBackground(painter, true);
@ -790,10 +791,11 @@ void HexWidget::drawAsciiArea(QPainter &painter)
painter.setPen(color); painter.setPen(color);
/* Dots look ugly. Use fillRect() instead of drawText(). */ /* Dots look ugly. Use fillRect() instead of drawText(). */
if (ascii == '.') { if (ascii == '.') {
int a = cursor.screenPos.width(); qreal a = cursor.screenPos.width();
int x = charRect.left() + (charWidth - a) / 2 + 1; QPointF p = charRect.bottomLeft();
int y = charRect.bottom() - 2 * a; p.rx() += (charWidth - a) / 2 + 1;
painter.fillRect(x, y, a, a, color); p.ry() += - 2 * a;
painter.fillRect(QRectF(p, QSizeF(a, a)), color);
} else { } else {
painter.drawText(charRect, Qt::AlignVCenter, ascii); painter.drawText(charRect, Qt::AlignVCenter, ascii);
} }
@ -892,15 +894,14 @@ QVector<QPolygonF> HexWidget::rangePolygons(RVA start, RVA last, bool ascii)
void HexWidget::updateMetrics() void HexWidget::updateMetrics()
{ {
lineHeight = fontMetrics().height(); QFontMetricsF fontMetrics(this->monospaceFont);
charWidth = fontMetrics().width(QLatin1Char('F')); lineHeight = fontMetrics.height();
charWidth = fontMetrics.width(QLatin1Char('F'));
updateCounts(); updateCounts();
updateAreasHeight(); updateAreasHeight();
int cursorWidth = charWidth / 3; qreal cursorWidth = std::max(charWidth / 3, 1.);
if (cursorWidth == 0)
cursorWidth = 1;
cursor.screenPos.setHeight(lineHeight); cursor.screenPos.setHeight(lineHeight);
shadowCursor.screenPos.setHeight(lineHeight); shadowCursor.screenPos.setHeight(lineHeight);
@ -919,17 +920,17 @@ void HexWidget::updateMetrics()
void HexWidget::updateAreasPosition() void HexWidget::updateAreasPosition()
{ {
const int spacingWidth = areaSpacingWidth(); const qreal spacingWidth = areaSpacingWidth();
int yOffset = showHeader ? lineHeight : 0; qreal yOffset = showHeader ? lineHeight : 0;
addrArea.setTopLeft(QPoint(0, yOffset)); addrArea.setTopLeft(QPointF(0, yOffset));
addrArea.setWidth((addrCharLen + (showExAddr ? 2 : 0)) * charWidth); addrArea.setWidth((addrCharLen + (showExAddr ? 2 : 0)) * charWidth);
itemArea.setTopLeft(QPoint(addrArea.right() + spacingWidth, yOffset)); itemArea.setTopLeft(QPointF(addrArea.right() + spacingWidth, yOffset));
itemArea.setWidth(itemRowWidth()); itemArea.setWidth(itemRowWidth());
asciiArea.setTopLeft(QPoint(itemArea.right() + spacingWidth, yOffset)); asciiArea.setTopLeft(QPointF(itemArea.right() + spacingWidth, yOffset));
asciiArea.setWidth(asciiRowWidth()); asciiArea.setWidth(asciiRowWidth());
updateWidth(); updateWidth();
@ -937,9 +938,9 @@ void HexWidget::updateAreasPosition()
void HexWidget::updateAreasHeight() void HexWidget::updateAreasHeight()
{ {
visibleLines = (viewport()->height() - itemArea.top()) / lineHeight; visibleLines = static_cast<int>((viewport()->height() - itemArea.top()) / lineHeight);
int height = visibleLines * lineHeight; qreal height = visibleLines * lineHeight;
addrArea.setHeight(height); addrArea.setHeight(height);
itemArea.setHeight(height); itemArea.setHeight(height);
asciiArea.setHeight(height); asciiArea.setHeight(height);
@ -1007,8 +1008,8 @@ void HexWidget::setCursorAddr(BasicCursor addr, bool select)
void HexWidget::updateCursorMeta() void HexWidget::updateCursorMeta()
{ {
QPoint point; QPointF point;
QPoint pointAscii; QPointF pointAscii;
int offset = cursor.address - startAddress; int offset = cursor.address - startAddress;
int itemOffset = offset; int itemOffset = offset;
@ -1169,14 +1170,16 @@ void HexWidget::fetchData()
BasicCursor HexWidget::screenPosToAddr(const QPoint &point, bool middle) const BasicCursor HexWidget::screenPosToAddr(const QPoint &point, bool middle) const
{ {
QPoint pt = point - itemArea.topLeft(); QPointF pt = point - itemArea.topLeft();
int relativeAddress = 0; int relativeAddress = 0;
relativeAddress += (pt.y() / lineHeight) * itemRowByteLen(); int line = static_cast<int>(pt.y() / lineHeight);
relativeAddress += (pt.x() / columnExWidth()) * itemGroupByteLen(); relativeAddress += line * itemRowByteLen();
pt.rx() %= columnExWidth(); int column = static_cast<int>(pt.x() / columnExWidth());
relativeAddress += column * itemGroupByteLen();
pt.rx() -= column * columnExWidth();
auto roundingOffset = middle ? itemWidth() / 2 : 0; auto roundingOffset = middle ? itemWidth() / 2 : 0;
relativeAddress += ((pt.x() + roundingOffset) / itemWidth()) * itemByteLen; relativeAddress += static_cast<int>((pt.x() + roundingOffset) / itemWidth()) * itemByteLen;
BasicCursor result(startAddress); BasicCursor result(startAddress);
result += relativeAddress; result += relativeAddress;
return result; return result;
@ -1184,12 +1187,12 @@ BasicCursor HexWidget::screenPosToAddr(const QPoint &point, bool middle) const
BasicCursor HexWidget::asciiPosToAddr(const QPoint &point, bool middle) const BasicCursor HexWidget::asciiPosToAddr(const QPoint &point, bool middle) const
{ {
QPoint pt = point - asciiArea.topLeft(); QPointF pt = point - asciiArea.topLeft();
int relativeAddress = 0; int relativeAddress = 0;
relativeAddress += (pt.y() / lineHeight) * itemRowByteLen(); relativeAddress += static_cast<int>(pt.y() / lineHeight) * itemRowByteLen();
auto roundingOffset = middle ? (charWidth / 2) : 0; auto roundingOffset = middle ? (charWidth / 2) : 0;
relativeAddress += (pt.x() + (roundingOffset)) / charWidth; relativeAddress += static_cast<int>((pt.x() + (roundingOffset)) / charWidth);
BasicCursor result(startAddress); BasicCursor result(startAddress);
result += relativeAddress; result += relativeAddress;
return result; return result;
@ -1205,12 +1208,12 @@ BasicCursor HexWidget::mousePosToAddr(const QPoint &point, bool middle) const
return asciiArea.contains(point) ? asciiPosToAddr(point, middle) : screenPosToAddr(point, middle); return asciiArea.contains(point) ? asciiPosToAddr(point, middle) : screenPosToAddr(point, middle);
} }
QRect HexWidget::itemRectangle(uint offset) QRectF HexWidget::itemRectangle(uint offset)
{ {
int x; qreal x;
int y; qreal y;
int width = itemWidth(); qreal width = itemWidth();
y = (offset / itemRowByteLen()) * lineHeight; y = (offset / itemRowByteLen()) * lineHeight;
offset %= itemRowByteLen(); offset %= itemRowByteLen();
@ -1228,21 +1231,19 @@ QRect HexWidget::itemRectangle(uint offset)
x += itemArea.x(); x += itemArea.x();
y += itemArea.y(); y += itemArea.y();
return QRect(x, y, width, lineHeight); return QRectF(x, y, width, lineHeight);
} }
QRect HexWidget::asciiRectangle(uint offset) QRectF HexWidget::asciiRectangle(uint offset)
{ {
int x; QPointF p;
int y;
y = (offset / itemRowByteLen()) * lineHeight; p.ry() = (offset / itemRowByteLen()) * lineHeight;
offset %= itemRowByteLen(); offset %= itemRowByteLen();
x = offset * charWidth; p.rx() = offset * charWidth;
x += asciiArea.x(); p += asciiArea.topLeft();
y += asciiArea.y();
return QRect(x, y, charWidth, lineHeight); return QRectF(p, QSizeF(charWidth, lineHeight));
} }

View File

@ -57,7 +57,7 @@ struct HexCursor
bool isVisible; bool isVisible;
bool onAsciiArea; bool onAsciiArea;
QTimer blinkTimer; QTimer blinkTimer;
QRect screenPos; QRectF screenPos;
uint64_t address; uint64_t address;
QString cachedChar; QString cachedChar;
QColor cachedColor; QColor cachedColor;
@ -319,17 +319,17 @@ private:
* @param offset relative to first byte on screen * @param offset relative to first byte on screen
* @return * @return
*/ */
QRect itemRectangle(uint offset); QRectF itemRectangle(uint offset);
/** /**
* @brief Rectangle for single item in ascii area. * @brief Rectangle for single item in ascii area.
* @param offset relative to first byte on screen * @param offset relative to first byte on screen
* @return * @return
*/ */
QRect asciiRectangle(uint offset); QRectF asciiRectangle(uint offset);
QVector<QPolygonF> rangePolygons(RVA start, RVA last, bool ascii); QVector<QPolygonF> rangePolygons(RVA start, RVA last, bool ascii);
void updateWidth(); void updateWidth();
inline int itemWidth() const inline qreal itemWidth() const
{ {
return itemCharLen * charWidth; return itemCharLen * charWidth;
} }
@ -349,17 +349,17 @@ private:
return itemByteLen * itemGroupSize; return itemByteLen * itemGroupSize;
} }
inline int columnWidth() const inline qreal columnWidth() const
{ {
return itemGroupCharLen() * charWidth; return itemGroupCharLen() * charWidth;
} }
inline int columnExWidth() const inline qreal columnExWidth() const
{ {
return columnExCharLen() * charWidth; return columnExCharLen() * charWidth;
} }
inline int columnSpacingWidth() const inline qreal columnSpacingWidth() const
{ {
return columnSpacing * charWidth; return columnSpacing * charWidth;
} }
@ -379,17 +379,17 @@ private:
return itemRowByteLen() * visibleLines; return itemRowByteLen() * visibleLines;
} }
inline int itemRowWidth() const inline qreal itemRowWidth() const
{ {
return itemRowCharLen() * charWidth; return itemRowCharLen() * charWidth;
} }
inline int asciiRowWidth() const inline qreal asciiRowWidth() const
{ {
return itemRowByteLen() * charWidth; return itemRowByteLen() * charWidth;
} }
inline int areaSpacingWidth() const inline qreal areaSpacingWidth() const
{ {
return areaSpacing * charWidth; return areaSpacing * charWidth;
} }
@ -399,7 +399,7 @@ private:
return (startAddress - 1) + bytesPerScreen(); return (startAddress - 1) + bytesPerScreen();
} }
const QRect &currentArea() const const QRectF &currentArea() const
{ {
return cursorOnAscii ? asciiArea : itemArea; return cursorOnAscii ? asciiArea : itemArea;
} }
@ -412,9 +412,9 @@ private:
HexSelection selection; HexSelection selection;
bool updatingSelection; bool updatingSelection;
QRect addrArea; QRectF addrArea;
QRect itemArea; QRectF itemArea;
QRect asciiArea; QRectF asciiArea;
int itemByteLen; int itemByteLen;
int itemGroupSize; ///< Items per group (default: 1), 2 in case of hexpair mode int itemGroupSize; ///< Items per group (default: 1), 2 in case of hexpair mode
@ -430,9 +430,9 @@ private:
int visibleLines; int visibleLines;
uint64_t startAddress; uint64_t startAddress;
int charWidth; qreal charWidth;
int byteWidth; int byteWidth;
int lineHeight; qreal lineHeight;
int addrCharLen; int addrCharLen;
int addrAreaWidth; int addrAreaWidth;
QFont monospaceFont; QFont monospaceFont;