mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 06:11:16 +00:00
Add support for source clipping to the Image element
This allows rendering only a sub-rectangle of the original image, which we can use right away in the sliding puzzle demo.
This commit is contained in:
parent
7583394751
commit
3d85e45ec3
13 changed files with 219 additions and 25 deletions
|
@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
|
||||||
- VerticalLayout / HorizontalLayout
|
- VerticalLayout / HorizontalLayout
|
||||||
- Placeholder text in line edit
|
- Placeholder text in line edit
|
||||||
- global components (#96)
|
- global components (#96)
|
||||||
|
- `Image` element: New source-clip-{x, y, width, height} properties
|
||||||
|
|
||||||
## [0.0.2] - 2020-12-22
|
## [0.0.2] - 2020-12-22
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ extern const cbindgen_private::ItemVTable BorderRectangleVTable;
|
||||||
extern const cbindgen_private::ItemVTable TextVTable;
|
extern const cbindgen_private::ItemVTable TextVTable;
|
||||||
extern const cbindgen_private::ItemVTable TouchAreaVTable;
|
extern const cbindgen_private::ItemVTable TouchAreaVTable;
|
||||||
extern const cbindgen_private::ItemVTable ImageVTable;
|
extern const cbindgen_private::ItemVTable ImageVTable;
|
||||||
|
extern const cbindgen_private::ItemVTable ClippedImageVTable;
|
||||||
extern const cbindgen_private::ItemVTable PathVTable;
|
extern const cbindgen_private::ItemVTable PathVTable;
|
||||||
extern const cbindgen_private::ItemVTable FlickableVTable;
|
extern const cbindgen_private::ItemVTable FlickableVTable;
|
||||||
extern const cbindgen_private::ItemVTable WindowVTable;
|
extern const cbindgen_private::ItemVTable WindowVTable;
|
||||||
|
@ -126,6 +127,7 @@ private:
|
||||||
|
|
||||||
using cbindgen_private::BorderRectangle;
|
using cbindgen_private::BorderRectangle;
|
||||||
using cbindgen_private::Clip;
|
using cbindgen_private::Clip;
|
||||||
|
using cbindgen_private::ClippedImage;
|
||||||
using cbindgen_private::Flickable;
|
using cbindgen_private::Flickable;
|
||||||
using cbindgen_private::Image;
|
using cbindgen_private::Image;
|
||||||
using cbindgen_private::Path;
|
using cbindgen_private::Path;
|
||||||
|
|
|
@ -88,6 +88,8 @@ An Image can be used to represent an image loaded from an image file
|
||||||
|
|
||||||
* **`source`** (*image*): The image to load. In order to reference image, one uses the `img!"..."` macro
|
* **`source`** (*image*): The image to load. In order to reference image, one uses the `img!"..."` macro
|
||||||
which loads the file relative to the directory containing the .60 file.
|
which loads the file relative to the directory containing the .60 file.
|
||||||
|
* **`source-clip-x`**, **`source-clip-y`**, **`source-clip-width`**, **`source-clip-height`** (*int*): properties in source
|
||||||
|
image coordinates that, when specified, can be used to render only a portion of the specified image.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ https://flutter.github.io/samples/slide_puzzle
|
||||||
This will allow to compare SixtyFPS and Flutter.
|
This will allow to compare SixtyFPS and Flutter.
|
||||||
|
|
||||||
Remaining feature to implement to have parity:
|
Remaining feature to implement to have parity:
|
||||||
* Images on the tiles in the "Berlin" theme.
|
|
||||||
* Fonts.
|
* Fonts.
|
||||||
* "Spring" animation instead of a bezier curve.
|
* "Spring" animation instead of a bezier curve.
|
||||||
* Animation when clicking on a tile that cannot be moved.
|
* Animation when clicking on a tile that cannot be moved.
|
||||||
|
|
|
@ -21,6 +21,7 @@ struct Theme := {
|
||||||
name: string,
|
name: string,
|
||||||
window-background-color: color,
|
window-background-color: color,
|
||||||
game-background-color: color,
|
game-background-color: color,
|
||||||
|
game-use-background-image: bool,
|
||||||
game-border: length,
|
game-border: length,
|
||||||
game-radius: length,
|
game-radius: length,
|
||||||
game-text-color: color,
|
game-text-color: color,
|
||||||
|
@ -133,6 +134,7 @@ export MainWindow := Window {
|
||||||
name: "SIMPLE",
|
name: "SIMPLE",
|
||||||
window-background-color: #ffffff,
|
window-background-color: #ffffff,
|
||||||
game-background-color: #ffffff,
|
game-background-color: #ffffff,
|
||||||
|
game-use-background-image: false,
|
||||||
game-border: 1px,
|
game-border: 1px,
|
||||||
game-radius: 2px,
|
game-radius: 2px,
|
||||||
game-text-color: #858585,
|
game-text-color: #858585,
|
||||||
|
@ -152,6 +154,7 @@ export MainWindow := Window {
|
||||||
name: "BERLIN",
|
name: "BERLIN",
|
||||||
window-background-color: #ffffff88,
|
window-background-color: #ffffff88,
|
||||||
game-background-color: #ffffffcc,
|
game-background-color: #ffffffcc,
|
||||||
|
game-use-background-image: true,
|
||||||
game-border: 0px,
|
game-border: 0px,
|
||||||
game-radius: 2px,
|
game-radius: 2px,
|
||||||
game-text-color: #858585,
|
game-text-color: #858585,
|
||||||
|
@ -171,6 +174,7 @@ export MainWindow := Window {
|
||||||
name: "PLASTER",
|
name: "PLASTER",
|
||||||
window-background-color: #424244,
|
window-background-color: #424244,
|
||||||
game-background-color: #f8f4e9,
|
game-background-color: #f8f4e9,
|
||||||
|
game-use-background-image: false,
|
||||||
game-border: 5px,
|
game-border: 5px,
|
||||||
game-radius: 20px,
|
game-radius: 20px,
|
||||||
game-text-color: #858585,
|
game-text-color: #858585,
|
||||||
|
@ -279,7 +283,17 @@ export MainWindow := Window {
|
||||||
+ (parent.height - (4*pieces_size + 3*pieces_spacing))/2;
|
+ (parent.height - (4*pieces_size + 3*pieces_spacing))/2;
|
||||||
animate px , py { duration: 170ms; easing: cubic-bezier(0.17,0.76,0.4,1.75); }
|
animate px , py { duration: 170ms; easing: cubic-bezier(0.17,0.76,0.4,1.75); }
|
||||||
|
|
||||||
Rectangle {
|
if (current-theme.game-use-background-image) : Image {
|
||||||
|
height: 100%; width: 100%;
|
||||||
|
// https://commons.wikimedia.org/wiki/File:Berlin_potsdamer_platz.jpg Belappetit, CC BY-SA 3.0
|
||||||
|
source: img!"berlin.jpg";
|
||||||
|
source-clip-x: mod(i, 4) * 1024 / 4;
|
||||||
|
source-clip-y: floor(i / 4) * 683 / 4;
|
||||||
|
source-clip-width: 1024 / 4;
|
||||||
|
source-clip-height: 683 / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current-theme.game-use-background-image) : Rectangle {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: i >= 8 ? current-theme.piece-background-2 : current-theme.piece-background-1;
|
color: i >= 8 ? current-theme.piece-background-2 : current-theme.piece-background-1;
|
||||||
|
|
|
@ -34,7 +34,7 @@ BorderRectangle := Rectangle {
|
||||||
|
|
||||||
export { BorderRectangle as Rectangle }
|
export { BorderRectangle as Rectangle }
|
||||||
|
|
||||||
export Image := _ {
|
Image := _ {
|
||||||
property <resource> source;
|
property <resource> source;
|
||||||
property <length> x;
|
property <length> x;
|
||||||
property <length> y;
|
property <length> y;
|
||||||
|
@ -42,6 +42,15 @@ export Image := _ {
|
||||||
property <length> height;
|
property <length> height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export ClippedImage := Image {
|
||||||
|
property <int> source-clip-x;
|
||||||
|
property <int> source-clip-y;
|
||||||
|
property <int> source-clip-width;
|
||||||
|
property <int> source-clip-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ClippedImage as Image }
|
||||||
|
|
||||||
export Text := _ {
|
export Text := _ {
|
||||||
property <string> text;
|
property <string> text;
|
||||||
property <string> font_family;
|
property <string> font_family;
|
||||||
|
|
|
@ -43,6 +43,8 @@ use std::rc::Rc;
|
||||||
|
|
||||||
/// 2D Rectangle
|
/// 2D Rectangle
|
||||||
pub type Rect = euclid::default::Rect<f32>;
|
pub type Rect = euclid::default::Rect<f32>;
|
||||||
|
/// 2D Rectangle with integer coordinates
|
||||||
|
pub type IntRect = euclid::default::Rect<i32>;
|
||||||
/// 2D Point
|
/// 2D Point
|
||||||
pub type Point = euclid::default::Point2D<f32>;
|
pub type Point = euclid::default::Point2D<f32>;
|
||||||
/// 2D Size
|
/// 2D Size
|
||||||
|
@ -276,7 +278,7 @@ pub enum HighLevelRenderingPrimitive {
|
||||||
/// Optional rendering variables:
|
/// Optional rendering variables:
|
||||||
/// * [`RenderingVariable::ScaledWidth`]: The image will be scaled to the specified width.
|
/// * [`RenderingVariable::ScaledWidth`]: The image will be scaled to the specified width.
|
||||||
/// * [`RenderingVariable::ScaledHeight`]: The image will be scaled to the specified height.
|
/// * [`RenderingVariable::ScaledHeight`]: The image will be scaled to the specified height.
|
||||||
Image { source: crate::Resource },
|
Image { source: crate::Resource, source_clip_rect: IntRect },
|
||||||
/// Renders the specified `text` with a font that matches the specified family (`font_family`) and the given
|
/// Renders the specified `text` with a font that matches the specified family (`font_family`) and the given
|
||||||
/// pixel size (`font_size`).
|
/// pixel size (`font_size`).
|
||||||
///
|
///
|
||||||
|
@ -1213,6 +1215,16 @@ pub(crate) mod ffi {
|
||||||
height: f32,
|
height: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expand IntRect so that cbindgen can see it. ( is in fact euclid::default::Rect<i32>)
|
||||||
|
#[cfg(cbindgen)]
|
||||||
|
#[repr(C)]
|
||||||
|
struct IntRect {
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
width: i32,
|
||||||
|
height: i32,
|
||||||
|
}
|
||||||
|
|
||||||
/// Expand Point so that cbindgen can see it. ( is in fact euclid::default::PointD2<f32>)
|
/// Expand Point so that cbindgen can see it. ( is in fact euclid::default::PointD2<f32>)
|
||||||
#[cfg(cbindgen)]
|
#[cfg(cbindgen)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -26,7 +26,7 @@ When adding an item or a property, it needs to be kept in sync with different pl
|
||||||
|
|
||||||
use super::component::ComponentVTable;
|
use super::component::ComponentVTable;
|
||||||
use super::eventloop::ComponentWindow;
|
use super::eventloop::ComponentWindow;
|
||||||
use super::graphics::{Color, HighLevelRenderingPrimitive, PathData, Rect, Resource};
|
use super::graphics::{Color, HighLevelRenderingPrimitive, IntRect, PathData, Rect, Resource};
|
||||||
use super::input::{
|
use super::input::{
|
||||||
FocusEvent, InputEventResult, KeyEvent, KeyEventResult, KeyboardModifiers, MouseEvent,
|
FocusEvent, InputEventResult, KeyEvent, KeyEventResult, KeyboardModifiers, MouseEvent,
|
||||||
MouseEventType,
|
MouseEventType,
|
||||||
|
@ -305,6 +305,7 @@ impl Item for Image {
|
||||||
) -> HighLevelRenderingPrimitive {
|
) -> HighLevelRenderingPrimitive {
|
||||||
HighLevelRenderingPrimitive::Image {
|
HighLevelRenderingPrimitive::Image {
|
||||||
source: Self::FIELD_OFFSETS.source.apply_pin(self).get(),
|
source: Self::FIELD_OFFSETS.source.apply_pin(self).get(),
|
||||||
|
source_clip_rect: IntRect::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +363,103 @@ ItemVTable_static! {
|
||||||
pub static ImageVTable for Image
|
pub static ImageVTable for Image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(FieldOffsets, Default, BuiltinItem)]
|
||||||
|
#[pin]
|
||||||
|
/// The implementation of the `ClippedImage` element
|
||||||
|
pub struct ClippedImage {
|
||||||
|
pub source: Property<Resource>,
|
||||||
|
pub x: Property<f32>,
|
||||||
|
pub y: Property<f32>,
|
||||||
|
pub width: Property<f32>,
|
||||||
|
pub height: Property<f32>,
|
||||||
|
pub source_clip_x: Property<i32>,
|
||||||
|
pub source_clip_y: Property<i32>,
|
||||||
|
pub source_clip_width: Property<i32>,
|
||||||
|
pub source_clip_height: Property<i32>,
|
||||||
|
pub cached_rendering_data: CachedRenderingData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Item for ClippedImage {
|
||||||
|
fn init(self: Pin<&Self>, _window: &ComponentWindow) {}
|
||||||
|
|
||||||
|
fn geometry(self: Pin<&Self>) -> Rect {
|
||||||
|
euclid::rect(
|
||||||
|
Self::FIELD_OFFSETS.x.apply_pin(self).get(),
|
||||||
|
Self::FIELD_OFFSETS.y.apply_pin(self).get(),
|
||||||
|
Self::FIELD_OFFSETS.width.apply_pin(self).get(),
|
||||||
|
Self::FIELD_OFFSETS.height.apply_pin(self).get(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fn rendering_primitive(
|
||||||
|
self: Pin<&Self>,
|
||||||
|
_window: &ComponentWindow,
|
||||||
|
) -> HighLevelRenderingPrimitive {
|
||||||
|
HighLevelRenderingPrimitive::Image {
|
||||||
|
source: Self::FIELD_OFFSETS.source.apply_pin(self).get(),
|
||||||
|
source_clip_rect: euclid::rect(
|
||||||
|
Self::FIELD_OFFSETS.source_clip_x.apply_pin(self).get(),
|
||||||
|
Self::FIELD_OFFSETS.source_clip_y.apply_pin(self).get(),
|
||||||
|
Self::FIELD_OFFSETS.source_clip_width.apply_pin(self).get(),
|
||||||
|
Self::FIELD_OFFSETS.source_clip_height.apply_pin(self).get(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rendering_variables(
|
||||||
|
self: Pin<&Self>,
|
||||||
|
_window: &ComponentWindow,
|
||||||
|
) -> SharedArray<RenderingVariable> {
|
||||||
|
let mut vars = SharedArray::default();
|
||||||
|
|
||||||
|
let width = Self::FIELD_OFFSETS.width.apply_pin(self).get();
|
||||||
|
let height = Self::FIELD_OFFSETS.height.apply_pin(self).get();
|
||||||
|
|
||||||
|
if width > 0. {
|
||||||
|
vars.push(RenderingVariable::ScaledWidth(width));
|
||||||
|
}
|
||||||
|
if height > 0. {
|
||||||
|
vars.push(RenderingVariable::ScaledHeight(height));
|
||||||
|
}
|
||||||
|
|
||||||
|
vars
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layouting_info(self: Pin<&Self>, _window: &crate::eventloop::ComponentWindow) -> LayoutInfo {
|
||||||
|
// FIXME: should we use the image size here
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input_event(
|
||||||
|
self: Pin<&Self>,
|
||||||
|
_: MouseEvent,
|
||||||
|
_window: &ComponentWindow,
|
||||||
|
_self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||||
|
_self_index: usize,
|
||||||
|
) -> InputEventResult {
|
||||||
|
InputEventResult::EventIgnored
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &ComponentWindow) -> KeyEventResult {
|
||||||
|
KeyEventResult::EventIgnored
|
||||||
|
}
|
||||||
|
|
||||||
|
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &ComponentWindow) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ItemConsts for ClippedImage {
|
||||||
|
const cached_rendering_data_offset: const_field_offset::FieldOffset<
|
||||||
|
ClippedImage,
|
||||||
|
CachedRenderingData,
|
||||||
|
> = ClippedImage::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemVTable_static! {
|
||||||
|
/// The VTable for `ClippedImage`
|
||||||
|
#[no_mangle]
|
||||||
|
pub static ClippedImageVTable for ClippedImage
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, strum_macros::EnumString, strum_macros::Display)]
|
#[derive(Copy, Clone, Debug, PartialEq, strum_macros::EnumString, strum_macros::Display)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
|
|
|
@ -489,6 +489,7 @@ fn generate_component<'id>(
|
||||||
rtti.extend(
|
rtti.extend(
|
||||||
[
|
[
|
||||||
rtti_for::<Image>(),
|
rtti_for::<Image>(),
|
||||||
|
rtti_for::<ClippedImage>(),
|
||||||
rtti_for::<Text>(),
|
rtti_for::<Text>(),
|
||||||
rtti_for::<Rectangle>(),
|
rtti_for::<Rectangle>(),
|
||||||
rtti_for::<BorderRectangle>(),
|
rtti_for::<BorderRectangle>(),
|
||||||
|
|
|
@ -18,8 +18,8 @@ use sixtyfps_corelib::eventloop::ComponentWindow;
|
||||||
use sixtyfps_corelib::{
|
use sixtyfps_corelib::{
|
||||||
graphics::{
|
graphics::{
|
||||||
Color, Frame as GraphicsFrame, GraphicsBackend, GraphicsWindow,
|
Color, Frame as GraphicsFrame, GraphicsBackend, GraphicsWindow,
|
||||||
HighLevelRenderingPrimitive, Point, Rect, RenderingPrimitivesBuilder, RenderingVariable,
|
HighLevelRenderingPrimitive, IntRect, Point, Rect, RenderingPrimitivesBuilder,
|
||||||
Resource, RgbaColor, Size,
|
RenderingVariable, Resource, RgbaColor, Size,
|
||||||
},
|
},
|
||||||
SharedArray,
|
SharedArray,
|
||||||
};
|
};
|
||||||
|
@ -413,7 +413,7 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder {
|
||||||
let rect = Rect::new(Point::default(), Size::new(*width, *height));
|
let rect = Rect::new(Point::default(), Size::new(*width, *height));
|
||||||
smallvec![self.fill_rectangle(&rect, *border_radius, *border_width)]
|
smallvec![self.fill_rectangle(&rect, *border_radius, *border_width)]
|
||||||
}
|
}
|
||||||
HighLevelRenderingPrimitive::Image { source } => {
|
HighLevelRenderingPrimitive::Image { source, source_clip_rect } => {
|
||||||
match source {
|
match source {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
Resource::AbsoluteFilePath(path) => {
|
Resource::AbsoluteFilePath(path) => {
|
||||||
|
@ -430,7 +430,8 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder {
|
||||||
smallvec![GLRenderingPrimitivesBuilder::create_image(
|
smallvec![GLRenderingPrimitivesBuilder::create_image(
|
||||||
&self.context,
|
&self.context,
|
||||||
&mut *self.texture_atlas.borrow_mut(),
|
&mut *self.texture_atlas.borrow_mut(),
|
||||||
image
|
image,
|
||||||
|
source_clip_rect
|
||||||
)]
|
)]
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
@ -447,12 +448,14 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder {
|
||||||
let shared_primitive = shared_primitive.clone();
|
let shared_primitive = shared_primitive.clone();
|
||||||
let window = self.window.clone();
|
let window = self.window.clone();
|
||||||
let event_loop_proxy = self.event_loop_proxy.clone();
|
let event_loop_proxy = self.event_loop_proxy.clone();
|
||||||
|
let source_clip_rect = *source_clip_rect;
|
||||||
move || {
|
move || {
|
||||||
let texture_primitive =
|
let texture_primitive =
|
||||||
GLRenderingPrimitivesBuilder::create_image(
|
GLRenderingPrimitivesBuilder::create_image(
|
||||||
&context,
|
&context,
|
||||||
&mut *atlas.borrow_mut(),
|
&mut *atlas.borrow_mut(),
|
||||||
&html_image,
|
&html_image,
|
||||||
|
&source_clip_rect,
|
||||||
);
|
);
|
||||||
|
|
||||||
*shared_primitive.borrow_mut() = Some(texture_primitive);
|
*shared_primitive.borrow_mut() = Some(texture_primitive);
|
||||||
|
@ -485,7 +488,8 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder {
|
||||||
smallvec![GLRenderingPrimitivesBuilder::create_image(
|
smallvec![GLRenderingPrimitivesBuilder::create_image(
|
||||||
&self.context,
|
&self.context,
|
||||||
&mut *self.texture_atlas.borrow_mut(),
|
&mut *self.texture_atlas.borrow_mut(),
|
||||||
image
|
image,
|
||||||
|
&source_clip_rect
|
||||||
)]
|
)]
|
||||||
}
|
}
|
||||||
Resource::EmbeddedRgbaImage { width, height, data } => {
|
Resource::EmbeddedRgbaImage { width, height, data } => {
|
||||||
|
@ -498,7 +502,8 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder {
|
||||||
smallvec![GLRenderingPrimitivesBuilder::create_image(
|
smallvec![GLRenderingPrimitivesBuilder::create_image(
|
||||||
&self.context,
|
&self.context,
|
||||||
&mut *self.texture_atlas.borrow_mut(),
|
&mut *self.texture_atlas.borrow_mut(),
|
||||||
image
|
image,
|
||||||
|
&source_clip_rect
|
||||||
)]
|
)]
|
||||||
}
|
}
|
||||||
Resource::None => SmallVec::new(),
|
Resource::None => SmallVec::new(),
|
||||||
|
@ -627,6 +632,7 @@ impl GLRenderingPrimitivesBuilder {
|
||||||
context: &Rc<glow::Context>,
|
context: &Rc<glow::Context>,
|
||||||
atlas: &mut TextureAtlas,
|
atlas: &mut TextureAtlas,
|
||||||
image: impl texture::UploadableAtlasImage,
|
image: impl texture::UploadableAtlasImage,
|
||||||
|
source_rect: &IntRect,
|
||||||
) -> GLRenderingPrimitive {
|
) -> GLRenderingPrimitive {
|
||||||
let rect =
|
let rect =
|
||||||
Rect::new(Point::new(0.0, 0.0), Size::new(image.width() as f32, image.height() as f32));
|
Rect::new(Point::new(0.0, 0.0), Size::new(image.width() as f32, image.height() as f32));
|
||||||
|
@ -642,8 +648,10 @@ impl GLRenderingPrimitivesBuilder {
|
||||||
&context,
|
&context,
|
||||||
&vec![vertex1, vertex2, vertex3, vertex1, vertex3, vertex4],
|
&vec![vertex1, vertex2, vertex3, vertex1, vertex3, vertex4],
|
||||||
);
|
);
|
||||||
let texture_vertices =
|
let texture_vertices = GLArrayBuffer::new(
|
||||||
GLArrayBuffer::new(&context, &atlas_allocation.normalized_texture_coordinates());
|
&context,
|
||||||
|
&atlas_allocation.normalized_texture_coordinates_with_source_rect(source_rect),
|
||||||
|
);
|
||||||
|
|
||||||
GLRenderingPrimitive::Texture { vertices, texture_vertices, texture: atlas_allocation }
|
GLRenderingPrimitive::Texture { vertices, texture_vertices, texture: atlas_allocation }
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,11 @@
|
||||||
LICENSE END */
|
LICENSE END */
|
||||||
use super::{GLContext, Vertex};
|
use super::{GLContext, Vertex};
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use pathfinder_geometry::{rect::RectI, vector::Vector2I};
|
use pathfinder_geometry::{
|
||||||
|
rect::{RectF, RectI},
|
||||||
|
vector::{Vector2F, Vector2I},
|
||||||
|
};
|
||||||
|
use sixtyfps_corelib::graphics::IntRect;
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
pub struct GLTexture {
|
pub struct GLTexture {
|
||||||
|
@ -202,12 +206,25 @@ impl Drop for AtlasAllocation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AtlasAllocation {
|
impl AtlasAllocation {
|
||||||
pub(crate) fn normalized_texture_coordinates(&self) -> [Vertex; 6] {
|
pub(crate) fn normalized_texture_coordinates_with_source_rect(
|
||||||
|
&self,
|
||||||
|
source_rect: &IntRect,
|
||||||
|
) -> [Vertex; 6] {
|
||||||
let atlas_width = self.atlas.texture.width as f32;
|
let atlas_width = self.atlas.texture.width as f32;
|
||||||
let atlas_height = self.atlas.texture.height as f32;
|
let atlas_height = self.atlas.texture.height as f32;
|
||||||
let origin = self.texture_coordinates.origin();
|
let origin = self.texture_coordinates.origin();
|
||||||
let size = self.texture_coordinates.size();
|
let size = self.texture_coordinates.size();
|
||||||
let texture_coordinates = RectI::new(origin, size);
|
let texture_coordinates = RectF::new(
|
||||||
|
Vector2F::new(
|
||||||
|
(origin.x() + source_rect.min_x()) as f32,
|
||||||
|
(origin.y() + source_rect.min_y()) as f32,
|
||||||
|
),
|
||||||
|
if source_rect.is_empty() {
|
||||||
|
Vector2F::new(size.x() as f32, size.y() as f32)
|
||||||
|
} else {
|
||||||
|
Vector2F::new(source_rect.width() as f32, source_rect.height() as f32)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let tex_left = ((texture_coordinates.min_x() as f32) + 0.5) / atlas_width;
|
let tex_left = ((texture_coordinates.min_x() as f32) + 0.5) / atlas_width;
|
||||||
let tex_top = ((texture_coordinates.min_y() as f32) + 0.5) / atlas_height;
|
let tex_top = ((texture_coordinates.min_y() as f32) + 0.5) / atlas_height;
|
||||||
|
@ -221,6 +238,9 @@ impl AtlasAllocation {
|
||||||
|
|
||||||
[tex_vertex1, tex_vertex2, tex_vertex3, tex_vertex1, tex_vertex3, tex_vertex4]
|
[tex_vertex1, tex_vertex2, tex_vertex3, tex_vertex1, tex_vertex3, tex_vertex4]
|
||||||
}
|
}
|
||||||
|
pub(crate) fn normalized_texture_coordinates(&self) -> [Vertex; 6] {
|
||||||
|
self.normalized_texture_coordinates_with_source_rect(&IntRect::default())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GLAtlasTexture {
|
impl GLAtlasTexture {
|
||||||
|
|
|
@ -163,7 +163,10 @@ impl Item for NativeButton {
|
||||||
option.state |= QStyle::State_Enabled;
|
option.state |= QStyle::State_Enabled;
|
||||||
qApp->style()->drawControl(QStyle::CE_PushButton, &option, &p, nullptr);
|
qApp->style()->drawControl(QStyle::CE_PushButton, &option, &p, nullptr);
|
||||||
});
|
});
|
||||||
return HighLevelRenderingPrimitive::Image { source: imgarray.to_resource() };
|
return HighLevelRenderingPrimitive::Image {
|
||||||
|
source: imgarray.to_resource(),
|
||||||
|
source_clip_rect: Default::default(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rendering_variables(
|
fn rendering_variables(
|
||||||
|
@ -294,7 +297,10 @@ impl Item for NativeCheckBox {
|
||||||
option.state |= QStyle::State_Enabled;
|
option.state |= QStyle::State_Enabled;
|
||||||
qApp->style()->drawControl(QStyle::CE_CheckBox, &option, &p, nullptr);
|
qApp->style()->drawControl(QStyle::CE_CheckBox, &option, &p, nullptr);
|
||||||
});
|
});
|
||||||
return HighLevelRenderingPrimitive::Image { source: imgarray.to_resource() };
|
return HighLevelRenderingPrimitive::Image {
|
||||||
|
source: imgarray.to_resource(),
|
||||||
|
source_clip_rect: Default::default(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rendering_variables(
|
fn rendering_variables(
|
||||||
|
@ -444,7 +450,10 @@ impl Item for NativeSpinBox {
|
||||||
auto text_rect = style->subControlRect(QStyle::CC_SpinBox, &option, QStyle::SC_SpinBoxEditField, nullptr);
|
auto text_rect = style->subControlRect(QStyle::CC_SpinBox, &option, QStyle::SC_SpinBoxEditField, nullptr);
|
||||||
p.drawText(text_rect, QString::number(value));
|
p.drawText(text_rect, QString::number(value));
|
||||||
});
|
});
|
||||||
return HighLevelRenderingPrimitive::Image { source: imgarray.to_resource() };
|
return HighLevelRenderingPrimitive::Image {
|
||||||
|
source: imgarray.to_resource(),
|
||||||
|
source_clip_rect: Default::default(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rendering_variables(
|
fn rendering_variables(
|
||||||
|
@ -651,7 +660,10 @@ impl Item for NativeSlider {
|
||||||
auto style = qApp->style();
|
auto style = qApp->style();
|
||||||
style->drawComplexControl(QStyle::CC_Slider, &option, &p, nullptr);
|
style->drawComplexControl(QStyle::CC_Slider, &option, &p, nullptr);
|
||||||
});
|
});
|
||||||
return HighLevelRenderingPrimitive::Image { source: imgarray.to_resource() };
|
return HighLevelRenderingPrimitive::Image {
|
||||||
|
source: imgarray.to_resource(),
|
||||||
|
source_clip_rect: Default::default(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rendering_variables(
|
fn rendering_variables(
|
||||||
|
@ -931,7 +943,10 @@ impl Item for NativeGroupBox {
|
||||||
QStyle::SH_GroupBox_TextLabelColor, &option));
|
QStyle::SH_GroupBox_TextLabelColor, &option));
|
||||||
qApp->style()->drawComplexControl(QStyle::CC_GroupBox, &option, &p, nullptr);
|
qApp->style()->drawComplexControl(QStyle::CC_GroupBox, &option, &p, nullptr);
|
||||||
});
|
});
|
||||||
return HighLevelRenderingPrimitive::Image { source: imgarray.to_resource() };
|
return HighLevelRenderingPrimitive::Image {
|
||||||
|
source: imgarray.to_resource(),
|
||||||
|
source_clip_rect: Default::default(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rendering_variables(
|
fn rendering_variables(
|
||||||
|
@ -1085,7 +1100,10 @@ impl Item for NativeLineEdit {
|
||||||
option.state |= QStyle::State_Enabled;
|
option.state |= QStyle::State_Enabled;
|
||||||
qApp->style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, &p, nullptr);
|
qApp->style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, &p, nullptr);
|
||||||
});
|
});
|
||||||
return HighLevelRenderingPrimitive::Image { source: imgarray.to_resource() };
|
return HighLevelRenderingPrimitive::Image {
|
||||||
|
source: imgarray.to_resource(),
|
||||||
|
source_clip_rect: Default::default(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rendering_variables(
|
fn rendering_variables(
|
||||||
|
@ -1336,7 +1354,10 @@ impl Item for NativeScrollView {
|
||||||
data.pressed == 1,
|
data.pressed == 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
return HighLevelRenderingPrimitive::Image { source: imgarray.to_resource() };
|
return HighLevelRenderingPrimitive::Image {
|
||||||
|
source: imgarray.to_resource(),
|
||||||
|
source_clip_rect: Default::default(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rendering_variables(
|
fn rendering_variables(
|
||||||
|
@ -1584,7 +1605,10 @@ impl Item for NativeStandardListViewItem {
|
||||||
qApp->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &option, &p, nullptr);
|
qApp->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &option, &p, nullptr);
|
||||||
qApp->style()->drawControl(QStyle::CE_ItemViewItem, &option, &p, nullptr);
|
qApp->style()->drawControl(QStyle::CE_ItemViewItem, &option, &p, nullptr);
|
||||||
});
|
});
|
||||||
return HighLevelRenderingPrimitive::Image { source: imgarray.to_resource() };
|
return HighLevelRenderingPrimitive::Image {
|
||||||
|
source: imgarray.to_resource(),
|
||||||
|
source_clip_rect: Default::default(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rendering_variables(
|
fn rendering_variables(
|
||||||
|
@ -1716,7 +1740,10 @@ impl Item for NativeComboBox {
|
||||||
qApp->style()->drawComplexControl(QStyle::CC_ComboBox, &option, &p, nullptr);
|
qApp->style()->drawComplexControl(QStyle::CC_ComboBox, &option, &p, nullptr);
|
||||||
qApp->style()->drawControl(QStyle::CE_ComboBoxLabel, &option, &p, nullptr);
|
qApp->style()->drawControl(QStyle::CE_ComboBoxLabel, &option, &p, nullptr);
|
||||||
});
|
});
|
||||||
return HighLevelRenderingPrimitive::Image { source: imgarray.to_resource() };
|
return HighLevelRenderingPrimitive::Image {
|
||||||
|
source: imgarray.to_resource(),
|
||||||
|
source_clip_rect: Default::default(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rendering_variables(
|
fn rendering_variables(
|
||||||
|
|
|
@ -45,6 +45,7 @@ fn gen_corelib(include_dir: &Path) -> anyhow::Result<()> {
|
||||||
"Rectangle",
|
"Rectangle",
|
||||||
"BorderRectangle",
|
"BorderRectangle",
|
||||||
"Image",
|
"Image",
|
||||||
|
"ClippedImage",
|
||||||
"TouchArea",
|
"TouchArea",
|
||||||
"Flickable",
|
"Flickable",
|
||||||
"Text",
|
"Text",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue