tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

animation.rs (8565B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 //! This example creates a 200x200 white rect and allows the user to move it
      6 //! around by using the arrow keys and rotate with '<'/'>'.
      7 //! It does this by using the animation API.
      8 
      9 //! The example also features seamless opaque/transparent split of a
     10 //! rounded cornered rectangle, which is done automatically during the
     11 //! scene building for render optimization.
     12 
     13 extern crate euclid;
     14 extern crate gleam;
     15 extern crate glutin;
     16 extern crate webrender;
     17 extern crate winit;
     18 
     19 #[path = "common/boilerplate.rs"]
     20 mod boilerplate;
     21 
     22 use crate::boilerplate::{Example, HandyDandyRectBuilder};
     23 use euclid::Angle;
     24 use webrender::api::*;
     25 use webrender::render_api::*;
     26 use webrender::api::units::*;
     27 
     28 
     29 struct App {
     30    property_key0: PropertyBindingKey<LayoutTransform>,
     31    property_key1: PropertyBindingKey<LayoutTransform>,
     32    property_key2: PropertyBindingKey<LayoutTransform>,
     33    opacity_key: PropertyBindingKey<f32>,
     34    opacity: f32,
     35    angle0: f32,
     36    angle1: f32,
     37    angle2: f32,
     38 }
     39 
     40 impl App {
     41    fn add_rounded_rect(
     42        &mut self,
     43        bounds: LayoutRect,
     44        color: ColorF,
     45        builder: &mut DisplayListBuilder,
     46        pipeline_id: PipelineId,
     47        property_key: PropertyBindingKey<LayoutTransform>,
     48        opacity_key: Option<PropertyBindingKey<f32>>,
     49        spatial_tree_item_key: SpatialTreeItemKey,
     50    ) {
     51        let filters = match opacity_key {
     52            Some(opacity_key) => {
     53                vec![
     54                    FilterOp::Opacity(PropertyBinding::Binding(opacity_key, self.opacity), self.opacity),
     55                ]
     56            }
     57            None => {
     58                vec![]
     59            }
     60        };
     61 
     62        let spatial_id = builder.push_reference_frame(
     63            bounds.min,
     64            SpatialId::root_scroll_node(pipeline_id),
     65            TransformStyle::Flat,
     66            PropertyBinding::Binding(property_key, LayoutTransform::identity()),
     67            ReferenceFrameKind::Transform {
     68                is_2d_scale_translation: false,
     69                should_snap: false,
     70                paired_with_perspective: false,
     71            },
     72            spatial_tree_item_key,
     73        );
     74 
     75        builder.push_simple_stacking_context_with_filters(
     76            LayoutPoint::zero(),
     77            spatial_id,
     78            PrimitiveFlags::IS_BACKFACE_VISIBLE,
     79            &filters,
     80            &[],
     81        );
     82 
     83        let space_and_clip = SpaceAndClipInfo {
     84            spatial_id,
     85            clip_chain_id: ClipChainId::INVALID,
     86        };
     87        let clip_bounds = LayoutRect::from_size(bounds.size());
     88        let complex_clip = ComplexClipRegion {
     89            rect: clip_bounds,
     90            radii: BorderRadius::uniform(30.0),
     91            mode: ClipMode::Clip,
     92        };
     93        let clip_id = builder.define_clip_rounded_rect(
     94            space_and_clip.spatial_id,
     95            complex_clip,
     96        );
     97        let clip_chain_id = builder.define_clip_chain(None, [clip_id]);
     98 
     99        // Fill it with a white rect
    100        builder.push_rect(
    101            &CommonItemProperties::new(
    102                LayoutRect::from_size(bounds.size()),
    103                SpaceAndClipInfo {
    104                    spatial_id,
    105                    clip_chain_id,
    106                }
    107            ),
    108            LayoutRect::from_size(bounds.size()),
    109            color,
    110        );
    111 
    112        builder.pop_stacking_context();
    113        builder.pop_reference_frame();
    114    }
    115 }
    116 
    117 impl Example for App {
    118    const WIDTH: u32 = 2048;
    119    const HEIGHT: u32 = 1536;
    120 
    121    fn render(
    122        &mut self,
    123        _api: &mut RenderApi,
    124        builder: &mut DisplayListBuilder,
    125        _txn: &mut Transaction,
    126        _device_size: DeviceIntSize,
    127        pipeline_id: PipelineId,
    128        _document_id: DocumentId,
    129    ) {
    130        let opacity_key = self.opacity_key;
    131 
    132        let bounds = (150, 150).to(250, 250);
    133        let key0 = self.property_key0;
    134        self.add_rounded_rect(
    135            bounds,
    136            ColorF::new(1.0, 0.0, 0.0, 0.5),
    137            builder,
    138            pipeline_id,
    139            key0,
    140            Some(opacity_key),
    141            SpatialTreeItemKey::new(0, 0)
    142        );
    143 
    144        let bounds = (400, 400).to(600, 600);
    145        let key1 = self.property_key1;
    146        self.add_rounded_rect(
    147            bounds,
    148            ColorF::new(0.0, 1.0, 0.0, 0.5),
    149            builder,
    150            pipeline_id,
    151            key1,
    152            None,
    153            SpatialTreeItemKey::new(0, 1)
    154        );
    155 
    156        let bounds = (200, 500).to(350, 580);
    157        let key2 = self.property_key2;
    158        self.add_rounded_rect(
    159            bounds,
    160            ColorF::new(0.0, 0.0, 1.0, 0.5),
    161            builder,
    162            pipeline_id,
    163            key2,
    164            None,
    165            SpatialTreeItemKey::new(0, 2)
    166        );
    167    }
    168 
    169    fn on_event(
    170        &mut self,
    171        win_event: winit::event::WindowEvent,
    172        _window: &winit::window::Window,
    173        api: &mut RenderApi,
    174        document_id: DocumentId
    175    ) -> bool {
    176        let mut rebuild_display_list = false;
    177 
    178        match win_event {
    179            winit::event::WindowEvent::KeyboardInput {
    180                input: winit::event::KeyboardInput {
    181                    state: winit::event::ElementState::Pressed,
    182                    virtual_keycode: Some(key),
    183                    ..
    184                },
    185                ..
    186            } => {
    187                let (delta_angle, delta_opacity) = match key {
    188                    winit::event::VirtualKeyCode::Down => (0.0, -0.1),
    189                    winit::event::VirtualKeyCode::Up => (0.0, 0.1),
    190                    winit::event::VirtualKeyCode::Right => (1.0, 0.0),
    191                    winit::event::VirtualKeyCode::Left => (-1.0, 0.0),
    192                    winit::event::VirtualKeyCode::R => {
    193                        rebuild_display_list = true;
    194                        (0.0, 0.0)
    195                    }
    196                    _ => return false,
    197                };
    198                // Update the transform based on the keyboard input and push it to
    199                // webrender using the generate_frame API. This will recomposite with
    200                // the updated transform.
    201                self.opacity += delta_opacity;
    202                self.angle0 += delta_angle * 0.1;
    203                self.angle1 += delta_angle * 0.2;
    204                self.angle2 -= delta_angle * 0.15;
    205                let xf0 = LayoutTransform::rotation(0.0, 0.0, 1.0, Angle::radians(self.angle0));
    206                let xf1 = LayoutTransform::rotation(0.0, 0.0, 1.0, Angle::radians(self.angle1));
    207                let xf2 = LayoutTransform::rotation(0.0, 0.0, 1.0, Angle::radians(self.angle2));
    208                let mut txn = Transaction::new();
    209                txn.reset_dynamic_properties();
    210                txn.append_dynamic_properties(
    211                    DynamicProperties {
    212                        transforms: vec![
    213                            PropertyValue {
    214                                key: self.property_key0,
    215                                value: xf0,
    216                            },
    217                            PropertyValue {
    218                                key: self.property_key1,
    219                                value: xf1,
    220                            },
    221                            PropertyValue {
    222                                key: self.property_key2,
    223                                value: xf2,
    224                            },
    225                        ],
    226                        floats: vec![
    227                            PropertyValue {
    228                                key: self.opacity_key,
    229                                value: self.opacity,
    230                            }
    231                        ],
    232                        colors: vec![],
    233                    },
    234                );
    235                txn.generate_frame(0, true, false, RenderReasons::empty());
    236                api.send_transaction(document_id, txn);
    237            }
    238            _ => (),
    239        }
    240 
    241        rebuild_display_list
    242    }
    243 }
    244 
    245 fn main() {
    246    let mut app = App {
    247        property_key0: PropertyBindingKey::new(42), // arbitrary magic number
    248        property_key1: PropertyBindingKey::new(44), // arbitrary magic number
    249        property_key2: PropertyBindingKey::new(45), // arbitrary magic number
    250        opacity_key: PropertyBindingKey::new(43),
    251        opacity: 0.5,
    252        angle0: 0.0,
    253        angle1: 0.0,
    254        angle2: 0.0,
    255    };
    256    boilerplate::main_wrapper(&mut app, None);
    257 }