Skip to content

Add QRegion support #101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Support for further types: `QLine`, `QLineF`, `QImage`, `QPainter`, `QFont`, `QPen`, `QPolygon`, `QPolygonF`
- Support for further types: `QLine`, `QLineF`, `QImage`, `QPainter`, `QFont`, `QPen`, `QPolygon`, `QPolygonF`, `QRegion`
- `internal_pointer_mut()` function on `QModelIndex`
- `c_void` in CXX-Qt-lib for easy access to `void *`
- `CxxQtThread` is now marked as `Sync` so that it can be used by reference
Expand Down
22 changes: 22 additions & 0 deletions crates/cxx-qt-lib-headers/include/gui/qregion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// clang-format off
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// clang-format on
// SPDX-FileContributor: Laurent Montel <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0
#pragma once

#include <QtGui/QRegion>

#include "rust/cxx.h"

// Define namespace otherwise we hit a GCC bug
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480
namespace rust {

template<>
struct IsRelocatable<QRegion> : ::std::true_type
{
};

} // namespace rust
2 changes: 2 additions & 0 deletions crates/cxx-qt-lib-headers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ pub fn build_opts() -> cxx_qt_build::CxxQtBuildersOpts {
#[cfg(feature = "qt_gui")]
(include_str!("../include/gui/qpainter.h"), "qpainter.h"),
#[cfg(feature = "qt_gui")]
(include_str!("../include/gui/qregion.h"), "qregion.h"),
#[cfg(feature = "qt_gui")]
(include_str!("../include/gui/qvector2d.h"), "qvector2d.h"),
#[cfg(feature = "qt_gui")]
(include_str!("../include/gui/qvector3d.h"), "qvector3d.h"),
Expand Down
2 changes: 2 additions & 0 deletions crates/cxx-qt-lib/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ fn main() {
"gui/qpen",
"gui/qpolygon",
"gui/qpolygonf",
"gui/qregion",
"gui/qvector2d",
"gui/qvector3d",
"gui/qvector4d",
Expand Down Expand Up @@ -208,6 +209,7 @@ fn main() {
"gui/qpen",
"gui/qpolygon",
"gui/qpolygonf",
"gui/qregion",
"gui/qvector2d",
"gui/qvector3d",
"gui/qvector4d",
Expand Down
3 changes: 3 additions & 0 deletions crates/cxx-qt-lib/src/gui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ pub use qpainterpath::QPainterPath;

mod qpainter;
pub use qpainter::{QPainter, QPainterCompositionMode, QPainterRenderHint};

mod qregion;
pub use qregion::QRegion;
12 changes: 12 additions & 0 deletions crates/cxx-qt-lib/src/gui/qpainter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ mod ffi {
type QPen = crate::QPen;
include!("cxx-qt-lib/qpolygon.h");
type QPolygon = crate::QPolygon;
include!("cxx-qt-lib/qregion.h");
type QRegion = crate::QRegion;

/// Returns the current background mode.
#[rust_name = "background_mode"]
Expand All @@ -191,6 +193,10 @@ mod ffi {
#[rust_name = "clip_path"]
fn clipPath(self: &QPainter) -> QPainterPath;

/// Returns the currently set clip region. Note that the clip region is given in logical coordinates.
#[rust_name = "clip_region"]
fn clipRegion(self: &QPainter) -> QRegion;

/// Returns the current composition mode.
#[rust_name = "composition_mode"]
fn compositionMode(self: &QPainter) -> QPainterCompositionMode;
Expand Down Expand Up @@ -326,6 +332,12 @@ mod ffi {
#[rust_name = "set_clip_rect"]
fn setClipRect(self: Pin<&mut QPainter>, rectangle: &QRect, operation: ClipOperation);

/// Sets the clip region to the given region using the specified clip operation. The default
/// clip operation is to replace the current clip region.
/// Note that the clip region is given in logical coordinates.
#[rust_name = "set_clip_region"]
fn setClipRegion(self: Pin<&mut QPainter>, region: &QRegion, operation: ClipOperation);

/// Sets the composition mode to the given mode.
#[rust_name = "set_composition_mode"]
fn setCompositionMode(self: Pin<&mut QPainter>, mode: QPainterCompositionMode);
Expand Down
5 changes: 5 additions & 0 deletions crates/cxx-qt-lib/src/gui/qpainterpath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ mod ffi {
type QString = crate::QString;
include!("cxx-qt-lib/qpolygonf.h");
type QPolygonF = crate::QPolygonF;
include!("cxx-qt-lib/qregion.h");
type QRegion = crate::QRegion;

/// Creates an ellipse within the specified boundingRectangle and adds it to the painter
/// path as a closed subpath.
Expand All @@ -47,6 +49,9 @@ mod ffi {
#[rust_name = "add_rect"]
fn addRect(self: &mut QPainterPath, rectangle: &QRectF);

#[rust_name = "add_region"]
fn addRegion(self: &mut QPainterPath, region: &QRegion);

/// Adds the given rectangle rect with rounded corners to the path.
#[rust_name = "add_rounded_rect"]
fn addRoundedRect(
Expand Down
23 changes: 23 additions & 0 deletions crates/cxx-qt-lib/src/gui/qregion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// clang-format off
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// clang-format on
// SPDX-FileContributor: Laurent Montel <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0

#include "cxx-qt-lib/qregion.h"

#include "../assertion_utils.h"

// https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/painting/qregion.h?h=v5.15.6-lts-lgpl#n178
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/painting/qregion.h?h=v6.2.4#n161
assert_alignment_and_size(QRegion,
alignof(::std::size_t),
sizeof(::std::size_t));

static_assert(!::std::is_trivially_copy_assignable<QRegion>::value);
static_assert(!::std::is_trivially_copy_constructible<QRegion>::value);

static_assert(!::std::is_trivially_destructible<QRegion>::value);

static_assert(QTypeInfo<QRegion>::isRelocatable);
110 changes: 110 additions & 0 deletions crates/cxx-qt-lib/src/gui/qregion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// SPDX-FileContributor: Laurent Montel <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0
use cxx::{type_id, ExternType};
use std::mem::MaybeUninit;

#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
include!("cxx-qt-lib/qregion.h");
type QRegion = super::QRegion;

include!("cxx-qt-lib/qrect.h");
type QRect = crate::QRect;

include!("cxx-qt-lib/qpoint.h");
type QPoint = crate::QPoint;

/// Returns the bounding rectangle of this region. An empty region gives a rectangle that is QRect::isNul
#[rust_name = "bounding_rect"]
fn boundingRect(self: &QRegion) -> QRect;

/// Returns true if the region overlaps the rectangle r; otherwise returns false.
fn contains(self: &QRegion, r: &QRect) -> bool;

/// Returns a region which is the intersection of this region and r.
fn intersected(self: &QRegion, r: &QRegion) -> QRegion;

/// Returns true if the region is empty; otherwise returns false. An empty region is a region that contains no points.
#[rust_name = "is_empty"]
fn isEmpty(self: &QRegion) -> bool;

/// Returns true if the region is empty; otherwise returns false. An empty region is a region that contains no points.
/// This function is the same as isEmpty
#[rust_name = "is_null"]
fn isNull(self: &QRegion) -> bool;

/// Returns the number of rectangles that this region is composed of.
#[rust_name = "rect_count"]
fn rectCount(self: &QRegion) -> i32;

/// Returns a region which is r subtracted from this region.
fn subtracted(self: &QRegion, r: &QRegion) -> QRegion;

/// Translates the region point.x() along the x axis and point.y() along the y axis, relative to the current position.
/// Positive values move the region to the right and down.
/// Translates to the given point.
fn translate(self: &mut QRegion, point: &QPoint);

/// Returns a copy of the region that is translated p.x() along the x axis and p.y() along the y axis,
/// relative to the current position. Positive values move the rectangle to the right and down.
fn translated(self: &QRegion, p: &QPoint) -> QRegion;

/// Returns a region which is the union of this region and r.
fn united(self: &QRegion, r: &QRegion) -> QRegion;

/// Returns a region which is the exclusive or (XOR) of this region and r.
fn xored(self: &QRegion, r: &QRegion) -> QRegion;
}

#[namespace = "rust::cxxqtlib1"]
unsafe extern "C++" {
include!("cxx-qt-lib/common.h");

#[doc(hidden)]
#[rust_name = "qregion_init_default"]
fn construct() -> QRegion;

#[doc(hidden)]
#[rust_name = "qregion_drop"]
fn drop(r: &mut QRegion);

#[doc(hidden)]
#[rust_name = "qregion_clone"]
fn construct(r: &QRegion) -> QRegion;
}
}

#[repr(C)]
pub struct QRegion {
_cspec: MaybeUninit<usize>,
}

impl Default for QRegion {
/// Constructs an empty region.
fn default() -> Self {
ffi::qregion_init_default()
}
}

impl Drop for QRegion {
fn drop(&mut self) {
ffi::qregion_drop(self);
}
}

impl Clone for QRegion {
fn clone(&self) -> Self {
ffi::qregion_clone(self)
}
}

// Safety:
//
// Static checks on the C++ side to ensure the size is the same.
unsafe impl ExternType for QRegion {
type Id = type_id!("QRegion");
type Kind = cxx::kind::Trivial;
}
1 change: 1 addition & 0 deletions tests/qt_types_standalone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ add_executable(${APP_NAME}
cpp/qqmlengine.h
cpp/qrect.h
cpp/qrectf.h
cpp/qregion.h
cpp/qset.h
cpp/qsize.h
cpp/qsizef.h
Expand Down
2 changes: 2 additions & 0 deletions tests/qt_types_standalone/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "qqmlengine.h"
#include "qrect.h"
#include "qrectf.h"
#include "qregion.h"
#include "qset.h"
#include "qsize.h"
#include "qsizef.h"
Expand Down Expand Up @@ -92,6 +93,7 @@ main(int argc, char* argv[])
runTest(QScopedPointer<QObject>(new QVector3DTest));
runTest(QScopedPointer<QObject>(new QVector4DTest));
runTest(QScopedPointer<QObject>(new QPolygonTest));
runTest(QScopedPointer<QObject>(new QRegionTest));

return status;
}
31 changes: 31 additions & 0 deletions tests/qt_types_standalone/cpp/qregion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// clang-format off
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// clang-format on
// SPDX-FileContributor: Laurent Montel <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0
#pragma once

#include <QtGui/QRegion>
#include <QtTest/QTest>

#include "cxx-qt-gen/qregion.cxx.h"

class QRegionTest : public QObject
{
Q_OBJECT

private Q_SLOTS:
void construct()
{
const auto p = construct_qregion();
QVERIFY(p.isEmpty());
}

void clone()
{
const auto p = QRegion(2, 4, 5, 3);
const auto c = clone_qregion(p);
QCOMPARE(p, c);
}
};
1 change: 1 addition & 0 deletions tests/qt_types_standalone/rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ fn main() {
.file("src/qqmlengine.rs")
.file("src/qrect.rs")
.file("src/qrectf.rs")
.file("src/qregion.rs")
.file("src/qset.rs")
.file("src/qsize.rs")
.file("src/qsizef.rs")
Expand Down
1 change: 1 addition & 0 deletions tests/qt_types_standalone/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ mod qqmlapplicationengine;
mod qqmlengine;
mod qrect;
mod qrectf;
mod qregion;
mod qset;
mod qsize;
mod qsizef;
Expand Down
28 changes: 28 additions & 0 deletions tests/qt_types_standalone/rust/src/qregion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// SPDX-FileContributor: Laurent Montel <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use cxx_qt_lib::QRegion;

#[cxx::bridge]
mod qregion_cxx {
unsafe extern "C++" {
include!("cxx-qt-lib/qregion.h");

type QRegion = cxx_qt_lib::QRegion;
}

extern "Rust" {
fn construct_qregion() -> QRegion;
fn clone_qregion(p: &QRegion) -> QRegion;
}
}

fn construct_qregion() -> QRegion {
QRegion::default()
}

fn clone_qregion(p: &QRegion) -> QRegion {
p.clone()
}
Loading