Cockatrice 2026-09-01-Development-3.1.0-beta.10
A virtual tabletop for multiplayer card games
Loading...
Searching...
No Matches
playmat_utils.h
Go to the documentation of this file.
1#ifndef COCKATRICE_PLAYMAT_UTILS_H
2#define COCKATRICE_PLAYMAT_UTILS_H
3
4#include <QRectF>
5#include <QSize>
6#include <QSizeF>
8
9namespace PlaymatUtils
10{
11
13constexpr qreal MAX_ZOOM = 4.0;
14
19inline qreal playmatVisibleWidth(const QSize &fullCardSize, const PlaymatParams &params)
20{
21 const qreal srcW = fullCardSize.width();
22 const qreal marginL = params.marginPctL * srcW;
23 const qreal marginR = params.marginPctR * srcW;
24 return qMax(0.0, srcW - marginL - marginR);
25}
26
37inline qreal playmatClampedZoom(const QSize &fullCardSize, const PlaymatParams &params)
38{
39 const qreal minDim = qMin<qreal>(fullCardSize.width(), fullCardSize.height());
40 const qreal visibleW = playmatVisibleWidth(fullCardSize, params);
41 const qreal zoomOutFloor = (minDim > 0.0 && visibleW > 0.0) ? visibleW / minDim : 1.0;
42 // The floor deliberately bypasses MAX_ZOOM: when the art is much wider
43 // than tall, keeping the square window inside it requires more than 4x
44 // zoom-out, and honoring that larger floor keeps side within
45 // min(card width, height). Zooming IN is still capped at MAX_ZOOM.
46 return qMin(MAX_ZOOM, qMax(params.zoom, zoomOutFloor));
47}
48
55inline qreal playmatWindowSide(const QSize &fullCardSize, const PlaymatParams &params)
56{
57 const qreal visibleW = playmatVisibleWidth(fullCardSize, params);
58 if (visibleW <= 0.0) {
59 return 0.0;
60 }
61 return visibleW / playmatClampedZoom(fullCardSize, params);
62}
63
76inline QRectF computeArtSourceRect(const QSize &fullCardSize, const PlaymatParams &params)
77{
78 const qreal srcW = fullCardSize.width();
79 const qreal srcH = fullCardSize.height();
80
81 // Square sampling window, keeps art unskewed, never exceeds the card on
82 // either axis thanks to the zoom floor in playmatWindowSide().
83 const qreal side = playmatWindowSide(fullCardSize, params);
84
85 // verticalOffset places the TOP edge of the sampling window itself within
86 // its travel, so the full [0, 1] parameter range is live at every zoom and
87 // the window can always reach the very top (0.0) and bottom (1.0) of the
88 // art.
89 const qreal offset = qBound(0.0, params.verticalOffset, 1.0);
90 const qreal y = offset * qMax(0.0, srcH - side);
91
92 // Horizontally the sampling window sits centered inside the trimmed span
93 // (margins pan it), zooming out can make it wider than that span, so it
94 // is then kept within the image, an edge stop, never an invalid rect.
95 const qreal outerW = playmatVisibleWidth(fullCardSize, params);
96 const qreal x = qBound(0.0, params.marginPctL * srcW + (outerW - side) / 2.0, qMax(0.0, srcW - side));
97
98 return QRectF(x, y, side, side);
99}
100
109inline QRectF coverFitRect(const QRectF &dstArea, const QSizeF &srcSize)
110{
111 const qreal srcAspect = srcSize.width() / srcSize.height();
112 const qreal dstAspect = dstArea.width() / dstArea.height();
113
114 if (srcAspect > dstAspect) {
115 const qreal dstW = dstArea.height() * srcAspect;
116 return QRectF(dstArea.left() + (dstArea.width() - dstW) / 2.0, dstArea.top(), dstW, dstArea.height());
117 }
118
119 const qreal dstH = dstArea.width() / srcAspect;
120 return QRectF(dstArea.left(), dstArea.top() + (dstArea.height() - dstH) / 2.0, dstArea.width(), dstH);
121}
122
128inline QRectF aspectFitRect(const QRectF &dstArea, qreal aspect)
129{
130 if (aspect <= 0.0) {
131 return dstArea;
132 }
133 qreal w = qMin(dstArea.width(), dstArea.height() * aspect);
134 qreal h = w / aspect;
135 return QRectF(dstArea.left() + (dstArea.width() - w) / 2.0, dstArea.top() + (dstArea.height() - h) / 2.0, w, h);
136}
137
138} // namespace PlaymatUtils
139
140#endif // COCKATRICE_PLAYMAT_UTILS_H
Defines the DeckList class, which manages a full deck structure including cards, zones,...
Definition playmat_utils.h:10
qreal playmatWindowSide(const QSize &fullCardSize, const PlaymatParams &params)
Side of the square sampling window actually rendered for these parameters. Never exceeds either card ...
Definition playmat_utils.h:55
QRectF computeArtSourceRect(const QSize &fullCardSize, const PlaymatParams &params)
Computes the source region of the full resolution card image to use as a playmat.
Definition playmat_utils.h:76
qreal playmatClampedZoom(const QSize &fullCardSize, const PlaymatParams &params)
Zoom clamped to the range where every step renders differently.
Definition playmat_utils.h:37
constexpr qreal MAX_ZOOM
Upper bound for zooming into the playmat art.
Definition playmat_utils.h:13
QRectF coverFitRect(const QRectF &dstArea, const QSizeF &srcSize)
Returns the destination rectangle that fits a source of the given aspect ratio into dstArea using "co...
Definition playmat_utils.h:109
QRectF aspectFitRect(const QRectF &dstArea, qreal aspect)
Fits a rectangle of the given aspect ratio into dstArea, centered, touching the constraining dimensio...
Definition playmat_utils.h:128
qreal playmatVisibleWidth(const QSize &fullCardSize, const PlaymatParams &params)
Width of the outer viewing window: full card width trimmed by the horizontal margins....
Definition playmat_utils.h:19
Positioning parameters for a playmat card image.
Definition playmat_params.h:18
double marginPctL
Left margin as fraction of card width (0.0–0.95).
Definition playmat_params.h:19
double marginPctR
Right margin as fraction of card width (0.0–0.95).
Definition playmat_params.h:20
double verticalOffset
Vertical position within card (0.0=top, 1.0=bottom).
Definition playmat_params.h:21
double zoom
Scale factor (0.1–4.0).
Definition playmat_params.h:22