Implement screen orientation (#202)
This commit is contained in:
parent
e2c10f8a35
commit
52f4ce220e
|
@ -11,7 +11,8 @@ ScreenCanvas::ScreenCanvas(QQuickItem *parent):
|
|||
m_foreground(QColor(0x00, 0x00, 0x00)),
|
||||
m_background(QColor(0xFF, 0xFF, 0xFF)),
|
||||
m_canvas(QImage(1, 1, QImage::Format_RGB32)),
|
||||
m_zoomFactor(1.0)
|
||||
m_zoomFactor(1.0),
|
||||
m_orientation(Qt::LandscapeOrientation)
|
||||
{
|
||||
connect(this, &ScreenCanvas::zoomFactorChanged, this, &ScreenCanvas::updateImplicitSize);
|
||||
connect(this, &ScreenCanvas::canvasSizeChanged, this, &ScreenCanvas::updateImplicitSize);
|
||||
|
@ -30,6 +31,7 @@ void ScreenCanvas::setFrame(const ScreenFrame &frame)
|
|||
}
|
||||
|
||||
setCanvasSize(frame.size);
|
||||
setCanvasOrientation(frame.orientation);
|
||||
|
||||
for (auto x = 0; x < m_canvas.width(); x++) {
|
||||
for (auto y = 0; y < m_canvas.height(); y++) {
|
||||
|
@ -37,9 +39,7 @@ void ScreenCanvas::setFrame(const ScreenFrame &frame)
|
|||
const auto z = y % 8;
|
||||
const auto color = ((frame.pixelData.at(i) & (1 << z))) ? m_foreground : m_background;
|
||||
|
||||
m_canvas.setPixelColor(frame.isFlipped ? m_canvas.width() - x - 1 : x,
|
||||
frame.isFlipped ? m_canvas.height() - y - 1 : y,
|
||||
color);
|
||||
m_canvas.setPixelColor(x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,27 +48,8 @@ void ScreenCanvas::setFrame(const ScreenFrame &frame)
|
|||
|
||||
void ScreenCanvas::paint(QPainter *painter)
|
||||
{
|
||||
const auto bw = boundingRect().width();
|
||||
const auto bh = boundingRect().height();
|
||||
|
||||
const auto aspectRatio = (double)m_canvas.width() / m_canvas.height();
|
||||
|
||||
auto w = bw;
|
||||
auto h = floor(w / aspectRatio);
|
||||
|
||||
if(h > bh) {
|
||||
h = bh;
|
||||
w = bh * aspectRatio;
|
||||
}
|
||||
|
||||
w -= ((int)w % m_canvas.width());
|
||||
h -= ((int)h % m_canvas.height());
|
||||
|
||||
const auto dw = (bw - w) / 2;
|
||||
const auto dh = (bh - h) / 2;
|
||||
|
||||
const QRectF canvasRect(dw, dh, w, h);
|
||||
painter->drawImage(canvasRect, m_canvas);
|
||||
painter->drawImage(canvasRect(), m_canvas.transformed(canvasTransform()));
|
||||
}
|
||||
|
||||
qreal ScreenCanvas::zoomFactor() const
|
||||
|
@ -144,11 +125,83 @@ void ScreenCanvas::setCanvasSize(const QSize &size)
|
|||
emit canvasSizeChanged();
|
||||
}
|
||||
|
||||
void ScreenCanvas::setCanvasOrientation(Qt::ScreenOrientation orientation)
|
||||
{
|
||||
m_orientation = orientation;
|
||||
}
|
||||
|
||||
QTransform ScreenCanvas::canvasTransform() const
|
||||
{
|
||||
switch (m_orientation) {
|
||||
case Qt::InvertedLandscapeOrientation:
|
||||
return QTransform().rotate(180);
|
||||
case Qt::PortraitOrientation:
|
||||
return QTransform().rotate(isLandscapeOnly() ? 0 : 90);
|
||||
case Qt::InvertedPortraitOrientation:
|
||||
return QTransform().rotate(isLandscapeOnly() ? 180 : -90);
|
||||
case Qt::LandscapeOrientation:
|
||||
default:
|
||||
return QTransform();
|
||||
}
|
||||
}
|
||||
|
||||
QRectF ScreenCanvas::canvasRect() const
|
||||
{
|
||||
const auto totalWidth = boundingRect().width();
|
||||
const auto totalHeight = boundingRect().height();
|
||||
|
||||
const auto isRegular = isLandscapeOrientation() || isLandscapeOnly();
|
||||
|
||||
const auto canvasWidth = isRegular ? m_canvas.width() : m_canvas.height();
|
||||
const auto canvasHeight = isRegular ? m_canvas.height() : m_canvas.width();
|
||||
|
||||
const auto aspectRatio = static_cast<qreal>(canvasWidth) / canvasHeight;
|
||||
|
||||
auto drawWidth = totalWidth;
|
||||
auto drawHeight = floor(drawWidth / aspectRatio);
|
||||
|
||||
if(drawHeight > totalHeight) {
|
||||
drawHeight = totalHeight;
|
||||
drawWidth = totalHeight * aspectRatio;
|
||||
}
|
||||
|
||||
if(drawWidth > canvasWidth) {
|
||||
drawWidth -= (static_cast<int>(drawWidth) % canvasWidth);
|
||||
}
|
||||
|
||||
if(drawHeight > canvasHeight) {
|
||||
drawHeight -= (static_cast<int>(drawHeight) % canvasHeight);
|
||||
}
|
||||
|
||||
const auto offsetX = (totalWidth - drawWidth) / 2;
|
||||
const auto offsetY = (totalHeight - drawHeight) / 2;
|
||||
|
||||
return QRectF(offsetX, offsetY, drawWidth, drawHeight);
|
||||
}
|
||||
|
||||
QSize ScreenCanvas::canvasSize() const
|
||||
{
|
||||
return QSize(isLandscapeOrientation() ? m_canvas.width() : m_canvas.height(),
|
||||
isLandscapeOrientation() ? m_canvas.height() : m_canvas.width());
|
||||
}
|
||||
|
||||
bool ScreenCanvas::isLandscapeOrientation() const
|
||||
{
|
||||
return m_orientation == Qt::LandscapeOrientation ||
|
||||
m_orientation == Qt::InvertedLandscapeOrientation;
|
||||
}
|
||||
|
||||
bool ScreenCanvas::isLandscapeOnly() const
|
||||
{
|
||||
return (boundingRect().width() < canvasSize().width()) ||
|
||||
(boundingRect().height() < canvasSize().height());
|
||||
}
|
||||
|
||||
const QImage ScreenCanvas::canvas(int scale) const
|
||||
{
|
||||
if(scale == 0) {
|
||||
return m_canvas.scaled(m_canvas.width() * m_zoomFactor, m_canvas.height() * m_zoomFactor);
|
||||
return m_canvas.scaled(m_canvas.width() * m_zoomFactor, m_canvas.height() * m_zoomFactor).transformed(canvasTransform());
|
||||
} else {
|
||||
return m_canvas.scaled(m_canvas.width() * scale, m_canvas.height() * scale);
|
||||
return m_canvas.scaled(m_canvas.width() * scale, m_canvas.height() * scale).transformed(canvasTransform());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,12 +49,21 @@ private slots:
|
|||
|
||||
private:
|
||||
void setCanvasSize(const QSize &size);
|
||||
void setCanvasOrientation(Qt::ScreenOrientation orientation);
|
||||
|
||||
const QImage canvas(int scale = 0) const;
|
||||
QTransform canvasTransform() const;
|
||||
QRectF canvasRect() const;
|
||||
QSize canvasSize() const;
|
||||
|
||||
bool isLandscapeOrientation() const;
|
||||
bool isLandscapeOnly() const;
|
||||
|
||||
const QImage canvas(int scale = 0) const;
|
||||
|
||||
QColor m_foreground;
|
||||
QColor m_background;
|
||||
QImage m_canvas;
|
||||
|
||||
qreal m_zoomFactor;
|
||||
Qt::ScreenOrientation m_orientation;
|
||||
};
|
||||
|
|
|
@ -61,7 +61,7 @@ void ScreenStreamer::setDevice(FlipperZero *device)
|
|||
setScreenFrame({
|
||||
transposeImage(QByteArray((char*)default_bits, sizeof(default_bits)), default_width, default_height),
|
||||
QSize(SCREEN_FRAME_WIDTH, SCREEN_FRAME_HEIGHT),
|
||||
false
|
||||
Qt::LandscapeOrientation,
|
||||
});
|
||||
|
||||
if(device) {
|
||||
|
@ -179,7 +179,7 @@ void ScreenStreamer::onBroadcastResponseReceived(QObject *response)
|
|||
setScreenFrame({
|
||||
screenFrameResponse->screenFrame(),
|
||||
QSize(SCREEN_FRAME_WIDTH, SCREEN_FRAME_HEIGHT),
|
||||
screenFrameResponse->screenOrientation() == GuiScreenFrameResponseInterface::HorizontalFlip
|
||||
screenFrameResponse->screenOrientation(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
struct ScreenFrame {
|
||||
QByteArray pixelData;
|
||||
QSize size;
|
||||
bool isFlipped;
|
||||
Qt::ScreenOrientation orientation;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(ScreenFrame)
|
||||
|
|
|
@ -10,17 +10,17 @@ const QByteArray GuiScreenFrameResponse::screenFrame() const
|
|||
return QByteArray((const char*)f->bytes, f->size);
|
||||
}
|
||||
|
||||
GuiScreenFrameResponseInterface::ScreenOrientation GuiScreenFrameResponse::screenOrientation() const
|
||||
Qt::ScreenOrientation GuiScreenFrameResponse::screenOrientation() const
|
||||
{
|
||||
switch(message().content.gui_screen_frame.orientation) {
|
||||
case PB_Gui_ScreenOrientation_HORIZONTAL_FLIP:
|
||||
return ScreenOrientation::HorizontalFlip;
|
||||
return Qt::InvertedLandscapeOrientation;
|
||||
case PB_Gui_ScreenOrientation_VERTICAL:
|
||||
return ScreenOrientation::Vertical;
|
||||
return Qt::PortraitOrientation;
|
||||
case PB_Gui_ScreenOrientation_VERTICAL_FLIP:
|
||||
return ScreenOrientation::VerticalFlip;
|
||||
return Qt::InvertedPortraitOrientation;
|
||||
case PB_Gui_ScreenOrientation_HORIZONTAL:
|
||||
default:
|
||||
return ScreenOrientation::Horizontal;
|
||||
return Qt::LandscapeOrientation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,5 +11,5 @@ class GuiScreenFrameResponse : public MainResponse, public GuiScreenFrameRespons
|
|||
public:
|
||||
GuiScreenFrameResponse(MessageWrapper &wrapper, QObject *parent = nullptr);
|
||||
const QByteArray screenFrame() const override;
|
||||
ScreenOrientation screenOrientation() const override;
|
||||
Qt::ScreenOrientation screenOrientation() const override;
|
||||
};
|
||||
|
|
|
@ -6,15 +6,8 @@
|
|||
class GuiScreenFrameResponseInterface
|
||||
{
|
||||
public:
|
||||
enum ScreenOrientation {
|
||||
Horizontal,
|
||||
HorizontalFlip,
|
||||
Vertical,
|
||||
VerticalFlip,
|
||||
};
|
||||
|
||||
virtual const QByteArray screenFrame() const = 0;
|
||||
virtual ScreenOrientation screenOrientation() const = 0;
|
||||
virtual Qt::ScreenOrientation screenOrientation() const = 0;
|
||||
};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
Loading…
Reference in New Issue