valentina/src/app/puzzle/scene/vpgraphicstilegrid.cpp

245 lines
8.1 KiB
C++
Raw Normal View History

#include "vpgraphicstilegrid.h"
2024-03-30 14:20:59 +01:00
#include <math.h>
2021-08-09 14:09:10 +02:00
#include "../layout/vplayout.h"
2021-09-07 19:26:35 +02:00
#include "../layout/vpsheet.h"
#include "../vmisc/theme/vscenestylesheet.h"
#include "../vptilefactory.h"
2022-02-18 19:01:30 +01:00
#include "../vwidgets/global.h"
2021-09-11 18:39:38 +02:00
#include <QFileInfo>
#include <QImageReader>
#include <QPixmapCache>
#include <QSvgRenderer>
2021-09-06 14:31:19 +02:00
namespace
{
constexpr qreal penWidth = 1;
2022-02-18 19:01:30 +01:00
constexpr qreal minTextFontSize = 5.0;
2022-02-10 13:07:05 +01:00
//---------------------------------------------------------------------------------------------------------------------
auto SheetMargins(const VPSheetPtr &sheet) -> QMarginsF
{
if (not sheet.isNull() && not sheet->IgnoreMargins())
{
return sheet->GetSheetMargins();
}
return {};
}
//---------------------------------------------------------------------------------------------------------------------
auto OptimizeFontSizeToFitTextInRect(QPainter *painter, const QRectF &drawRect, const QString &text,
int flags = Qt::TextDontClip | Qt::TextWordWrap, double goalError = 0.01,
int maxIterationNumber = 10) -> QFont
2022-02-10 13:07:05 +01:00
{
2022-02-18 19:01:30 +01:00
QFont font;
if (not drawRect.isValid())
{
font.setPointSizeF(0.00000001);
return font;
}
2022-02-10 13:07:05 +01:00
painter->save();
double minError = std::numeric_limits<double>::max();
double error = std::numeric_limits<double>::max();
int iterationNumber = 0;
while ((error > goalError) && (iterationNumber < maxIterationNumber))
2022-02-10 13:07:05 +01:00
{
iterationNumber++;
2024-02-19 17:09:56 +01:00
QRect const fontBoundRect = painter->fontMetrics().boundingRect(drawRect.toRect(), flags, text);
2022-02-18 19:01:30 +01:00
if (fontBoundRect.isNull())
{
font.setPointSizeF(0.00000001);
break;
}
2024-02-19 17:09:56 +01:00
double const xFactor = drawRect.width() / fontBoundRect.width();
double const yFactor = drawRect.height() / fontBoundRect.height();
2024-03-30 14:20:59 +01:00
double factor = NAN;
if (xFactor < 1 && yFactor < 1)
2022-02-10 13:07:05 +01:00
{
factor = std::min(xFactor, yFactor);
}
else if (xFactor > 1 && yFactor > 1)
2022-02-10 13:07:05 +01:00
{
factor = std::max(xFactor, yFactor);
}
else if (xFactor < 1 && yFactor > 1)
2022-02-10 13:07:05 +01:00
{
factor = xFactor;
}
else
{
factor = yFactor;
}
error = qFabs(factor - 1);
if (factor > 1)
2022-02-10 13:07:05 +01:00
{
if (error < minError)
{
minError = error;
}
else
{
break;
}
}
font = painter->font();
qreal size = font.pointSizeF() * factor;
2022-02-18 19:01:30 +01:00
if (size <= 0)
{
size = 0.00000001;
}
font.setPointSizeF(size);
2022-02-10 13:07:05 +01:00
painter->setFont(font);
}
painter->restore();
return font;
}
} // namespace
2021-09-06 14:31:19 +02:00
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsTileGrid::VPGraphicsTileGrid(const VPLayoutPtr &layout, const QUuid &sheetUuid, QGraphicsItem *parent)
: QGraphicsItem(parent),
2021-09-06 14:31:19 +02:00
m_layout(layout),
m_sheetUuid(sheetUuid)
{
}
//---------------------------------------------------------------------------------------------------------------------
2021-08-25 15:58:50 +02:00
auto VPGraphicsTileGrid::boundingRect() const -> QRectF
{
if (VPLayoutPtr const layout = m_layout.toStrongRef();
not layout.isNull() && layout->LayoutSettings().GetShowTiles())
{
2024-02-19 17:09:56 +01:00
VPSheetPtr const sheet = layout->GetSheet(m_sheetUuid);
2021-09-06 14:31:19 +02:00
2021-09-07 19:26:35 +02:00
QMarginsF sheetMargins;
if (not sheet.isNull() && not sheet->IgnoreMargins())
{
sheetMargins = sheet->GetSheetMargins();
}
2024-02-19 17:09:56 +01:00
qreal const xScale = layout->LayoutSettings().HorizontalScale();
qreal const yScale = layout->LayoutSettings().VerticalScale();
2021-09-06 15:56:56 +02:00
2024-02-19 17:09:56 +01:00
qreal const width = layout->TileFactory()->DrawingAreaWidth() - VPTileFactory::tileStripeWidth;
qreal const height = layout->TileFactory()->DrawingAreaHeight() - VPTileFactory::tileStripeWidth;
2021-09-07 19:26:35 +02:00
2024-02-19 17:09:56 +01:00
QRectF const rect(sheetMargins.left(), sheetMargins.top(),
layout->TileFactory()->ColNb(sheet) * (width / xScale),
layout->TileFactory()->RowNb(sheet) * (height / yScale));
2021-09-06 14:31:19 +02:00
constexpr qreal halfPenWidth = penWidth / 2.;
2021-09-06 14:31:19 +02:00
return rect.adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
2021-07-29 16:11:18 +02:00
return {};
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTileGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
2024-01-06 13:20:56 +01:00
VPLayoutPtr const layout = m_layout.toStrongRef();
if (layout.isNull() || not layout->LayoutSettings().GetShowTiles())
{
2022-02-10 13:07:05 +01:00
return;
}
2021-09-06 14:31:19 +02:00
QPen pen(VSceneStylesheet::ManualLayoutStyle().SheetTileGridColor(), penWidth, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin);
2022-02-10 13:07:05 +01:00
pen.setCosmetic(true);
pen.setStyle(Qt::DashLine);
2024-01-06 13:20:56 +01:00
QBrush const noBrush(Qt::NoBrush);
2022-02-10 13:07:05 +01:00
painter->setPen(pen);
painter->setBrush(noBrush);
2024-01-06 13:20:56 +01:00
qreal const xScale = layout->LayoutSettings().HorizontalScale();
qreal const yScale = layout->LayoutSettings().VerticalScale();
2022-02-10 13:07:05 +01:00
2024-01-06 13:20:56 +01:00
VWatermarkData const watermarkData = layout->TileFactory()->WatermarkData();
2022-02-10 13:07:05 +01:00
auto PaintWatermark = [painter, layout, xScale, yScale, &watermarkData](const QRectF &img)
2022-02-10 13:07:05 +01:00
{
if (not layout->LayoutSettings().WatermarkPath().isEmpty() && layout->LayoutSettings().GetShowWatermark() &&
watermarkData.opacity > 0)
2021-09-07 19:26:35 +02:00
{
2022-02-10 13:07:05 +01:00
if (watermarkData.showImage && not watermarkData.path.isEmpty())
{
VPTileFactory::PaintWatermarkImage(painter, img, watermarkData,
layout->LayoutSettings().WatermarkPath(), true, xScale, yScale);
2022-02-10 13:07:05 +01:00
}
if (watermarkData.showText && not watermarkData.text.isEmpty())
{
VPTileFactory::PaintWatermarkText(painter, img, watermarkData);
}
2021-09-07 19:26:35 +02:00
}
2022-02-10 13:07:05 +01:00
};
2022-02-18 19:01:30 +01:00
const qreal width = (layout->TileFactory()->DrawingAreaWidth() - VPTileFactory::tileStripeWidth) / xScale;
const qreal height = (layout->TileFactory()->DrawingAreaHeight() - VPTileFactory::tileStripeWidth) / yScale;
2024-01-06 13:20:56 +01:00
VPSheetPtr const sheet = layout->GetSheet(m_sheetUuid);
QMarginsF const sheetMargins = SheetMargins(sheet);
2022-02-18 19:01:30 +01:00
const int nbCol = layout->TileFactory()->ColNb(sheet);
const int nbRow = layout->TileFactory()->RowNb(sheet);
2024-01-06 13:20:56 +01:00
QFont const font = OptimizeFontSizeToFitTextInRect(
painter, QRectF(sheetMargins.left(), sheetMargins.top(), width / 3., height / 3.),
QString::number(nbRow * nbCol));
2022-02-18 19:01:30 +01:00
const qreal scale = SceneScale(scene());
auto PaintTileNumber = [painter, layout, nbCol, font, scale](const QRectF &img, int i, int j)
2022-02-10 13:07:05 +01:00
{
2022-02-18 19:01:30 +01:00
if (layout->LayoutSettings().GetShowTileNumber() && font.pointSizeF() * scale >= minTextFontSize)
2022-02-10 13:07:05 +01:00
{
painter->save();
2021-09-07 19:26:35 +02:00
2022-02-10 13:07:05 +01:00
painter->setFont(font);
2022-02-10 13:07:05 +01:00
QPen pen = painter->pen();
pen.setColor(VSceneStylesheet::ManualLayoutStyle().SheetTileNumberColor());
2022-02-10 13:07:05 +01:00
painter->setPen(pen);
2021-09-06 15:56:56 +02:00
painter->drawText(img, Qt::AlignCenter, QString::number(j * nbCol + i + 1));
2021-09-07 19:26:35 +02:00
2022-02-10 13:07:05 +01:00
painter->restore();
}
};
2021-09-06 15:56:56 +02:00
for (int j = 0; j <= nbRow; ++j)
2022-02-10 13:07:05 +01:00
{
// horizontal lines
painter->drawLine(QPointF(sheetMargins.left(), sheetMargins.top() + j * height),
QPointF(sheetMargins.left() + nbCol * width, sheetMargins.top() + j * height));
for (int i = 0; i <= nbCol; ++i)
{
2022-02-10 13:07:05 +01:00
// vertical lines
painter->drawLine(QPointF(sheetMargins.left() + i * width, sheetMargins.top()),
QPointF(sheetMargins.left() + i * width, sheetMargins.top() + nbRow * height));
2021-09-11 18:39:38 +02:00
2022-02-10 13:07:05 +01:00
if (j < nbRow && i < nbCol)
2021-09-11 18:39:38 +02:00
{
2024-01-06 13:20:56 +01:00
QRectF const img(sheetMargins.left() + i * width, sheetMargins.top() + j * height, width, height);
2022-02-10 13:07:05 +01:00
PaintWatermark(img);
PaintTileNumber(img, i, j);
2021-09-11 18:39:38 +02:00
}
}
}
}