зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 3 changesets (bug 1474300) on request by kats for introducing a crasher a=backout
Backed out changeset f7659b60b7b0 (bug 1474300) Backed out changeset a65429a135c7 (bug 1474300) Backed out changeset 376e702ed3ea (bug 1474300)
This commit is contained in:
Родитель
14976cd6b3
Коммит
1261098dca
|
@ -333,6 +333,15 @@ dependencies = [
|
|||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.6.0"
|
||||
|
@ -342,6 +351,14 @@ dependencies = [
|
|||
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.6.0"
|
||||
|
@ -349,22 +366,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.14.0"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-text"
|
||||
version = "10.0.0"
|
||||
version = "9.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -2350,9 +2367,9 @@ dependencies = [
|
|||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 10.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2379,8 +2396,8 @@ dependencies = [
|
|||
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2395,8 +2412,8 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2563,10 +2580,12 @@ dependencies = [
|
|||
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
|
||||
"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
|
||||
"checksum cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "746858cae4eae40fff37e1998320068df317bc247dc91a67c6cfa053afdc2abb"
|
||||
"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
|
||||
"checksum core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25"
|
||||
"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
|
||||
"checksum core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a"
|
||||
"checksum core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e54c4ab33705fa1fc8af375bb7929d68e1c1546c1ecef408966d8c3e49a1d84a"
|
||||
"checksum core-text 10.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f59bff773954e5cd058a3f5983406b52bec7cc65202bef340ba64a0c40ac91"
|
||||
"checksum core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb0ed45fdc32f9ab426238fba9407dfead7bacd7900c9b4dd3f396f46eafdae3"
|
||||
"checksum core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd581c37283d0c23311d179aefbb891f2324ee0405da58a26e8594ab76e5748"
|
||||
"checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
|
||||
"checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
|
||||
"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
|
||||
|
|
|
@ -71,6 +71,6 @@ freetype = { version = "0.4", default-features = false }
|
|||
dwrote = "0.4.1"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.6"
|
||||
core-graphics = "0.14"
|
||||
core-text = { version = "10", default-features = false }
|
||||
core-foundation = "0.5"
|
||||
core-graphics = "0.13"
|
||||
core-text = { version = "9.2.0", default-features = false }
|
||||
|
|
|
@ -475,8 +475,8 @@ impl AlphaBatchBuilder {
|
|||
|
||||
// Add each run in this picture to the batch.
|
||||
for run in &pic.runs {
|
||||
let transform_id =
|
||||
ctx.transforms.get_id(run.clip_and_scroll.scroll_node_id.transform_index());
|
||||
let scroll_node = &ctx.clip_scroll_tree.nodes[run.clip_and_scroll.scroll_node_id.0];
|
||||
let transform_id = ctx.transforms.get_id(scroll_node.transform_index);
|
||||
self.add_run_to_batch(
|
||||
run,
|
||||
transform_id,
|
||||
|
@ -670,7 +670,7 @@ impl AlphaBatchBuilder {
|
|||
debug_assert!(picture.surface.is_some());
|
||||
|
||||
let real_xf = &ctx.clip_scroll_tree
|
||||
.spatial_nodes[picture.reference_frame_index.0]
|
||||
.nodes[picture.reference_frame_index.0]
|
||||
.world_content_transform
|
||||
.into();
|
||||
let polygon = make_polygon(
|
||||
|
|
|
@ -7,11 +7,11 @@ use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D, L
|
|||
use api::{BoxShadowClipMode, LayoutToWorldScale, LineOrientation, LineStyle};
|
||||
use border::{ensure_no_corner_overlap};
|
||||
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
|
||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId, TransformIndex};
|
||||
use ellipse::Ellipse;
|
||||
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
|
||||
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
|
||||
use gpu_types::{BoxShadowStretchMode, TransformIndex};
|
||||
use gpu_types::{BoxShadowStretchMode};
|
||||
use prim_store::{ClipData, ImageMaskData};
|
||||
use render_task::to_cache_size;
|
||||
use resource_cache::{ImageRequest, ResourceCache};
|
||||
|
@ -257,39 +257,19 @@ impl ClipSource {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_rect(&self) -> bool {
|
||||
match *self {
|
||||
ClipSource::Rectangle(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_image_or_line_decoration_clip(&self) -> bool {
|
||||
match *self {
|
||||
ClipSource::Image(..) | ClipSource::LineDecoration(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClipSources {
|
||||
pub clips: Vec<(ClipSource, GpuCacheHandle)>,
|
||||
pub local_inner_rect: LayoutRect,
|
||||
pub local_outer_rect: Option<LayoutRect>,
|
||||
pub only_rectangular_clips: bool,
|
||||
pub has_image_or_line_decoration_clip: bool,
|
||||
pub local_outer_rect: Option<LayoutRect>
|
||||
}
|
||||
|
||||
impl ClipSources {
|
||||
pub fn new(clips: Vec<ClipSource>) -> Self {
|
||||
let (local_inner_rect, local_outer_rect) = Self::calculate_inner_and_outer_rects(&clips);
|
||||
|
||||
let has_image_or_line_decoration_clip =
|
||||
clips.iter().any(|clip| clip.is_image_or_line_decoration_clip());
|
||||
let only_rectangular_clips =
|
||||
!has_image_or_line_decoration_clip && clips.iter().all(|clip| clip.is_rect());
|
||||
let clips = clips
|
||||
.into_iter()
|
||||
.map(|clip| (clip, GpuCacheHandle::new()))
|
||||
|
@ -299,8 +279,6 @@ impl ClipSources {
|
|||
clips,
|
||||
local_inner_rect,
|
||||
local_outer_rect,
|
||||
only_rectangular_clips,
|
||||
has_image_or_line_decoration_clip,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::DevicePixelScale;
|
||||
use clip::{ClipChain, ClipChainNode, ClipSourcesHandle, ClipStore, ClipWorkItem};
|
||||
use clip_scroll_tree::{ClipChainIndex, SpatialNodeIndex};
|
||||
use gpu_cache::GpuCache;
|
||||
use resource_cache::ResourceCache;
|
||||
use spatial_node::SpatialNode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClipNode {
|
||||
/// The node that determines how this clip node is positioned.
|
||||
pub spatial_node: SpatialNodeIndex,
|
||||
|
||||
/// A handle to this clip nodes clips in the ClipStore.
|
||||
pub handle: Option<ClipSourcesHandle>,
|
||||
|
||||
/// An index to a ClipChain defined by this ClipNode's hiearchy in the display
|
||||
/// list.
|
||||
pub clip_chain_index: ClipChainIndex,
|
||||
|
||||
/// The index of the parent ClipChain of this node's hiearchical ClipChain.
|
||||
pub parent_clip_chain_index: ClipChainIndex,
|
||||
|
||||
/// A copy of the ClipChainNode this node would produce. We need to keep a copy,
|
||||
/// because the ClipChain may not contain our node if is optimized out, but API
|
||||
/// defined ClipChains will still need to access it.
|
||||
pub clip_chain_node: Option<ClipChainNode>,
|
||||
}
|
||||
|
||||
impl ClipNode {
|
||||
const EMPTY: ClipNode = ClipNode {
|
||||
spatial_node: SpatialNodeIndex(0),
|
||||
handle: None,
|
||||
clip_chain_index: ClipChainIndex(0),
|
||||
parent_clip_chain_index: ClipChainIndex(0),
|
||||
clip_chain_node: None,
|
||||
};
|
||||
|
||||
pub fn empty() -> ClipNode {
|
||||
ClipNode::EMPTY
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
spatial_node: &SpatialNode,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
clip_store: &mut ClipStore,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
clip_chains: &mut [ClipChain],
|
||||
) {
|
||||
let (clip_sources, weak_handle) = match self.handle {
|
||||
Some(ref handle) => (clip_store.get_mut(handle), handle.weak()),
|
||||
None => {
|
||||
warn!("Tried to process an empty clip node");
|
||||
return;
|
||||
}
|
||||
};
|
||||
clip_sources.update(gpu_cache, resource_cache, device_pixel_scale);
|
||||
|
||||
let (screen_inner_rect, screen_outer_rect) = clip_sources.get_screen_bounds(
|
||||
&spatial_node.world_content_transform,
|
||||
device_pixel_scale,
|
||||
None,
|
||||
);
|
||||
|
||||
// All clipping SpatialNodes should have outer rectangles, because they never
|
||||
// use the BorderCorner clip type and they always have at last one non-ClipOut
|
||||
// Rectangle ClipSource.
|
||||
let screen_outer_rect = screen_outer_rect
|
||||
.expect("Clipping node didn't have outer rect.");
|
||||
let local_outer_rect = clip_sources.local_outer_rect
|
||||
.expect("Clipping node didn't have outer rect.");
|
||||
|
||||
let new_node = ClipChainNode {
|
||||
work_item: ClipWorkItem {
|
||||
transform_index: self.spatial_node.transform_index(),
|
||||
clip_sources: weak_handle,
|
||||
coordinate_system_id: spatial_node.coordinate_system_id,
|
||||
},
|
||||
local_clip_rect: spatial_node
|
||||
.coordinate_system_relative_transform
|
||||
.transform_rect(&local_outer_rect),
|
||||
screen_outer_rect,
|
||||
screen_inner_rect,
|
||||
prev: None,
|
||||
};
|
||||
|
||||
let mut clip_chain =
|
||||
clip_chains[self.parent_clip_chain_index.0]
|
||||
.new_with_added_node(&new_node);
|
||||
|
||||
self.clip_chain_node = Some(new_node);
|
||||
clip_chain.parent_index = Some(self.parent_clip_chain_index);
|
||||
clip_chains[self.clip_chain_index.0] = clip_chain;
|
||||
}
|
||||
}
|
|
@ -1,19 +1,52 @@
|
|||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ExternalScrollId, LayoutPixel, LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
|
||||
use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollLocation};
|
||||
use api::{ScrollSensitivity, StickyOffsetBounds};
|
||||
use clip_scroll_tree::{CoordinateSystemId, SpatialNodeIndex, TransformUpdateState};
|
||||
use api::{DevicePixelScale, ExternalScrollId, LayoutPixel, LayoutPoint, LayoutRect, LayoutSize};
|
||||
use api::{LayoutVector2D, LayoutTransform, PipelineId, PropertyBinding};
|
||||
use api::{ScrollClamping, ScrollLocation, ScrollSensitivity, StickyOffsetBounds};
|
||||
use clip::{ClipChain, ClipChainNode, ClipSourcesHandle, ClipStore, ClipWorkItem};
|
||||
use clip_scroll_tree::{ClipChainIndex, ClipScrollNodeIndex, CoordinateSystemId};
|
||||
use clip_scroll_tree::{TransformUpdateState, TransformIndex};
|
||||
use euclid::SideOffsets2D;
|
||||
use gpu_types::{TransformData, TransformIndex, TransformPalette};
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::{TransformData, TransformPalette};
|
||||
use resource_cache::ResourceCache;
|
||||
use scene::SceneProperties;
|
||||
use util::{LayoutFastTransform, LayoutToWorldFastTransform, TransformedRectKind};
|
||||
use util::{LayoutToWorldFastTransform, LayoutFastTransform};
|
||||
use util::{TransformedRectKind};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum SpatialNodeType {
|
||||
#[derive(Debug)]
|
||||
pub struct StickyFrameInfo {
|
||||
pub frame_rect: LayoutRect,
|
||||
pub margins: SideOffsets2D<Option<f32>>,
|
||||
pub vertical_offset_bounds: StickyOffsetBounds,
|
||||
pub horizontal_offset_bounds: StickyOffsetBounds,
|
||||
pub previously_applied_offset: LayoutVector2D,
|
||||
pub current_offset: LayoutVector2D,
|
||||
}
|
||||
|
||||
impl StickyFrameInfo {
|
||||
pub fn new(
|
||||
frame_rect: LayoutRect,
|
||||
margins: SideOffsets2D<Option<f32>>,
|
||||
vertical_offset_bounds: StickyOffsetBounds,
|
||||
horizontal_offset_bounds: StickyOffsetBounds,
|
||||
previously_applied_offset: LayoutVector2D
|
||||
) -> StickyFrameInfo {
|
||||
StickyFrameInfo {
|
||||
frame_rect,
|
||||
margins,
|
||||
vertical_offset_bounds,
|
||||
horizontal_offset_bounds,
|
||||
previously_applied_offset,
|
||||
current_offset: LayoutVector2D::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SpatialNodeKind {
|
||||
/// A special kind of node that adjusts its position based on the position
|
||||
/// of its parent node and a given set of sticky positioning offset bounds.
|
||||
/// Sticky positioned is described in the CSS Positioned Layout Module Level 3 here:
|
||||
|
@ -26,25 +59,43 @@ pub enum SpatialNodeType {
|
|||
|
||||
/// A reference frame establishes a new coordinate space in the tree.
|
||||
ReferenceFrame(ReferenceFrameInfo),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum NodeType {
|
||||
Spatial {
|
||||
kind: SpatialNodeKind,
|
||||
},
|
||||
|
||||
/// Other nodes just do clipping, but no transformation.
|
||||
Clip {
|
||||
handle: ClipSourcesHandle,
|
||||
clip_chain_index: ClipChainIndex,
|
||||
|
||||
/// A copy of the ClipChainNode this node would produce. We need to keep a copy,
|
||||
/// because the ClipChain may not contain our node if is optimized out, but API
|
||||
/// defined ClipChains will still need to access it.
|
||||
clip_chain_node: Option<ClipChainNode>,
|
||||
},
|
||||
|
||||
/// An empty node, used to pad the ClipScrollTree's array of nodes so that
|
||||
/// we can immediately use each assigned SpatialNodeIndex. After display
|
||||
/// we can immediately use each assigned ClipScrollNodeIndex. After display
|
||||
/// list flattening this node type should never be used.
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl SpatialNodeType {
|
||||
impl NodeType {
|
||||
fn is_reference_frame(&self) -> bool {
|
||||
match *self {
|
||||
SpatialNodeType::ReferenceFrame(_) => true,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ReferenceFrame(_), .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains information common among all types of ClipScrollTree nodes.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SpatialNode {
|
||||
#[derive(Debug)]
|
||||
pub struct ClipScrollNode {
|
||||
/// The transformation for this viewport in world coordinates is the transformation for
|
||||
/// our parent reference frame, plus any accumulated scrolling offsets from nodes
|
||||
/// between our reference frame and this node. For reference frames, we also include
|
||||
|
@ -61,13 +112,13 @@ pub struct SpatialNode {
|
|||
pub pipeline_id: PipelineId,
|
||||
|
||||
/// Parent layer. If this is None, we are the root node.
|
||||
pub parent: Option<SpatialNodeIndex>,
|
||||
pub parent: Option<ClipScrollNodeIndex>,
|
||||
|
||||
/// Child layers
|
||||
pub children: Vec<SpatialNodeIndex>,
|
||||
pub children: Vec<ClipScrollNodeIndex>,
|
||||
|
||||
/// The type of this node and any data associated with that node type.
|
||||
pub node_type: SpatialNodeType,
|
||||
pub node_type: NodeType,
|
||||
|
||||
/// True if this node is transformed by an invertible transform. If not, display items
|
||||
/// transformed by this node will not be displayed and display items not transformed by this
|
||||
|
@ -81,15 +132,21 @@ pub struct SpatialNode {
|
|||
/// system (same coordinate system id) and us. This can change via scroll offsets and via new
|
||||
/// reference frame transforms.
|
||||
pub coordinate_system_relative_transform: LayoutFastTransform,
|
||||
|
||||
/// The index of the spatial node that provides positioning information for this node.
|
||||
/// For reference frames, scroll and sticky frames it is a unique identfier.
|
||||
/// For clip nodes, this is the nearest ancestor spatial node.
|
||||
pub transform_index: TransformIndex,
|
||||
}
|
||||
|
||||
impl SpatialNode {
|
||||
impl ClipScrollNode {
|
||||
pub fn new(
|
||||
pipeline_id: PipelineId,
|
||||
parent_index: Option<SpatialNodeIndex>,
|
||||
node_type: SpatialNodeType,
|
||||
parent_index: Option<ClipScrollNodeIndex>,
|
||||
node_type: NodeType,
|
||||
transform_index: TransformIndex,
|
||||
) -> Self {
|
||||
SpatialNode {
|
||||
ClipScrollNode {
|
||||
world_viewport_transform: LayoutToWorldFastTransform::identity(),
|
||||
world_content_transform: LayoutToWorldFastTransform::identity(),
|
||||
transform_kind: TransformedRectKind::AxisAligned,
|
||||
|
@ -100,22 +157,30 @@ impl SpatialNode {
|
|||
invertible: true,
|
||||
coordinate_system_id: CoordinateSystemId(0),
|
||||
coordinate_system_relative_transform: LayoutFastTransform::identity(),
|
||||
transform_index,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty() -> SpatialNode {
|
||||
Self::new(PipelineId::dummy(), None, SpatialNodeType::Empty)
|
||||
pub fn empty() -> ClipScrollNode {
|
||||
Self::new(
|
||||
PipelineId::dummy(),
|
||||
None,
|
||||
NodeType::Empty,
|
||||
TransformIndex(0),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_scroll_frame(
|
||||
pipeline_id: PipelineId,
|
||||
parent_index: SpatialNodeIndex,
|
||||
parent_index: ClipScrollNodeIndex,
|
||||
external_id: Option<ExternalScrollId>,
|
||||
frame_rect: &LayoutRect,
|
||||
content_size: &LayoutSize,
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
transform_index: TransformIndex,
|
||||
) -> Self {
|
||||
let node_type = SpatialNodeType::ScrollFrame(ScrollFrameInfo::new(
|
||||
let node_type = NodeType::Spatial {
|
||||
kind: SpatialNodeKind::ScrollFrame(ScrollFrameInfo::new(
|
||||
*frame_rect,
|
||||
scroll_sensitivity,
|
||||
LayoutSize::new(
|
||||
|
@ -123,18 +188,24 @@ impl SpatialNode {
|
|||
(content_size.height - frame_rect.size.height).max(0.0)
|
||||
),
|
||||
external_id,
|
||||
)
|
||||
);
|
||||
)),
|
||||
};
|
||||
|
||||
Self::new(pipeline_id, Some(parent_index), node_type)
|
||||
Self::new(
|
||||
pipeline_id,
|
||||
Some(parent_index),
|
||||
node_type,
|
||||
transform_index,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_reference_frame(
|
||||
parent_index: Option<SpatialNodeIndex>,
|
||||
parent_index: Option<ClipScrollNodeIndex>,
|
||||
source_transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
source_perspective: Option<LayoutTransform>,
|
||||
origin_in_parent_reference_frame: LayoutVector2D,
|
||||
pipeline_id: PipelineId,
|
||||
transform_index: TransformIndex,
|
||||
) -> Self {
|
||||
let identity = LayoutTransform::identity();
|
||||
let source_perspective = source_perspective.map_or_else(
|
||||
|
@ -146,25 +217,41 @@ impl SpatialNode {
|
|||
origin_in_parent_reference_frame,
|
||||
invertible: true,
|
||||
};
|
||||
Self::new(pipeline_id, parent_index, SpatialNodeType:: ReferenceFrame(info))
|
||||
Self::new(
|
||||
pipeline_id,
|
||||
parent_index,
|
||||
NodeType::Spatial {
|
||||
kind: SpatialNodeKind::ReferenceFrame(info),
|
||||
},
|
||||
transform_index,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_sticky_frame(
|
||||
parent_index: SpatialNodeIndex,
|
||||
parent_index: ClipScrollNodeIndex,
|
||||
sticky_frame_info: StickyFrameInfo,
|
||||
pipeline_id: PipelineId,
|
||||
transform_index: TransformIndex,
|
||||
) -> Self {
|
||||
Self::new(pipeline_id, Some(parent_index), SpatialNodeType::StickyFrame(sticky_frame_info))
|
||||
let node_type = NodeType::Spatial {
|
||||
kind: SpatialNodeKind::StickyFrame(sticky_frame_info),
|
||||
};
|
||||
Self::new(
|
||||
pipeline_id,
|
||||
Some(parent_index),
|
||||
node_type,
|
||||
transform_index,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
pub fn add_child(&mut self, child: SpatialNodeIndex) {
|
||||
pub fn add_child(&mut self, child: ClipScrollNodeIndex) {
|
||||
self.children.push(child);
|
||||
}
|
||||
|
||||
pub fn apply_old_scrolling_state(&mut self, old_scroll_info: &ScrollFrameInfo) {
|
||||
match self.node_type {
|
||||
SpatialNodeType::ScrollFrame(ref mut scrolling) => {
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(ref mut scrolling), .. } => {
|
||||
*scrolling = scrolling.combine_with_old_scroll_info(old_scroll_info);
|
||||
}
|
||||
_ if old_scroll_info.offset != LayoutVector2D::zero() => {
|
||||
|
@ -180,7 +267,7 @@ impl SpatialNode {
|
|||
let scrollable_height = scrollable_size.height;
|
||||
|
||||
let scrolling = match self.node_type {
|
||||
SpatialNodeType::ScrollFrame(ref mut scrolling) => scrolling,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(ref mut scrolling), .. } => scrolling,
|
||||
_ => {
|
||||
warn!("Tried to scroll a non-scroll node.");
|
||||
return false;
|
||||
|
@ -219,36 +306,41 @@ impl SpatialNode {
|
|||
pub fn push_gpu_data(
|
||||
&mut self,
|
||||
transform_palette: &mut TransformPalette,
|
||||
node_index: SpatialNodeIndex,
|
||||
) {
|
||||
let transform_index = TransformIndex(node_index.0 as u32);
|
||||
if !self.invertible {
|
||||
transform_palette.set(transform_index, TransformData::invalid());
|
||||
return;
|
||||
}
|
||||
|
||||
let inv_transform = match self.world_content_transform.inverse() {
|
||||
Some(inverted) => inverted.to_transform(),
|
||||
None => {
|
||||
transform_palette.set(transform_index, TransformData::invalid());
|
||||
if let NodeType::Spatial { .. } = self.node_type {
|
||||
if !self.invertible {
|
||||
transform_palette.set(self.transform_index, TransformData::invalid());
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let data = TransformData {
|
||||
transform: self.world_content_transform.into(),
|
||||
inv_transform,
|
||||
};
|
||||
let inv_transform = match self.world_content_transform.inverse() {
|
||||
Some(inverted) => inverted.to_transform(),
|
||||
None => {
|
||||
transform_palette.set(self.transform_index, TransformData::invalid());
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Write the data that will be made available to the GPU for this node.
|
||||
transform_palette.set(transform_index, data);
|
||||
let data = TransformData {
|
||||
transform: self.world_content_transform.into(),
|
||||
inv_transform,
|
||||
};
|
||||
|
||||
// Write the data that will be made available to the GPU for this node.
|
||||
transform_palette.set(self.transform_index, data);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
state: &mut TransformUpdateState,
|
||||
next_coordinate_system_id: &mut CoordinateSystemId,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
clip_store: &mut ClipStore,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
scene_properties: &SceneProperties,
|
||||
clip_chains: &mut Vec<ClipChain>,
|
||||
) {
|
||||
// If any of our parents was not rendered, we are not rendered either and can just
|
||||
// quit here.
|
||||
|
@ -269,12 +361,82 @@ impl SpatialNode {
|
|||
// For non-reference-frames we assume that they will produce only additional
|
||||
// translations which should be invertible.
|
||||
match self.node_type {
|
||||
SpatialNodeType::ReferenceFrame(info) if !info.invertible => {
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ReferenceFrame(info), .. } if !info.invertible => {
|
||||
self.mark_uninvertible();
|
||||
return;
|
||||
}
|
||||
_ => self.invertible = true,
|
||||
}
|
||||
|
||||
self.update_clip_work_item(
|
||||
state,
|
||||
device_pixel_scale,
|
||||
clip_store,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
clip_chains,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn update_clip_work_item(
|
||||
&mut self,
|
||||
state: &mut TransformUpdateState,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
clip_store: &mut ClipStore,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
clip_chains: &mut [ClipChain],
|
||||
) {
|
||||
let (clip_sources_handle, clip_chain_index, stored_clip_chain_node) = match self.node_type {
|
||||
NodeType::Clip { ref handle, clip_chain_index, ref mut clip_chain_node, .. } =>
|
||||
(handle, clip_chain_index, clip_chain_node),
|
||||
_ => {
|
||||
self.invertible = true;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let clip_sources = clip_store.get_mut(clip_sources_handle);
|
||||
clip_sources.update(
|
||||
gpu_cache,
|
||||
resource_cache,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
||||
let (screen_inner_rect, screen_outer_rect) = clip_sources.get_screen_bounds(
|
||||
&self.world_viewport_transform,
|
||||
device_pixel_scale,
|
||||
None,
|
||||
);
|
||||
|
||||
// All clipping ClipScrollNodes should have outer rectangles, because they never
|
||||
// use the BorderCorner clip type and they always have at last one non-ClipOut
|
||||
// Rectangle ClipSource.
|
||||
let screen_outer_rect = screen_outer_rect
|
||||
.expect("Clipping node didn't have outer rect.");
|
||||
let local_outer_rect = clip_sources.local_outer_rect
|
||||
.expect("Clipping node didn't have outer rect.");
|
||||
|
||||
let new_node = ClipChainNode {
|
||||
work_item: ClipWorkItem {
|
||||
transform_index: self.transform_index,
|
||||
clip_sources: clip_sources_handle.weak(),
|
||||
coordinate_system_id: state.current_coordinate_system_id,
|
||||
},
|
||||
local_clip_rect:
|
||||
self.coordinate_system_relative_transform.transform_rect(&local_outer_rect),
|
||||
screen_outer_rect,
|
||||
screen_inner_rect,
|
||||
prev: None,
|
||||
};
|
||||
|
||||
let mut clip_chain =
|
||||
clip_chains[state.parent_clip_chain_index.0].new_with_added_node(&new_node);
|
||||
|
||||
*stored_clip_chain_node = Some(new_node);
|
||||
clip_chain.parent_index = Some(state.parent_clip_chain_index);
|
||||
clip_chains[clip_chain_index.0] = clip_chain;
|
||||
state.parent_clip_chain_index = clip_chain_index;
|
||||
}
|
||||
|
||||
pub fn update_transform(
|
||||
|
@ -321,7 +483,7 @@ impl SpatialNode {
|
|||
self.coordinate_system_relative_transform =
|
||||
state.coordinate_system_relative_transform.offset(added_offset);
|
||||
|
||||
if let SpatialNodeType::StickyFrame(ref mut info) = self.node_type {
|
||||
if let NodeType::Spatial { kind: SpatialNodeKind::StickyFrame(ref mut info), .. } = self.node_type {
|
||||
info.current_offset = sticky_offset;
|
||||
}
|
||||
|
||||
|
@ -335,7 +497,7 @@ impl SpatialNode {
|
|||
scene_properties: &SceneProperties,
|
||||
) {
|
||||
let info = match self.node_type {
|
||||
SpatialNodeType::ReferenceFrame(ref mut info) => info,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ReferenceFrame(ref mut info), .. } => info,
|
||||
_ => unreachable!("Called update_transform_for_reference_frame on non-ReferenceFrame"),
|
||||
};
|
||||
|
||||
|
@ -383,7 +545,7 @@ impl SpatialNode {
|
|||
viewport_rect: &LayoutRect,
|
||||
) -> LayoutVector2D {
|
||||
let info = match self.node_type {
|
||||
SpatialNodeType::StickyFrame(ref info) => info,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::StickyFrame(ref info), .. } => info,
|
||||
_ => return LayoutVector2D::zero(),
|
||||
};
|
||||
|
||||
|
@ -497,43 +659,48 @@ impl SpatialNode {
|
|||
// between us and the parent reference frame. If we are a reference frame,
|
||||
// we need to reset both these values.
|
||||
match self.node_type {
|
||||
SpatialNodeType::StickyFrame(ref info) => {
|
||||
// We don't translate the combined rect by the sticky offset, because sticky
|
||||
// offsets actually adjust the node position itself, whereas scroll offsets
|
||||
// only apply to contents inside the node.
|
||||
state.parent_accumulated_scroll_offset =
|
||||
info.current_offset + state.parent_accumulated_scroll_offset;
|
||||
NodeType::Spatial { ref kind, .. } => {
|
||||
match *kind {
|
||||
SpatialNodeKind::StickyFrame(ref info) => {
|
||||
// We don't translate the combined rect by the sticky offset, because sticky
|
||||
// offsets actually adjust the node position itself, whereas scroll offsets
|
||||
// only apply to contents inside the node.
|
||||
state.parent_accumulated_scroll_offset =
|
||||
info.current_offset + state.parent_accumulated_scroll_offset;
|
||||
}
|
||||
SpatialNodeKind::ScrollFrame(ref scrolling) => {
|
||||
state.parent_accumulated_scroll_offset =
|
||||
scrolling.offset + state.parent_accumulated_scroll_offset;
|
||||
state.nearest_scrolling_ancestor_offset = scrolling.offset;
|
||||
state.nearest_scrolling_ancestor_viewport = scrolling.viewport_rect;
|
||||
}
|
||||
SpatialNodeKind::ReferenceFrame(ref info) => {
|
||||
state.parent_reference_frame_transform = self.world_viewport_transform;
|
||||
state.parent_accumulated_scroll_offset = LayoutVector2D::zero();
|
||||
state.coordinate_system_relative_transform =
|
||||
self.coordinate_system_relative_transform.clone();
|
||||
let translation = -info.origin_in_parent_reference_frame;
|
||||
state.nearest_scrolling_ancestor_viewport =
|
||||
state.nearest_scrolling_ancestor_viewport
|
||||
.translate(&translation);
|
||||
}
|
||||
}
|
||||
}
|
||||
SpatialNodeType::ScrollFrame(ref scrolling) => {
|
||||
state.parent_accumulated_scroll_offset =
|
||||
scrolling.offset + state.parent_accumulated_scroll_offset;
|
||||
state.nearest_scrolling_ancestor_offset = scrolling.offset;
|
||||
state.nearest_scrolling_ancestor_viewport = scrolling.viewport_rect;
|
||||
}
|
||||
SpatialNodeType::ReferenceFrame(ref info) => {
|
||||
state.parent_reference_frame_transform = self.world_viewport_transform;
|
||||
state.parent_accumulated_scroll_offset = LayoutVector2D::zero();
|
||||
state.coordinate_system_relative_transform =
|
||||
self.coordinate_system_relative_transform.clone();
|
||||
let translation = -info.origin_in_parent_reference_frame;
|
||||
state.nearest_scrolling_ancestor_viewport =
|
||||
state.nearest_scrolling_ancestor_viewport
|
||||
.translate(&translation);
|
||||
}
|
||||
SpatialNodeType::Empty => unreachable!("Empty node remaining in ClipScrollTree."),
|
||||
NodeType::Clip{ .. } => { }
|
||||
NodeType::Empty => unreachable!("Empty node remaining in ClipScrollTree."),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scrollable_size(&self) -> LayoutSize {
|
||||
match self.node_type {
|
||||
SpatialNodeType::ScrollFrame(state) => state.scrollable_size,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(state), .. } => state.scrollable_size,
|
||||
_ => LayoutSize::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll(&mut self, scroll_location: ScrollLocation) -> bool {
|
||||
let scrolling = match self.node_type {
|
||||
SpatialNodeType::ScrollFrame(ref mut scrolling) => scrolling,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(ref mut scrolling), .. } => scrolling,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
|
@ -583,14 +750,14 @@ impl SpatialNode {
|
|||
|
||||
pub fn scroll_offset(&self) -> LayoutVector2D {
|
||||
match self.node_type {
|
||||
SpatialNodeType::ScrollFrame(ref scrolling) => scrolling.offset,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(ref scrolling), .. } => scrolling.offset,
|
||||
_ => LayoutVector2D::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn matches_external_id(&self, external_id: ExternalScrollId) -> bool {
|
||||
match self.node_type {
|
||||
SpatialNodeType::ScrollFrame(info) if info.external_id == Some(external_id) => true,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(info), .. } if info.external_id == Some(external_id) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -675,32 +842,3 @@ pub struct ReferenceFrameInfo {
|
|||
/// True if the resolved transform is invertible.
|
||||
pub invertible: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StickyFrameInfo {
|
||||
pub frame_rect: LayoutRect,
|
||||
pub margins: SideOffsets2D<Option<f32>>,
|
||||
pub vertical_offset_bounds: StickyOffsetBounds,
|
||||
pub horizontal_offset_bounds: StickyOffsetBounds,
|
||||
pub previously_applied_offset: LayoutVector2D,
|
||||
pub current_offset: LayoutVector2D,
|
||||
}
|
||||
|
||||
impl StickyFrameInfo {
|
||||
pub fn new(
|
||||
frame_rect: LayoutRect,
|
||||
margins: SideOffsets2D<Option<f32>>,
|
||||
vertical_offset_bounds: StickyOffsetBounds,
|
||||
horizontal_offset_bounds: StickyOffsetBounds,
|
||||
previously_applied_offset: LayoutVector2D
|
||||
) -> StickyFrameInfo {
|
||||
StickyFrameInfo {
|
||||
frame_rect,
|
||||
margins,
|
||||
vertical_offset_bounds,
|
||||
horizontal_offset_bounds,
|
||||
previously_applied_offset,
|
||||
current_offset: LayoutVector2D::zero(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,14 +6,13 @@ use api::{DeviceIntRect, DevicePixelScale, ExternalScrollId, LayoutPoint, Layout
|
|||
use api::{PipelineId, ScrollClamping, ScrollLocation, ScrollNodeState};
|
||||
use api::{LayoutSize, LayoutTransform, PropertyBinding, ScrollSensitivity, WorldPoint};
|
||||
use clip::{ClipChain, ClipSourcesHandle, ClipStore};
|
||||
use clip_node::ClipNode;
|
||||
use clip_scroll_node::{ClipScrollNode, NodeType, SpatialNodeKind, ScrollFrameInfo, StickyFrameInfo};
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::{TransformIndex, TransformPalette};
|
||||
use gpu_types::TransformPalette;
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use print_tree::{PrintTree, PrintTreePrinter};
|
||||
use resource_cache::ResourceCache;
|
||||
use scene::SceneProperties;
|
||||
use spatial_node::{ScrollFrameInfo, SpatialNode, SpatialNodeType, StickyFrameInfo};
|
||||
use util::{LayoutFastTransform, LayoutToWorldFastTransform};
|
||||
|
||||
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
|
||||
|
@ -28,19 +27,19 @@ pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
|
|||
pub struct CoordinateSystemId(pub u32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
||||
pub struct SpatialNodeIndex(pub usize);
|
||||
pub struct ClipScrollNodeIndex(pub usize);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
||||
pub struct ClipNodeIndex(pub usize);
|
||||
// Used to index the smaller subset of nodes in the CST that define
|
||||
// new transform / positioning.
|
||||
// TODO(gw): In the future if we split the CST into a positioning and
|
||||
// clipping tree, this can be tidied up a bit.
|
||||
#[derive(Copy, Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct TransformIndex(pub u32);
|
||||
|
||||
impl SpatialNodeIndex {
|
||||
pub fn transform_index(&self) -> TransformIndex {
|
||||
TransformIndex(self.0 as u32)
|
||||
}
|
||||
}
|
||||
|
||||
const ROOT_REFERENCE_FRAME_INDEX: SpatialNodeIndex = SpatialNodeIndex(0);
|
||||
const TOPMOST_SCROLL_NODE_INDEX: SpatialNodeIndex = SpatialNodeIndex(1);
|
||||
const ROOT_REFERENCE_FRAME_INDEX: ClipScrollNodeIndex = ClipScrollNodeIndex(0);
|
||||
const TOPMOST_SCROLL_NODE_INDEX: ClipScrollNodeIndex = ClipScrollNodeIndex(1);
|
||||
|
||||
impl CoordinateSystemId {
|
||||
pub fn root() -> Self {
|
||||
|
@ -60,19 +59,14 @@ impl CoordinateSystemId {
|
|||
pub struct ClipChainDescriptor {
|
||||
pub index: ClipChainIndex,
|
||||
pub parent: Option<ClipChainIndex>,
|
||||
pub clips: Vec<ClipNodeIndex>,
|
||||
pub clips: Vec<ClipScrollNodeIndex>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct ClipChainIndex(pub usize);
|
||||
|
||||
pub struct ClipScrollTree {
|
||||
/// Nodes which determine the positions (offsets and transforms) for primitives
|
||||
/// and clips.
|
||||
pub spatial_nodes: Vec<SpatialNode>,
|
||||
|
||||
/// Nodes which clip primitives.
|
||||
pub clip_nodes: Vec<ClipNode>,
|
||||
pub nodes: Vec<ClipScrollNode>,
|
||||
|
||||
/// A Vec of all descriptors that describe ClipChains in the order in which they are
|
||||
/// encountered during display list flattening. ClipChains are expected to never be
|
||||
|
@ -88,6 +82,10 @@ pub struct ClipScrollTree {
|
|||
/// A set of pipelines which should be discarded the next time this
|
||||
/// tree is drained.
|
||||
pub pipelines_to_discard: FastHashSet<PipelineId>,
|
||||
|
||||
/// The number of nodes in the CST that are spatial. Currently, this is all
|
||||
/// nodes that are not clip nodes.
|
||||
spatial_node_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -97,6 +95,9 @@ pub struct TransformUpdateState {
|
|||
pub nearest_scrolling_ancestor_offset: LayoutVector2D,
|
||||
pub nearest_scrolling_ancestor_viewport: LayoutRect,
|
||||
|
||||
/// The index of the current parent's clip chain.
|
||||
pub parent_clip_chain_index: ClipChainIndex,
|
||||
|
||||
/// An id for keeping track of the axis-aligned space of this node. This is used in
|
||||
/// order to to track what kinds of clip optimizations can be done for a particular
|
||||
/// display list item, since optimizations can usually only be done among
|
||||
|
@ -115,35 +116,35 @@ pub struct TransformUpdateState {
|
|||
impl ClipScrollTree {
|
||||
pub fn new() -> Self {
|
||||
ClipScrollTree {
|
||||
spatial_nodes: Vec::new(),
|
||||
clip_nodes: Vec::new(),
|
||||
nodes: Vec::new(),
|
||||
clip_chains_descriptors: Vec::new(),
|
||||
clip_chains: vec![ClipChain::empty(&DeviceIntRect::zero())],
|
||||
pending_scroll_offsets: FastHashMap::default(),
|
||||
pipelines_to_discard: FastHashSet::default(),
|
||||
spatial_node_count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// The root reference frame, which is the true root of the ClipScrollTree. Initially
|
||||
/// this ID is not valid, which is indicated by ```spatial_nodes``` being empty.
|
||||
pub fn root_reference_frame_index(&self) -> SpatialNodeIndex {
|
||||
/// this ID is not valid, which is indicated by ```nodes``` being empty.
|
||||
pub fn root_reference_frame_index(&self) -> ClipScrollNodeIndex {
|
||||
// TODO(mrobinson): We should eventually make this impossible to misuse.
|
||||
debug_assert!(!self.spatial_nodes.is_empty());
|
||||
debug_assert!(!self.nodes.is_empty());
|
||||
ROOT_REFERENCE_FRAME_INDEX
|
||||
}
|
||||
|
||||
/// The root scroll node which is the first child of the root reference frame.
|
||||
/// Initially this ID is not valid, which is indicated by ```spatial_nodes``` being empty.
|
||||
pub fn topmost_scroll_node_index(&self) -> SpatialNodeIndex {
|
||||
/// Initially this ID is not valid, which is indicated by ```nodes``` being empty.
|
||||
pub fn topmost_scroll_node_index(&self) -> ClipScrollNodeIndex {
|
||||
// TODO(mrobinson): We should eventually make this impossible to misuse.
|
||||
debug_assert!(self.spatial_nodes.len() >= 1);
|
||||
debug_assert!(self.nodes.len() >= 1);
|
||||
TOPMOST_SCROLL_NODE_INDEX
|
||||
}
|
||||
|
||||
pub fn get_scroll_node_state(&self) -> Vec<ScrollNodeState> {
|
||||
let mut result = vec![];
|
||||
for node in &self.spatial_nodes {
|
||||
if let SpatialNodeType::ScrollFrame(info) = node.node_type {
|
||||
for node in &self.nodes {
|
||||
if let NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(info), .. } = node.node_type {
|
||||
if let Some(id) = info.external_id {
|
||||
result.push(ScrollNodeState { id, scroll_offset: info.offset })
|
||||
}
|
||||
|
@ -154,20 +155,20 @@ impl ClipScrollTree {
|
|||
|
||||
pub fn drain(&mut self) -> ScrollStates {
|
||||
let mut scroll_states = FastHashMap::default();
|
||||
for old_node in &mut self.spatial_nodes.drain(..) {
|
||||
for old_node in &mut self.nodes.drain(..) {
|
||||
if self.pipelines_to_discard.contains(&old_node.pipeline_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match old_node.node_type {
|
||||
SpatialNodeType::ScrollFrame(info) if info.external_id.is_some() => {
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(info), .. } if info.external_id.is_some() => {
|
||||
scroll_states.insert(info.external_id.unwrap(), info);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
self.clip_nodes.clear();
|
||||
self.spatial_node_count = 0;
|
||||
self.pipelines_to_discard.clear();
|
||||
self.clip_chains = vec![ClipChain::empty(&DeviceIntRect::zero())];
|
||||
self.clip_chains_descriptors.clear();
|
||||
|
@ -180,7 +181,7 @@ impl ClipScrollTree {
|
|||
id: ExternalScrollId,
|
||||
clamp: ScrollClamping
|
||||
) -> bool {
|
||||
for node in &mut self.spatial_nodes {
|
||||
for node in &mut self.nodes {
|
||||
if node.matches_external_id(id) {
|
||||
return node.set_scroll_origin(&origin, clamp);
|
||||
}
|
||||
|
@ -192,16 +193,16 @@ impl ClipScrollTree {
|
|||
|
||||
fn find_nearest_scrolling_ancestor(
|
||||
&self,
|
||||
index: Option<SpatialNodeIndex>
|
||||
) -> SpatialNodeIndex {
|
||||
index: Option<ClipScrollNodeIndex>
|
||||
) -> ClipScrollNodeIndex {
|
||||
let index = match index {
|
||||
Some(index) => index,
|
||||
None => return self.topmost_scroll_node_index(),
|
||||
};
|
||||
|
||||
let node = &self.spatial_nodes[index.0];
|
||||
let node = &self.nodes[index.0];
|
||||
match node.node_type {
|
||||
SpatialNodeType::ScrollFrame(state) if state.sensitive_to_input_events() => index,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(state), .. } if state.sensitive_to_input_events() => index,
|
||||
_ => self.find_nearest_scrolling_ancestor(node.parent)
|
||||
}
|
||||
}
|
||||
|
@ -209,13 +210,13 @@ impl ClipScrollTree {
|
|||
pub fn scroll_nearest_scrolling_ancestor(
|
||||
&mut self,
|
||||
scroll_location: ScrollLocation,
|
||||
node_index: Option<SpatialNodeIndex>,
|
||||
node_index: Option<ClipScrollNodeIndex>,
|
||||
) -> bool {
|
||||
if self.spatial_nodes.is_empty() {
|
||||
if self.nodes.is_empty() {
|
||||
return false;
|
||||
}
|
||||
let node_index = self.find_nearest_scrolling_ancestor(node_index);
|
||||
self.spatial_nodes[node_index.0].scroll(scroll_location)
|
||||
self.nodes[node_index.0].scroll(scroll_location)
|
||||
}
|
||||
|
||||
pub fn update_tree(
|
||||
|
@ -228,54 +229,50 @@ impl ClipScrollTree {
|
|||
pan: WorldPoint,
|
||||
scene_properties: &SceneProperties,
|
||||
) -> TransformPalette {
|
||||
let mut transform_palette = TransformPalette::new(self.spatial_nodes.len());
|
||||
if self.spatial_nodes.is_empty() {
|
||||
return transform_palette;
|
||||
}
|
||||
let mut transform_palette = TransformPalette::new(self.spatial_node_count);
|
||||
|
||||
self.clip_chains[0] = ClipChain::empty(screen_rect);
|
||||
if !self.nodes.is_empty() {
|
||||
self.clip_chains[0] = ClipChain::empty(screen_rect);
|
||||
|
||||
let root_reference_frame_index = self.root_reference_frame_index();
|
||||
let mut state = TransformUpdateState {
|
||||
parent_reference_frame_transform: LayoutVector2D::new(pan.x, pan.y).into(),
|
||||
parent_accumulated_scroll_offset: LayoutVector2D::zero(),
|
||||
nearest_scrolling_ancestor_offset: LayoutVector2D::zero(),
|
||||
nearest_scrolling_ancestor_viewport: LayoutRect::zero(),
|
||||
current_coordinate_system_id: CoordinateSystemId::root(),
|
||||
coordinate_system_relative_transform: LayoutFastTransform::identity(),
|
||||
invertible: true,
|
||||
};
|
||||
|
||||
let mut next_coordinate_system_id = state.current_coordinate_system_id.next();
|
||||
self.update_node(
|
||||
root_reference_frame_index,
|
||||
&mut state,
|
||||
&mut next_coordinate_system_id,
|
||||
&mut transform_palette,
|
||||
scene_properties,
|
||||
);
|
||||
|
||||
for clip_node in &mut self.clip_nodes {
|
||||
let spatial_node = &self.spatial_nodes[clip_node.spatial_node.0];
|
||||
clip_node.update(
|
||||
spatial_node,
|
||||
let root_reference_frame_index = self.root_reference_frame_index();
|
||||
let mut state = TransformUpdateState {
|
||||
parent_reference_frame_transform: LayoutVector2D::new(pan.x, pan.y).into(),
|
||||
parent_accumulated_scroll_offset: LayoutVector2D::zero(),
|
||||
nearest_scrolling_ancestor_offset: LayoutVector2D::zero(),
|
||||
nearest_scrolling_ancestor_viewport: LayoutRect::zero(),
|
||||
parent_clip_chain_index: ClipChainIndex(0),
|
||||
current_coordinate_system_id: CoordinateSystemId::root(),
|
||||
coordinate_system_relative_transform: LayoutFastTransform::identity(),
|
||||
invertible: true,
|
||||
};
|
||||
let mut next_coordinate_system_id = state.current_coordinate_system_id.next();
|
||||
self.update_node(
|
||||
root_reference_frame_index,
|
||||
&mut state,
|
||||
&mut next_coordinate_system_id,
|
||||
device_pixel_scale,
|
||||
clip_store,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
&mut self.clip_chains,
|
||||
&mut transform_palette,
|
||||
scene_properties,
|
||||
);
|
||||
|
||||
self.build_clip_chains(screen_rect);
|
||||
}
|
||||
self.build_clip_chains(screen_rect);
|
||||
|
||||
transform_palette
|
||||
}
|
||||
|
||||
fn update_node(
|
||||
&mut self,
|
||||
node_index: SpatialNodeIndex,
|
||||
node_index: ClipScrollNodeIndex,
|
||||
state: &mut TransformUpdateState,
|
||||
next_coordinate_system_id: &mut CoordinateSystemId,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
clip_store: &mut ClipStore,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
transform_palette: &mut TransformPalette,
|
||||
scene_properties: &SceneProperties,
|
||||
) {
|
||||
|
@ -283,13 +280,23 @@ impl ClipScrollTree {
|
|||
// Restructure this to avoid the clones!
|
||||
let mut state = state.clone();
|
||||
let node_children = {
|
||||
let node = match self.spatial_nodes.get_mut(node_index.0) {
|
||||
let node = match self.nodes.get_mut(node_index.0) {
|
||||
Some(node) => node,
|
||||
None => return,
|
||||
};
|
||||
|
||||
node.update(&mut state, next_coordinate_system_id, scene_properties);
|
||||
node.push_gpu_data(transform_palette, node_index);
|
||||
node.update(
|
||||
&mut state,
|
||||
next_coordinate_system_id,
|
||||
device_pixel_scale,
|
||||
clip_store,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
scene_properties,
|
||||
&mut self.clip_chains,
|
||||
);
|
||||
|
||||
node.push_gpu_data(transform_palette);
|
||||
|
||||
if node.children.is_empty() {
|
||||
return;
|
||||
|
@ -304,6 +311,10 @@ impl ClipScrollTree {
|
|||
child_node_index,
|
||||
&mut state,
|
||||
next_coordinate_system_id,
|
||||
device_pixel_scale,
|
||||
clip_store,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
transform_palette,
|
||||
scene_properties,
|
||||
);
|
||||
|
@ -313,21 +324,22 @@ impl ClipScrollTree {
|
|||
pub fn build_clip_chains(&mut self, screen_rect: &DeviceIntRect) {
|
||||
for descriptor in &self.clip_chains_descriptors {
|
||||
// A ClipChain is an optional parent (which is another ClipChain) and a list of
|
||||
// SpatialNode clipping nodes. Here we start the ClipChain with a clone of the
|
||||
// ClipScrollNode clipping nodes. Here we start the ClipChain with a clone of the
|
||||
// parent's node, if necessary.
|
||||
let mut chain = match descriptor.parent {
|
||||
Some(index) => self.clip_chains[index.0].clone(),
|
||||
None => ClipChain::empty(screen_rect),
|
||||
};
|
||||
|
||||
// Now we walk through each ClipNode in the vector and extract their ClipChain nodes to
|
||||
// construct the final list.
|
||||
// Now we walk through each ClipScrollNode in the vector of clip nodes and
|
||||
// extract their ClipChain nodes to construct the final list.
|
||||
for clip_index in &descriptor.clips {
|
||||
match self.clip_nodes[clip_index.0] {
|
||||
ClipNode { clip_chain_node: Some(ref node), .. } => {
|
||||
match self.nodes[clip_index.0].node_type {
|
||||
NodeType::Clip { clip_chain_node: Some(ref node), .. } => {
|
||||
chain.add_node(node.clone());
|
||||
}
|
||||
ClipNode { .. } => warn!("Found uninitialized clipping ClipNode."),
|
||||
NodeType::Clip { .. } => warn!("Found uninitialized clipping ClipScrollNode."),
|
||||
_ => warn!("Tried to create a clip chain with non-clipping node."),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -337,9 +349,9 @@ impl ClipScrollTree {
|
|||
}
|
||||
|
||||
pub fn finalize_and_apply_pending_scroll_offsets(&mut self, old_states: ScrollStates) {
|
||||
for node in &mut self.spatial_nodes {
|
||||
for node in &mut self.nodes {
|
||||
let external_id = match node.node_type {
|
||||
SpatialNodeType::ScrollFrame(ScrollFrameInfo { external_id: Some(id), ..} ) => id,
|
||||
NodeType::Spatial { kind: SpatialNodeKind::ScrollFrame(ScrollFrameInfo { external_id: Some(id), ..} ), .. } => id,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
|
@ -353,131 +365,133 @@ impl ClipScrollTree {
|
|||
}
|
||||
}
|
||||
|
||||
// Generate the next valid TransformIndex for the CST.
|
||||
fn next_transform_index(&mut self) -> TransformIndex {
|
||||
let transform_index = TransformIndex(self.spatial_node_count as u32);
|
||||
self.spatial_node_count += 1;
|
||||
transform_index
|
||||
}
|
||||
|
||||
pub fn add_clip_node(
|
||||
&mut self,
|
||||
index: ClipNodeIndex,
|
||||
parent_clip_chain_index: ClipChainIndex,
|
||||
spatial_node: SpatialNodeIndex,
|
||||
index: ClipScrollNodeIndex,
|
||||
parent_index: ClipScrollNodeIndex,
|
||||
handle: ClipSourcesHandle,
|
||||
pipeline_id: PipelineId,
|
||||
) -> ClipChainIndex {
|
||||
let clip_chain_index = self.allocate_clip_chain();
|
||||
let node = ClipNode {
|
||||
parent_clip_chain_index,
|
||||
spatial_node,
|
||||
handle: Some(handle),
|
||||
let transform_index = self.nodes[parent_index.0].transform_index;
|
||||
|
||||
let node_type = NodeType::Clip {
|
||||
handle,
|
||||
clip_chain_index,
|
||||
clip_chain_node: None,
|
||||
};
|
||||
self.push_clip_node(node, index);
|
||||
let node = ClipScrollNode::new(
|
||||
pipeline_id,
|
||||
Some(parent_index),
|
||||
node_type,
|
||||
transform_index,
|
||||
);
|
||||
self.add_node(node, index);
|
||||
clip_chain_index
|
||||
}
|
||||
|
||||
pub fn add_scroll_frame(
|
||||
&mut self,
|
||||
index: SpatialNodeIndex,
|
||||
parent_index: SpatialNodeIndex,
|
||||
index: ClipScrollNodeIndex,
|
||||
parent_index: ClipScrollNodeIndex,
|
||||
external_id: Option<ExternalScrollId>,
|
||||
pipeline_id: PipelineId,
|
||||
frame_rect: &LayoutRect,
|
||||
content_size: &LayoutSize,
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
) {
|
||||
let node = SpatialNode::new_scroll_frame(
|
||||
let node = ClipScrollNode::new_scroll_frame(
|
||||
pipeline_id,
|
||||
parent_index,
|
||||
external_id,
|
||||
frame_rect,
|
||||
content_size,
|
||||
scroll_sensitivity,
|
||||
self.next_transform_index(),
|
||||
);
|
||||
self.add_spatial_node(node, index);
|
||||
self.add_node(node, index);
|
||||
}
|
||||
|
||||
pub fn add_reference_frame(
|
||||
&mut self,
|
||||
index: SpatialNodeIndex,
|
||||
parent_index: Option<SpatialNodeIndex>,
|
||||
index: ClipScrollNodeIndex,
|
||||
parent_index: Option<ClipScrollNodeIndex>,
|
||||
source_transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
source_perspective: Option<LayoutTransform>,
|
||||
origin_in_parent_reference_frame: LayoutVector2D,
|
||||
pipeline_id: PipelineId,
|
||||
) {
|
||||
let node = SpatialNode::new_reference_frame(
|
||||
let node = ClipScrollNode::new_reference_frame(
|
||||
parent_index,
|
||||
source_transform,
|
||||
source_perspective,
|
||||
origin_in_parent_reference_frame,
|
||||
pipeline_id,
|
||||
self.next_transform_index(),
|
||||
);
|
||||
self.add_spatial_node(node, index);
|
||||
self.add_node(node, index);
|
||||
}
|
||||
|
||||
pub fn add_sticky_frame(
|
||||
&mut self,
|
||||
index: SpatialNodeIndex,
|
||||
parent_index: SpatialNodeIndex,
|
||||
index: ClipScrollNodeIndex,
|
||||
parent_index: ClipScrollNodeIndex,
|
||||
sticky_frame_info: StickyFrameInfo,
|
||||
pipeline_id: PipelineId,
|
||||
) {
|
||||
let node = SpatialNode::new_sticky_frame(
|
||||
let node = ClipScrollNode::new_sticky_frame(
|
||||
parent_index,
|
||||
sticky_frame_info,
|
||||
pipeline_id,
|
||||
self.next_transform_index(),
|
||||
);
|
||||
self.add_spatial_node(node, index);
|
||||
self.add_node(node, index);
|
||||
}
|
||||
|
||||
pub fn add_clip_chain_descriptor(
|
||||
&mut self,
|
||||
parent: Option<ClipChainIndex>,
|
||||
clips: Vec<ClipNodeIndex>
|
||||
clips: Vec<ClipScrollNodeIndex>
|
||||
) -> ClipChainIndex {
|
||||
let index = self.allocate_clip_chain();
|
||||
self.clip_chains_descriptors.push(ClipChainDescriptor { index, parent, clips });
|
||||
index
|
||||
}
|
||||
|
||||
pub fn push_clip_node(&mut self, node: ClipNode, index: ClipNodeIndex) {
|
||||
if index.0 == self.clip_nodes.len() {
|
||||
self.clip_nodes.push(node);
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(empty_node) = self.clip_nodes.get_mut(index.0) {
|
||||
*empty_node = node;
|
||||
return
|
||||
}
|
||||
|
||||
let length_to_reserve = index.0 + 1 - self.clip_nodes.len();
|
||||
self.clip_nodes.reserve_exact(length_to_reserve);
|
||||
|
||||
// We would like to use `Vec::resize` here, but the Clone trait is not supported
|
||||
// for ClipNodes. We can fix this either when support is added for something like
|
||||
// `Vec::resize_default`.
|
||||
let length_to_extend = self.clip_nodes.len() .. index.0;
|
||||
self.clip_nodes.extend(length_to_extend.map(|_| ClipNode::empty()));
|
||||
self.clip_nodes.push(node);
|
||||
}
|
||||
|
||||
pub fn add_spatial_node(&mut self, node: SpatialNode, index: SpatialNodeIndex) {
|
||||
pub fn add_node(&mut self, node: ClipScrollNode, index: ClipScrollNodeIndex) {
|
||||
// When the parent node is None this means we are adding the root.
|
||||
if let Some(parent_index) = node.parent {
|
||||
self.spatial_nodes[parent_index.0].add_child(index);
|
||||
self.nodes[parent_index.0].add_child(index);
|
||||
}
|
||||
|
||||
if index.0 == self.spatial_nodes.len() {
|
||||
self.spatial_nodes.push(node);
|
||||
if index.0 == self.nodes.len() {
|
||||
self.nodes.push(node);
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(empty_node) = self.spatial_nodes.get_mut(index.0) {
|
||||
|
||||
if let Some(empty_node) = self.nodes.get_mut(index.0) {
|
||||
*empty_node = node;
|
||||
return
|
||||
}
|
||||
|
||||
debug_assert!(index.0 > self.spatial_nodes.len() - 1);
|
||||
self.spatial_nodes.resize(index.0, SpatialNode::empty());
|
||||
self.spatial_nodes.push(node);
|
||||
let length_to_reserve = index.0 + 1 - self.nodes.len();
|
||||
self.nodes.reserve_exact(length_to_reserve);
|
||||
|
||||
// We would like to use `Vec::resize` here, but the Clone trait is not supported
|
||||
// for ClipScrollNodes. We can fix this either by splitting the clip nodes out into
|
||||
// their own tree or when support is added for something like `Vec::resize_default`.
|
||||
let length_to_extend = self.nodes.len() .. index.0;
|
||||
self.nodes.extend(length_to_extend.map(|_| ClipScrollNode::empty()));
|
||||
|
||||
self.nodes.push(node);
|
||||
}
|
||||
|
||||
pub fn discard_frame_state_for_pipeline(&mut self, pipeline_id: PipelineId) {
|
||||
|
@ -486,29 +500,44 @@ impl ClipScrollTree {
|
|||
|
||||
fn print_node<T: PrintTreePrinter>(
|
||||
&self,
|
||||
index: SpatialNodeIndex,
|
||||
index: ClipScrollNodeIndex,
|
||||
pt: &mut T,
|
||||
clip_store: &ClipStore
|
||||
) {
|
||||
let node = &self.spatial_nodes[index.0];
|
||||
let node = &self.nodes[index.0];
|
||||
match node.node_type {
|
||||
SpatialNodeType::StickyFrame(ref sticky_frame_info) => {
|
||||
pt.new_level(format!("StickyFrame"));
|
||||
pt.add_item(format!("index: {:?}", index));
|
||||
pt.add_item(format!("sticky info: {:?}", sticky_frame_info));
|
||||
NodeType::Spatial { ref kind, .. } => {
|
||||
match *kind {
|
||||
SpatialNodeKind::StickyFrame(ref sticky_frame_info) => {
|
||||
pt.new_level(format!("StickyFrame"));
|
||||
pt.add_item(format!("index: {:?}", index));
|
||||
pt.add_item(format!("sticky info: {:?}", sticky_frame_info));
|
||||
}
|
||||
SpatialNodeKind::ScrollFrame(scrolling_info) => {
|
||||
pt.new_level(format!("ScrollFrame"));
|
||||
pt.add_item(format!("index: {:?}", index));
|
||||
pt.add_item(format!("viewport: {:?}", scrolling_info.viewport_rect));
|
||||
pt.add_item(format!("scrollable_size: {:?}", scrolling_info.scrollable_size));
|
||||
pt.add_item(format!("scroll offset: {:?}", scrolling_info.offset));
|
||||
}
|
||||
SpatialNodeKind::ReferenceFrame(ref info) => {
|
||||
pt.new_level(format!("ReferenceFrame {:?}", info.resolved_transform));
|
||||
pt.add_item(format!("index: {:?}", index));
|
||||
}
|
||||
}
|
||||
}
|
||||
SpatialNodeType::ScrollFrame(scrolling_info) => {
|
||||
pt.new_level(format!("ScrollFrame"));
|
||||
NodeType::Clip { ref handle, .. } => {
|
||||
pt.new_level("Clip".to_owned());
|
||||
|
||||
pt.add_item(format!("index: {:?}", index));
|
||||
pt.add_item(format!("viewport: {:?}", scrolling_info.viewport_rect));
|
||||
pt.add_item(format!("scrollable_size: {:?}", scrolling_info.scrollable_size));
|
||||
pt.add_item(format!("scroll offset: {:?}", scrolling_info.offset));
|
||||
let clips = clip_store.get(handle).clips();
|
||||
pt.new_level(format!("Clip Sources [{}]", clips.len()));
|
||||
for source in clips {
|
||||
pt.add_item(format!("{:?}", source));
|
||||
}
|
||||
pt.end_level();
|
||||
}
|
||||
SpatialNodeType::ReferenceFrame(ref info) => {
|
||||
pt.new_level(format!("ReferenceFrame {:?}", info.resolved_transform));
|
||||
pt.add_item(format!("index: {:?}", index));
|
||||
}
|
||||
SpatialNodeType::Empty => unreachable!("Empty node remaining in ClipScrollTree."),
|
||||
NodeType::Empty => unreachable!("Empty node remaining in ClipScrollTree."),
|
||||
}
|
||||
|
||||
pt.add_item(format!("world_viewport_transform: {:?}", node.world_viewport_transform));
|
||||
|
@ -524,14 +553,14 @@ impl ClipScrollTree {
|
|||
|
||||
#[allow(dead_code)]
|
||||
pub fn print(&self, clip_store: &ClipStore) {
|
||||
if !self.spatial_nodes.is_empty() {
|
||||
if !self.nodes.is_empty() {
|
||||
let mut pt = PrintTree::new("clip_scroll tree");
|
||||
self.print_with(clip_store, &mut pt);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_with<T: PrintTreePrinter>(&self, clip_store: &ClipStore, pt: &mut T) {
|
||||
if !self.spatial_nodes.is_empty() {
|
||||
if !self.nodes.is_empty() {
|
||||
self.print_node(self.root_reference_frame_index(), pt, clip_store);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ use api::{PropertyBinding, ReferenceFrame, RepeatMode, ScrollFrameDisplayItem, S
|
|||
use api::{Shadow, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
||||
use api::{TransformStyle, YuvColorSpace, YuvData};
|
||||
use clip::{ClipRegion, ClipSource, ClipSources, ClipStore};
|
||||
use clip_scroll_tree::{ClipChainIndex, ClipNodeIndex, ClipScrollTree, SpatialNodeIndex};
|
||||
use clip_scroll_node::{NodeType, SpatialNodeKind, StickyFrameInfo};
|
||||
use clip_scroll_tree::{ClipChainIndex, ClipScrollNodeIndex, ClipScrollTree};
|
||||
use euclid::vec2;
|
||||
use frame_builder::{ChasePrimitive, FrameBuilder, FrameBuilderConfig};
|
||||
use glyph_rasterizer::FontInstance;
|
||||
|
@ -32,7 +33,6 @@ use render_backend::{DocumentView};
|
|||
use resource_cache::{FontInstanceMap, ImageRequest};
|
||||
use scene::{Scene, ScenePipeline, StackingContextHelpers};
|
||||
use scene_builder::{BuiltScene, SceneRequest};
|
||||
use spatial_node::{SpatialNodeType, StickyFrameInfo};
|
||||
use std::{f32, mem, usize};
|
||||
use tiling::{CompositeOps, ScrollbarPrimitive};
|
||||
use util::{MaxRect, RectHelpers, recycle_vec};
|
||||
|
@ -44,16 +44,9 @@ static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF {
|
|||
a: 0.6,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PipelineOffset {
|
||||
pipeline: PipelineId,
|
||||
spatial_offset: usize,
|
||||
clip_offset: usize,
|
||||
}
|
||||
|
||||
/// A data structure that keeps track of mapping between API ClipIds and the indices used
|
||||
/// internally in the ClipScrollTree to avoid having to do HashMap lookups. ClipIdToIndexMapper is
|
||||
/// responsible for mapping both ClipId to ClipChainIndex and ClipId to SpatialNodeIndex. We
|
||||
/// responsible for mapping both ClipId to ClipChainIndex and ClipId to ClipScrollNodeIndex. We
|
||||
/// also include two small LRU caches. Currently the caches are small (1 entry), but in the future
|
||||
/// we could use uluru here to do something more involved.
|
||||
#[derive(Default)]
|
||||
|
@ -67,23 +60,18 @@ pub struct ClipIdToIndexMapper {
|
|||
/// HashMap lookups.
|
||||
cached_clip_chain_index: Option<(ClipId, ClipChainIndex)>,
|
||||
|
||||
/// The offset in the ClipScrollTree's array of SpatialNodes and ClipNodes for a particular
|
||||
/// pipeline. This is used to convert ClipIds into SpatialNodeIndex or ClipNodeIndex.
|
||||
pipeline_offsets: FastHashMap<PipelineId, PipelineOffset>,
|
||||
/// The offset in the ClipScrollTree's array of ClipScrollNodes for a particular pipeline.
|
||||
/// This is used to convert a ClipId into a ClipScrollNodeIndex.
|
||||
pipeline_offsets: FastHashMap<PipelineId, usize>,
|
||||
|
||||
/// The last mapped pipeline offset for this mapper. This is used to avoid having to
|
||||
/// consult `pipeline_offsets` repeatedly when flattening the display list.
|
||||
cached_pipeline_offset: Option<PipelineOffset>,
|
||||
cached_pipeline_offset: Option<(PipelineId, usize)>,
|
||||
|
||||
/// The next available pipeline offset for ClipNodeIndex. When we encounter a pipeline
|
||||
/// we will use this value and increment it by the total number of clip nodes in the
|
||||
/// The next available pipeline offset for ClipScrollNodeIndex. When we encounter a pipeline
|
||||
/// we will use this value and increment it by the total number of ClipScrollNodes in the
|
||||
/// pipeline's display list.
|
||||
next_available_clip_offset: usize,
|
||||
|
||||
/// The next available pipeline offset for SpatialNodeIndex. When we encounter a pipeline
|
||||
/// we will use this value and increment it by the total number of spatial nodes in the
|
||||
/// pipeline's display list.
|
||||
next_available_spatial_offset: usize,
|
||||
next_available_offset: usize,
|
||||
}
|
||||
|
||||
impl ClipIdToIndexMapper {
|
||||
|
@ -113,46 +101,39 @@ impl ClipIdToIndexMapper {
|
|||
index
|
||||
}
|
||||
|
||||
pub fn map_clip_and_scroll(&mut self, info: &ClipAndScrollInfo) -> ScrollNodeAndClipChain {
|
||||
ScrollNodeAndClipChain::new(
|
||||
self.get_node_index(info.scroll_node_id),
|
||||
self.get_clip_chain_index_and_cache_result(&info.clip_node_id())
|
||||
)
|
||||
}
|
||||
|
||||
pub fn simple_scroll_and_clip_chain(&mut self, id: &ClipId) -> ScrollNodeAndClipChain {
|
||||
self.map_clip_and_scroll(&ClipAndScrollInfo::simple(*id))
|
||||
}
|
||||
|
||||
pub fn initialize_for_pipeline(&mut self, pipeline: &ScenePipeline) {
|
||||
debug_assert!(!self.pipeline_offsets.contains_key(&pipeline.pipeline_id));
|
||||
self.pipeline_offsets.insert(
|
||||
pipeline.pipeline_id,
|
||||
PipelineOffset {
|
||||
pipeline: pipeline.pipeline_id,
|
||||
spatial_offset: self.next_available_spatial_offset,
|
||||
clip_offset: self.next_available_clip_offset,
|
||||
}
|
||||
);
|
||||
|
||||
self.next_available_clip_offset += pipeline.display_list.total_clip_nodes();
|
||||
self.next_available_spatial_offset += pipeline.display_list.total_spatial_nodes();
|
||||
self.pipeline_offsets.insert(pipeline.pipeline_id, self.next_available_offset);
|
||||
self.next_available_offset += pipeline.display_list.total_clip_ids();
|
||||
}
|
||||
|
||||
pub fn get_pipeline_offet<'a>(&'a mut self, id: PipelineId) -> &'a PipelineOffset {
|
||||
match self.cached_pipeline_offset {
|
||||
Some(ref offset) if offset.pipeline == id => offset,
|
||||
pub fn get_node_index(&mut self, id: ClipId) -> ClipScrollNodeIndex {
|
||||
let (index, pipeline_id) = match id {
|
||||
ClipId::Clip(index, pipeline_id) => (index, pipeline_id),
|
||||
ClipId::ClipChain(_) => panic!("Tried to use ClipChain as scroll node."),
|
||||
};
|
||||
|
||||
let pipeline_offset = match self.cached_pipeline_offset {
|
||||
Some((last_used_id, offset)) if last_used_id == pipeline_id => offset,
|
||||
_ => {
|
||||
let offset = &self.pipeline_offsets[&id];
|
||||
self.cached_pipeline_offset = Some(*offset);
|
||||
let offset = self.pipeline_offsets[&pipeline_id];
|
||||
self.cached_pipeline_offset = Some((pipeline_id, offset));
|
||||
offset
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn get_clip_node_index(&mut self, id: ClipId) -> ClipNodeIndex {
|
||||
match id {
|
||||
ClipId::Clip(index, pipeline_id) => {
|
||||
let pipeline_offset = self.get_pipeline_offet(pipeline_id);
|
||||
ClipNodeIndex(pipeline_offset.clip_offset + index)
|
||||
}
|
||||
ClipId::Spatial(..) => {
|
||||
// We could theoretically map back to the containing clip node with the current
|
||||
// design, but we will eventually fully separate out clipping from spatial nodes
|
||||
// in the display list. We don't ever need to do this anyway.
|
||||
panic!("Tried to use positioning node as clip node.");
|
||||
}
|
||||
ClipId::ClipChain(_) => panic!("Tried to use ClipChain as scroll node."),
|
||||
}
|
||||
ClipScrollNodeIndex(pipeline_offset + index)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,7 +160,7 @@ pub struct DisplayListFlattener<'a> {
|
|||
|
||||
/// A stack of scroll nodes used during display list processing to properly
|
||||
/// parent new scroll nodes.
|
||||
reference_frame_stack: Vec<(ClipId, SpatialNodeIndex)>,
|
||||
reference_frame_stack: Vec<(ClipId, ClipScrollNodeIndex)>,
|
||||
|
||||
/// A stack of stacking context properties.
|
||||
sc_stack: Vec<FlattenedStackingContext>,
|
||||
|
@ -292,12 +273,14 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
fn flatten_root(&mut self, pipeline: &'a ScenePipeline, frame_size: &LayoutSize) {
|
||||
let pipeline_id = pipeline.pipeline_id;
|
||||
let reference_frame_info = self.simple_scroll_and_clip_chain(
|
||||
&ClipId::root_reference_frame(pipeline_id),
|
||||
let reference_frame_info = self.id_to_index_mapper.simple_scroll_and_clip_chain(
|
||||
&ClipId::root_reference_frame(pipeline_id)
|
||||
);
|
||||
|
||||
let root_scroll_node = ClipId::root_scroll_node(pipeline_id);
|
||||
let scroll_frame_info = self.simple_scroll_and_clip_chain(&root_scroll_node);
|
||||
let scroll_frame_info = self.id_to_index_mapper.simple_scroll_and_clip_chain(
|
||||
&root_scroll_node,
|
||||
);
|
||||
|
||||
self.push_stacking_context(
|
||||
pipeline_id,
|
||||
|
@ -397,7 +380,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
info.previously_applied_offset,
|
||||
);
|
||||
|
||||
let index = self.get_spatial_node_index_for_clip_id(info.id);
|
||||
let index = self.id_to_index_mapper.get_node_index(info.id);
|
||||
self.clip_scroll_tree.add_sticky_frame(
|
||||
index,
|
||||
clip_and_scroll.scroll_node_id, /* parent id */
|
||||
|
@ -424,7 +407,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
);
|
||||
// Just use clip rectangle as the frame rect for this scroll frame.
|
||||
// This is useful when calculating scroll extents for the
|
||||
// SpatialNode::scroll(..) API as well as for properly setting sticky
|
||||
// ClipScrollNode::scroll(..) API as well as for properly setting sticky
|
||||
// positioning offsets.
|
||||
let frame_rect = item.clip_rect().translate(reference_frame_relative_offset);
|
||||
let content_rect = item.rect().translate(reference_frame_relative_offset);
|
||||
|
@ -573,7 +556,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
reference_frame_relative_offset: LayoutVector2D,
|
||||
) -> Option<BuiltDisplayListIter<'a>> {
|
||||
let clip_and_scroll_ids = item.clip_and_scroll();
|
||||
let clip_and_scroll = self.map_clip_and_scroll(&clip_and_scroll_ids);
|
||||
let clip_and_scroll = self.id_to_index_mapper.map_clip_and_scroll(&clip_and_scroll_ids);
|
||||
|
||||
let prim_info = item.get_layout_primitive_info(&reference_frame_relative_offset);
|
||||
match *item.item() {
|
||||
|
@ -734,7 +717,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
SpecificDisplayItem::ClipChain(ref info) => {
|
||||
let items = self.get_clip_chain_items(pipeline_id, item.clip_chain_items())
|
||||
.iter()
|
||||
.map(|id| self.id_to_index_mapper.get_clip_node_index(*id))
|
||||
.map(|id| self.id_to_index_mapper.get_node_index(*id))
|
||||
.collect();
|
||||
let parent = info.parent.map(|id|
|
||||
self.id_to_index_mapper.get_clip_chain_index(&ClipId::ClipChain(id))
|
||||
|
@ -900,7 +883,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
transform_style: TransformStyle,
|
||||
is_backface_visible: bool,
|
||||
is_pipeline_root: bool,
|
||||
spatial_node: ClipId,
|
||||
positioning_node: ClipId,
|
||||
clipping_node: Option<ClipId>,
|
||||
glyph_raster_space: GlyphRasterSpace,
|
||||
) {
|
||||
|
@ -909,7 +892,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
None => ClipChainIndex(0), // This means no clipping.
|
||||
};
|
||||
let clip_and_scroll = ScrollNodeAndClipChain::new(
|
||||
self.get_spatial_node_index_for_clip_id(spatial_node),
|
||||
self.id_to_index_mapper.get_node_index(positioning_node),
|
||||
clip_chain_id
|
||||
);
|
||||
|
||||
|
@ -1208,9 +1191,9 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
source_transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
source_perspective: Option<LayoutTransform>,
|
||||
origin_in_parent_reference_frame: LayoutVector2D,
|
||||
) -> SpatialNodeIndex {
|
||||
let index = self.get_spatial_node_index_for_clip_id(reference_frame_id);
|
||||
let parent_index = parent_id.map(|id| self.get_spatial_node_index_for_clip_id(id));
|
||||
) -> ClipScrollNodeIndex {
|
||||
let index = self.id_to_index_mapper.get_node_index(reference_frame_id);
|
||||
let parent_index = parent_id.map(|id| self.id_to_index_mapper.get_node_index(id));
|
||||
self.clip_scroll_tree.add_reference_frame(
|
||||
index,
|
||||
parent_index,
|
||||
|
@ -1229,7 +1212,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
index
|
||||
}
|
||||
|
||||
pub fn current_reference_frame_index(&self) -> SpatialNodeIndex {
|
||||
pub fn current_reference_frame_index(&self) -> ClipScrollNodeIndex {
|
||||
self.reference_frame_stack.last().unwrap().1
|
||||
}
|
||||
|
||||
|
@ -1240,8 +1223,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
) {
|
||||
let viewport_offset = (inner_rect.origin.to_vector().to_f32() / device_pixel_scale).round();
|
||||
let root_id = self.clip_scroll_tree.root_reference_frame_index();
|
||||
let root_node = &mut self.clip_scroll_tree.spatial_nodes[root_id.0];
|
||||
if let SpatialNodeType::ReferenceFrame(ref mut info) = root_node.node_type {
|
||||
let root_node = &mut self.clip_scroll_tree.nodes[root_id.0];
|
||||
if let NodeType::Spatial { kind: SpatialNodeKind::ReferenceFrame(ref mut info), .. } = root_node.node_type {
|
||||
info.resolved_transform =
|
||||
LayoutVector2D::new(viewport_offset.x, viewport_offset.y).into();
|
||||
}
|
||||
|
@ -1278,21 +1261,19 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
new_node_id: ClipId,
|
||||
parent_id: ClipId,
|
||||
clip_region: ClipRegion,
|
||||
) {
|
||||
) -> ClipScrollNodeIndex {
|
||||
let clip_sources = ClipSources::from(clip_region);
|
||||
let handle = self.clip_store.insert(clip_sources);
|
||||
|
||||
let node_index = self.id_to_index_mapper.get_clip_node_index(new_node_id);
|
||||
let parent_clip_chain_index =
|
||||
self.id_to_index_mapper.get_clip_chain_index_and_cache_result(&parent_id);
|
||||
let spatial_node = self.get_spatial_node_index_for_clip_id(parent_id);
|
||||
let node_index = self.id_to_index_mapper.get_node_index(new_node_id);
|
||||
let clip_chain_index = self.clip_scroll_tree.add_clip_node(
|
||||
node_index,
|
||||
parent_clip_chain_index,
|
||||
spatial_node,
|
||||
self.id_to_index_mapper.get_node_index(parent_id),
|
||||
handle,
|
||||
new_node_id.pipeline_id(),
|
||||
);
|
||||
self.id_to_index_mapper.add_clip_chain(new_node_id, clip_chain_index);
|
||||
node_index
|
||||
}
|
||||
|
||||
pub fn add_scroll_frame(
|
||||
|
@ -1304,12 +1285,11 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
frame_rect: &LayoutRect,
|
||||
content_size: &LayoutSize,
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
) -> SpatialNodeIndex {
|
||||
let node_index = self.get_spatial_node_index_for_clip_id(new_node_id);
|
||||
let parent_node_index = self.get_spatial_node_index_for_clip_id(parent_id);
|
||||
) -> ClipScrollNodeIndex {
|
||||
let node_index = self.id_to_index_mapper.get_node_index(new_node_id);
|
||||
self.clip_scroll_tree.add_scroll_frame(
|
||||
node_index,
|
||||
parent_node_index,
|
||||
self.id_to_index_mapper.get_node_index(parent_id),
|
||||
external_id,
|
||||
pipeline_id,
|
||||
frame_rect,
|
||||
|
@ -1953,31 +1933,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
PrimitiveContainer::Brush(prim),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn map_clip_and_scroll(&mut self, info: &ClipAndScrollInfo) -> ScrollNodeAndClipChain {
|
||||
ScrollNodeAndClipChain::new(
|
||||
self.get_spatial_node_index_for_clip_id(info.scroll_node_id),
|
||||
self.id_to_index_mapper.get_clip_chain_index_and_cache_result(&info.clip_node_id())
|
||||
)
|
||||
}
|
||||
|
||||
pub fn simple_scroll_and_clip_chain(&mut self, id: &ClipId) -> ScrollNodeAndClipChain {
|
||||
self.map_clip_and_scroll(&ClipAndScrollInfo::simple(*id))
|
||||
}
|
||||
|
||||
pub fn get_spatial_node_index_for_clip_id(&mut self, id: ClipId,) -> SpatialNodeIndex {
|
||||
match id {
|
||||
ClipId::Spatial(index, pipeline_id) => {
|
||||
let pipeline_offset = self.id_to_index_mapper.get_pipeline_offet(pipeline_id);
|
||||
SpatialNodeIndex(pipeline_offset.spatial_offset + index)
|
||||
}
|
||||
ClipId::Clip(..) => {
|
||||
let clip_node_index = self.id_to_index_mapper.get_clip_node_index(id);
|
||||
self.clip_scroll_tree.clip_nodes[clip_node_index.0].spatial_node
|
||||
}
|
||||
ClipId::ClipChain(_) => panic!("Tried to use ClipChain as scroll node."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_scene(config: &FrameBuilderConfig, request: SceneRequest) -> BuiltScene {
|
||||
|
@ -2032,4 +1987,4 @@ struct FlattenedStackingContext {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ScrollbarInfo(pub SpatialNodeIndex, pub LayoutRect);
|
||||
pub struct ScrollbarInfo(pub ClipScrollNodeIndex, pub LayoutRect);
|
||||
|
|
|
@ -6,10 +6,11 @@ use api::{BuiltDisplayList, ColorF, DeviceIntPoint, DeviceIntRect, DevicePixelSc
|
|||
use api::{DeviceUintPoint, DeviceUintRect, DeviceUintSize, DocumentLayer, FontRenderMode};
|
||||
use api::{LayoutPoint, LayoutRect, LayoutSize, PipelineId, WorldPoint};
|
||||
use clip::{ClipChain, ClipStore};
|
||||
use clip_scroll_tree::{ClipScrollTree, SpatialNodeIndex};
|
||||
use clip_scroll_node::{ClipScrollNode};
|
||||
use clip_scroll_tree::{ClipScrollNodeIndex, ClipScrollTree};
|
||||
use display_list_flattener::{DisplayListFlattener};
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::{PrimitiveHeaders, TransformData, TransformIndex, UvRectKind};
|
||||
use gpu_types::{PrimitiveHeaders, TransformData, UvRectKind};
|
||||
use hit_test::{HitTester, HitTestingRun};
|
||||
use internal_types::{FastHashMap};
|
||||
use picture::PictureSurface;
|
||||
|
@ -19,7 +20,6 @@ use render_backend::FrameId;
|
|||
use render_task::{RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
|
||||
use resource_cache::{ResourceCache};
|
||||
use scene::{ScenePipeline, SceneProperties};
|
||||
use spatial_node::SpatialNode;
|
||||
use std::{mem, f32};
|
||||
use std::sync::Arc;
|
||||
use tiling::{Frame, RenderPass, RenderPassKind, RenderTargetContext};
|
||||
|
@ -88,7 +88,7 @@ pub struct FrameBuildingState<'a> {
|
|||
pub struct PictureContext<'a> {
|
||||
pub pipeline_id: PipelineId,
|
||||
pub prim_runs: Vec<PrimitiveRun>,
|
||||
pub original_reference_frame_index: Option<SpatialNodeIndex>,
|
||||
pub original_reference_frame_index: Option<ClipScrollNodeIndex>,
|
||||
pub display_list: &'a BuiltDisplayList,
|
||||
pub inv_world_transform: Option<WorldToLayoutFastTransform>,
|
||||
pub apply_local_clip_rect: bool,
|
||||
|
@ -114,23 +114,20 @@ impl PictureState {
|
|||
|
||||
pub struct PrimitiveRunContext<'a> {
|
||||
pub clip_chain: &'a ClipChain,
|
||||
pub scroll_node: &'a SpatialNode,
|
||||
pub transform_index: TransformIndex,
|
||||
pub scroll_node: &'a ClipScrollNode,
|
||||
pub local_clip_rect: LayoutRect,
|
||||
}
|
||||
|
||||
impl<'a> PrimitiveRunContext<'a> {
|
||||
pub fn new(
|
||||
clip_chain: &'a ClipChain,
|
||||
scroll_node: &'a SpatialNode,
|
||||
transform_index: TransformIndex,
|
||||
scroll_node: &'a ClipScrollNode,
|
||||
local_clip_rect: LayoutRect,
|
||||
) -> Self {
|
||||
PrimitiveRunContext {
|
||||
clip_chain,
|
||||
scroll_node,
|
||||
local_clip_rect,
|
||||
transform_index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,11 +195,11 @@ impl FrameBuilder {
|
|||
}
|
||||
|
||||
// The root picture is always the first one added.
|
||||
let root_spatial_node =
|
||||
&clip_scroll_tree.spatial_nodes[clip_scroll_tree.root_reference_frame_index().0];
|
||||
let root_clip_scroll_node =
|
||||
&clip_scroll_tree.nodes[clip_scroll_tree.root_reference_frame_index().0];
|
||||
|
||||
let display_list = &pipelines
|
||||
.get(&root_spatial_node.pipeline_id)
|
||||
.get(&root_clip_scroll_node.pipeline_id)
|
||||
.expect("No display list?")
|
||||
.display_list;
|
||||
|
||||
|
@ -232,7 +229,7 @@ impl FrameBuilder {
|
|||
};
|
||||
|
||||
let pic_context = PictureContext {
|
||||
pipeline_id: root_spatial_node.pipeline_id,
|
||||
pipeline_id: root_clip_scroll_node.pipeline_id,
|
||||
prim_runs: mem::replace(&mut self.prim_store.pictures[0].runs, Vec::new()),
|
||||
original_reference_frame_index: None,
|
||||
display_list,
|
||||
|
@ -273,7 +270,7 @@ impl FrameBuilder {
|
|||
|
||||
for scrollbar_prim in &self.scrollbar_prims {
|
||||
let metadata = &mut self.prim_store.cpu_metadata[scrollbar_prim.prim_index.0];
|
||||
let scroll_frame = &clip_scroll_tree.spatial_nodes[scrollbar_prim.scroll_frame_index.0];
|
||||
let scroll_frame = &clip_scroll_tree.nodes[scrollbar_prim.scroll_frame_index.0];
|
||||
|
||||
// Invalidate what's in the cache so it will get rebuilt.
|
||||
gpu_cache.invalidate(&metadata.gpu_location);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use api::{DevicePoint, DeviceSize, DeviceRect, LayoutRect, LayoutToWorldTransform};
|
||||
use api::{PremultipliedColorF, WorldToLayoutTransform};
|
||||
use clip_scroll_tree::TransformIndex;
|
||||
use gpu_cache::{GpuCacheAddress, GpuDataRequest};
|
||||
use prim_store::{EdgeAaSegmentMask};
|
||||
use render_task::RenderTaskAddress;
|
||||
|
@ -399,11 +400,6 @@ pub struct TransformPalette {
|
|||
metadata: Vec<TransformMetadata>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct TransformIndex(pub u32);
|
||||
|
||||
impl TransformPalette {
|
||||
pub fn new(spatial_node_count: usize) -> TransformPalette {
|
||||
TransformPalette {
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
use api::{BorderRadius, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag, LayoutPoint};
|
||||
use api::{LayoutPrimitiveInfo, LayoutRect, PipelineId, WorldPoint};
|
||||
use clip::{ClipSource, ClipStore, rounded_rectangle_contains_point};
|
||||
use clip_node::ClipNode;
|
||||
use clip_scroll_tree::{ClipChainIndex, ClipNodeIndex, SpatialNodeIndex, ClipScrollTree};
|
||||
use clip_scroll_node::{ClipScrollNode, NodeType};
|
||||
use clip_scroll_tree::{ClipChainIndex, ClipScrollNodeIndex, ClipScrollTree};
|
||||
use internal_types::FastHashMap;
|
||||
use prim_store::ScrollNodeAndClipChain;
|
||||
use util::LayoutToWorldFastTransform;
|
||||
|
@ -14,10 +14,14 @@ use util::LayoutToWorldFastTransform;
|
|||
/// A copy of important clip scroll node data to use during hit testing. This a copy of
|
||||
/// data from the ClipScrollTree that will persist as a new frame is under construction,
|
||||
/// allowing hit tests consistent with the currently rendered frame.
|
||||
pub struct HitTestSpatialNode {
|
||||
pub struct HitTestClipScrollNode {
|
||||
/// The pipeline id of this node.
|
||||
pipeline_id: PipelineId,
|
||||
|
||||
/// A particular point must be inside all of these regions to be considered clipped in
|
||||
/// for the purposes of a hit test.
|
||||
regions: Vec<HitTestRegion>,
|
||||
|
||||
/// World transform for content transformed by this node.
|
||||
world_content_transform: LayoutToWorldFastTransform,
|
||||
|
||||
|
@ -25,15 +29,6 @@ pub struct HitTestSpatialNode {
|
|||
world_viewport_transform: LayoutToWorldFastTransform,
|
||||
}
|
||||
|
||||
pub struct HitTestClipNode {
|
||||
/// The positioning node for this clip node.
|
||||
spatial_node: SpatialNodeIndex,
|
||||
|
||||
/// A particular point must be inside all of these regions to be considered clipped in
|
||||
/// for the purposes of a hit test.
|
||||
regions: Vec<HitTestRegion>,
|
||||
}
|
||||
|
||||
/// A description of a clip chain in the HitTester. This is used to describe
|
||||
/// hierarchical clip scroll nodes as well as ClipChains, so that they can be
|
||||
/// handled the same way during hit testing. Once we represent all ClipChains
|
||||
|
@ -42,7 +37,7 @@ pub struct HitTestClipNode {
|
|||
#[derive(Clone)]
|
||||
struct HitTestClipChainDescriptor {
|
||||
parent: Option<ClipChainIndex>,
|
||||
clips: Vec<ClipNodeIndex>,
|
||||
clips: Vec<ClipScrollNodeIndex>,
|
||||
}
|
||||
|
||||
impl HitTestClipChainDescriptor {
|
||||
|
@ -98,10 +93,9 @@ impl HitTestRegion {
|
|||
|
||||
pub struct HitTester {
|
||||
runs: Vec<HitTestingRun>,
|
||||
spatial_nodes: Vec<HitTestSpatialNode>,
|
||||
clip_nodes: Vec<HitTestClipNode>,
|
||||
nodes: Vec<HitTestClipScrollNode>,
|
||||
clip_chains: Vec<HitTestClipChainDescriptor>,
|
||||
pipeline_root_nodes: FastHashMap<PipelineId, SpatialNodeIndex>,
|
||||
pipeline_root_nodes: FastHashMap<PipelineId, ClipScrollNodeIndex>,
|
||||
}
|
||||
|
||||
impl HitTester {
|
||||
|
@ -112,8 +106,7 @@ impl HitTester {
|
|||
) -> HitTester {
|
||||
let mut hit_tester = HitTester {
|
||||
runs: runs.clone(),
|
||||
spatial_nodes: Vec::new(),
|
||||
clip_nodes: Vec::new(),
|
||||
nodes: Vec::new(),
|
||||
clip_chains: Vec::new(),
|
||||
pipeline_root_nodes: FastHashMap::default(),
|
||||
};
|
||||
|
@ -126,41 +119,33 @@ impl HitTester {
|
|||
clip_scroll_tree: &ClipScrollTree,
|
||||
clip_store: &ClipStore
|
||||
) {
|
||||
self.spatial_nodes.clear();
|
||||
self.nodes.clear();
|
||||
self.clip_chains.clear();
|
||||
self.clip_chains.resize(
|
||||
clip_scroll_tree.clip_chains.len(),
|
||||
HitTestClipChainDescriptor::empty()
|
||||
);
|
||||
|
||||
for (index, node) in clip_scroll_tree.spatial_nodes.iter().enumerate() {
|
||||
let index = SpatialNodeIndex(index);
|
||||
for (index, node) in clip_scroll_tree.nodes.iter().enumerate() {
|
||||
let index = ClipScrollNodeIndex(index);
|
||||
|
||||
// If we haven't already seen a node for this pipeline, record this one as the root
|
||||
// node.
|
||||
self.pipeline_root_nodes.entry(node.pipeline_id).or_insert(index);
|
||||
|
||||
self.spatial_nodes.push(HitTestSpatialNode {
|
||||
self.nodes.push(HitTestClipScrollNode {
|
||||
pipeline_id: node.pipeline_id,
|
||||
regions: get_regions_for_clip_scroll_node(node, clip_store),
|
||||
world_content_transform: node.world_content_transform,
|
||||
world_viewport_transform: node.world_viewport_transform,
|
||||
});
|
||||
}
|
||||
|
||||
for (index, node) in clip_scroll_tree.clip_nodes.iter().enumerate() {
|
||||
let regions = match get_regions_for_clip_node(node, clip_store) {
|
||||
Some(regions) => regions,
|
||||
None => continue,
|
||||
};
|
||||
self.clip_nodes.push(HitTestClipNode {
|
||||
spatial_node: node.spatial_node,
|
||||
regions,
|
||||
});
|
||||
|
||||
let clip_chain = self.clip_chains.get_mut(node.clip_chain_index.0).unwrap();
|
||||
clip_chain.parent =
|
||||
clip_scroll_tree.get_clip_chain(node.clip_chain_index).parent_index;
|
||||
clip_chain.clips = vec![ClipNodeIndex(index)];
|
||||
if let NodeType::Clip { clip_chain_index, .. } = node.node_type {
|
||||
let clip_chain = self.clip_chains.get_mut(clip_chain_index.0).unwrap();
|
||||
clip_chain.parent =
|
||||
clip_scroll_tree.get_clip_chain(clip_chain_index).parent_index;
|
||||
clip_chain.clips = vec![index];
|
||||
}
|
||||
}
|
||||
|
||||
for descriptor in &clip_scroll_tree.clip_chains_descriptors {
|
||||
|
@ -192,7 +177,7 @@ impl HitTester {
|
|||
}
|
||||
|
||||
for clip_node_index in &descriptor.clips {
|
||||
if !self.is_point_clipped_in_for_clip_node(point, *clip_node_index, test) {
|
||||
if !self.is_point_clipped_in_for_node(point, *clip_node_index, test) {
|
||||
test.set_in_clip_chain_cache(clip_chain_index, ClippedIn::NotClippedIn);
|
||||
return false;
|
||||
}
|
||||
|
@ -202,18 +187,18 @@ impl HitTester {
|
|||
true
|
||||
}
|
||||
|
||||
fn is_point_clipped_in_for_clip_node(
|
||||
fn is_point_clipped_in_for_node(
|
||||
&self,
|
||||
point: WorldPoint,
|
||||
node_index: ClipNodeIndex,
|
||||
node_index: ClipScrollNodeIndex,
|
||||
test: &mut HitTest
|
||||
) -> bool {
|
||||
if let Some(clipped_in) = test.node_cache.get(&node_index) {
|
||||
return *clipped_in == ClippedIn::ClippedIn;
|
||||
}
|
||||
|
||||
let node = &self.clip_nodes[node_index.0];
|
||||
let transform = self.spatial_nodes[node.spatial_node.0].world_viewport_transform;
|
||||
let node = &self.nodes[node_index.0];
|
||||
let transform = node.world_viewport_transform;
|
||||
let transformed_point = match transform.inverse() {
|
||||
Some(inverted) => inverted.transform_point2d(&point),
|
||||
None => {
|
||||
|
@ -233,12 +218,12 @@ impl HitTester {
|
|||
true
|
||||
}
|
||||
|
||||
pub fn find_node_under_point(&self, mut test: HitTest) -> Option<SpatialNodeIndex> {
|
||||
pub fn find_node_under_point(&self, mut test: HitTest) -> Option<ClipScrollNodeIndex> {
|
||||
let point = test.get_absolute_point(self);
|
||||
|
||||
for &HitTestingRun(ref items, ref clip_and_scroll) in self.runs.iter().rev() {
|
||||
let scroll_node_id = clip_and_scroll.scroll_node_id;
|
||||
let scroll_node = &self.spatial_nodes[scroll_node_id.0];
|
||||
let scroll_node = &self.nodes[scroll_node_id.0];
|
||||
let transform = scroll_node.world_content_transform;
|
||||
let point_in_layer = match transform.inverse() {
|
||||
Some(inverted) => inverted.transform_point2d(&point),
|
||||
|
@ -272,7 +257,7 @@ impl HitTester {
|
|||
let mut result = HitTestResult::default();
|
||||
for &HitTestingRun(ref items, ref clip_and_scroll) in self.runs.iter().rev() {
|
||||
let scroll_node_id = clip_and_scroll.scroll_node_id;
|
||||
let scroll_node = &self.spatial_nodes[scroll_node_id.0];
|
||||
let scroll_node = &self.nodes[scroll_node_id.0];
|
||||
let pipeline_id = scroll_node.pipeline_id;
|
||||
match (test.pipeline_id, pipeline_id) {
|
||||
(Some(id), node_id) if node_id != id => continue,
|
||||
|
@ -311,7 +296,7 @@ impl HitTester {
|
|||
// the pipeline of the hit item. If we cannot get a transformed point, we are
|
||||
// in a situation with an uninvertible transformation so we should just skip this
|
||||
// result.
|
||||
let root_node = &self.spatial_nodes[self.pipeline_root_nodes[&pipeline_id].0];
|
||||
let root_node = &self.nodes[self.pipeline_root_nodes[&pipeline_id].0];
|
||||
let point_in_viewport = match root_node.world_viewport_transform.inverse() {
|
||||
Some(inverted) => inverted.transform_point2d(&point),
|
||||
None => continue,
|
||||
|
@ -333,25 +318,21 @@ impl HitTester {
|
|||
result
|
||||
}
|
||||
|
||||
pub fn get_pipeline_root(&self, pipeline_id: PipelineId) -> &HitTestSpatialNode {
|
||||
&self.spatial_nodes[self.pipeline_root_nodes[&pipeline_id].0]
|
||||
pub fn get_pipeline_root(&self, pipeline_id: PipelineId) -> &HitTestClipScrollNode {
|
||||
&self.nodes[self.pipeline_root_nodes[&pipeline_id].0]
|
||||
}
|
||||
}
|
||||
|
||||
fn get_regions_for_clip_node(
|
||||
node: &ClipNode,
|
||||
fn get_regions_for_clip_scroll_node(
|
||||
node: &ClipScrollNode,
|
||||
clip_store: &ClipStore
|
||||
) -> Option<Vec<HitTestRegion>> {
|
||||
let handle = match node.handle.as_ref() {
|
||||
Some(handle) => handle,
|
||||
None => {
|
||||
warn!("Encountered an empty clip node unexpectedly.");
|
||||
return None;
|
||||
}
|
||||
) -> Vec<HitTestRegion> {
|
||||
let clips = match node.node_type {
|
||||
NodeType::Clip{ ref handle, .. } => clip_store.get(handle).clips(),
|
||||
_ => return Vec::new(),
|
||||
};
|
||||
|
||||
let clips = clip_store.get(handle).clips();
|
||||
Some(clips.iter().map(|source| {
|
||||
clips.iter().map(|source| {
|
||||
match source.0 {
|
||||
ClipSource::Rectangle(ref rect, mode) => HitTestRegion::Rectangle(*rect, mode),
|
||||
ClipSource::RoundedRectangle(ref rect, ref radii, ref mode) =>
|
||||
|
@ -362,7 +343,7 @@ fn get_regions_for_clip_node(
|
|||
unreachable!("Didn't expect to hit test against BorderCorner / BoxShadow / LineDecoration");
|
||||
}
|
||||
}
|
||||
}).collect())
|
||||
}).collect()
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
|
@ -375,7 +356,7 @@ pub struct HitTest {
|
|||
pipeline_id: Option<PipelineId>,
|
||||
point: WorldPoint,
|
||||
flags: HitTestFlags,
|
||||
node_cache: FastHashMap<ClipNodeIndex, ClippedIn>,
|
||||
node_cache: FastHashMap<ClipScrollNodeIndex, ClippedIn>,
|
||||
clip_chain_cache: Vec<Option<ClippedIn>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ mod box_shadow;
|
|||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
mod capture;
|
||||
mod clip;
|
||||
mod clip_node;
|
||||
mod clip_scroll_node;
|
||||
mod clip_scroll_tree;
|
||||
mod debug_colors;
|
||||
#[cfg(feature = "debug_renderer")]
|
||||
|
@ -98,7 +98,6 @@ mod scene;
|
|||
mod scene_builder;
|
||||
mod segment;
|
||||
mod shade;
|
||||
mod spatial_node;
|
||||
mod texture_allocator;
|
||||
mod texture_cache;
|
||||
mod tiling;
|
||||
|
|
|
@ -6,8 +6,8 @@ use api::{DeviceRect, FilterOp, MixBlendMode, PipelineId, PremultipliedColorF};
|
|||
use api::{DeviceIntRect, DeviceIntSize, DevicePoint, LayoutPoint, LayoutRect};
|
||||
use api::{DevicePixelScale, PictureIntPoint, PictureIntRect, PictureIntSize};
|
||||
use box_shadow::{BLUR_SAMPLE_SCALE};
|
||||
use spatial_node::SpatialNode;
|
||||
use clip_scroll_tree::SpatialNodeIndex;
|
||||
use clip_scroll_node::ClipScrollNode;
|
||||
use clip_scroll_tree::ClipScrollNodeIndex;
|
||||
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PrimitiveRunContext};
|
||||
use gpu_cache::{GpuCacheHandle};
|
||||
use gpu_types::UvRectKind;
|
||||
|
@ -150,7 +150,7 @@ pub struct PicturePrimitive {
|
|||
// The original reference frame ID for this picture.
|
||||
// It is only different if this is part of a 3D
|
||||
// rendering context.
|
||||
pub reference_frame_index: SpatialNodeIndex,
|
||||
pub reference_frame_index: ClipScrollNodeIndex,
|
||||
pub real_local_rect: LayoutRect,
|
||||
// An optional cache handle for storing extra data
|
||||
// in the GPU cache, depending on the type of
|
||||
|
@ -183,7 +183,7 @@ impl PicturePrimitive {
|
|||
composite_mode: Option<PictureCompositeMode>,
|
||||
is_in_3d_context: bool,
|
||||
pipeline_id: PipelineId,
|
||||
reference_frame_index: SpatialNodeIndex,
|
||||
reference_frame_index: ClipScrollNodeIndex,
|
||||
frame_output_pipeline_id: Option<PipelineId>,
|
||||
apply_local_clip_rect: bool,
|
||||
) -> Self {
|
||||
|
@ -590,18 +590,18 @@ impl PicturePrimitive {
|
|||
// Calculate a single screen-space UV for a picture.
|
||||
fn calculate_screen_uv(
|
||||
local_pos: &LayoutPoint,
|
||||
spatial_node: &SpatialNode,
|
||||
clip_scroll_node: &ClipScrollNode,
|
||||
rendered_rect: &DeviceRect,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
) -> DevicePoint {
|
||||
let world_pos = spatial_node
|
||||
let world_pos = clip_scroll_node
|
||||
.world_content_transform
|
||||
.transform_point2d(local_pos);
|
||||
|
||||
let mut device_pos = world_pos * device_pixel_scale;
|
||||
|
||||
// Apply snapping for axis-aligned scroll nodes, as per prim_shared.glsl.
|
||||
if spatial_node.transform_kind == TransformedRectKind::AxisAligned {
|
||||
if clip_scroll_node.transform_kind == TransformedRectKind::AxisAligned {
|
||||
device_pos.x = (device_pos.x + 0.5).floor();
|
||||
device_pos.y = (device_pos.y + 0.5).floor();
|
||||
}
|
||||
|
@ -616,7 +616,7 @@ fn calculate_screen_uv(
|
|||
// vertex positions of a picture.
|
||||
fn calculate_uv_rect_kind(
|
||||
local_rect: &LayoutRect,
|
||||
spatial_node: &SpatialNode,
|
||||
clip_scroll_node: &ClipScrollNode,
|
||||
rendered_rect: &DeviceIntRect,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
) -> UvRectKind {
|
||||
|
@ -624,28 +624,28 @@ fn calculate_uv_rect_kind(
|
|||
|
||||
let top_left = calculate_screen_uv(
|
||||
&local_rect.origin,
|
||||
spatial_node,
|
||||
clip_scroll_node,
|
||||
&rendered_rect,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
||||
let top_right = calculate_screen_uv(
|
||||
&local_rect.top_right(),
|
||||
spatial_node,
|
||||
clip_scroll_node,
|
||||
&rendered_rect,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
||||
let bottom_left = calculate_screen_uv(
|
||||
&local_rect.bottom_left(),
|
||||
spatial_node,
|
||||
clip_scroll_node,
|
||||
&rendered_rect,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
||||
let bottom_right = calculate_screen_uv(
|
||||
&local_rect.bottom_right(),
|
||||
spatial_node,
|
||||
clip_scroll_node,
|
||||
&rendered_rect,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
|
|
@ -187,7 +187,7 @@ fn new_ct_font_with_variations(cg_font: &CGFont, size: f64, variations: &[FontVa
|
|||
}
|
||||
let tag_val = match axis.find(kCTFontVariationAxisIdentifierKey as *const _) {
|
||||
Some(tag_ptr) => {
|
||||
let tag: CFNumber = TCFType::wrap_under_get_rule(*tag_ptr as CFNumberRef);
|
||||
let tag: CFNumber = TCFType::wrap_under_get_rule(tag_ptr as CFNumberRef);
|
||||
if !tag.instance_of::<CFNumber>() {
|
||||
return ct_font;
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ fn new_ct_font_with_variations(cg_font: &CGFont, size: f64, variations: &[FontVa
|
|||
};
|
||||
|
||||
let name: CFString = match axis.find(kCTFontVariationAxisNameKey as *const _) {
|
||||
Some(name_ptr) => TCFType::wrap_under_get_rule(*name_ptr as CFStringRef),
|
||||
Some(name_ptr) => TCFType::wrap_under_get_rule(name_ptr as CFStringRef),
|
||||
None => return ct_font,
|
||||
};
|
||||
if !name.instance_of::<CFString>() {
|
||||
|
@ -213,7 +213,7 @@ fn new_ct_font_with_variations(cg_font: &CGFont, size: f64, variations: &[FontVa
|
|||
|
||||
let min_val = match axis.find(kCTFontVariationAxisMinimumValueKey as *const _) {
|
||||
Some(min_ptr) => {
|
||||
let min: CFNumber = TCFType::wrap_under_get_rule(*min_ptr as CFNumberRef);
|
||||
let min: CFNumber = TCFType::wrap_under_get_rule(min_ptr as CFNumberRef);
|
||||
if !min.instance_of::<CFNumber>() {
|
||||
return ct_font;
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ fn new_ct_font_with_variations(cg_font: &CGFont, size: f64, variations: &[FontVa
|
|||
};
|
||||
let max_val = match axis.find(kCTFontVariationAxisMaximumValueKey as *const _) {
|
||||
Some(max_ptr) => {
|
||||
let max: CFNumber = TCFType::wrap_under_get_rule(*max_ptr as CFNumberRef);
|
||||
let max: CFNumber = TCFType::wrap_under_get_rule(max_ptr as CFNumberRef);
|
||||
if !max.instance_of::<CFNumber>() {
|
||||
return ct_font;
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ fn new_ct_font_with_variations(cg_font: &CGFont, size: f64, variations: &[FontVa
|
|||
};
|
||||
let def_val = match axis.find(kCTFontVariationAxisDefaultValueKey as *const _) {
|
||||
Some(def_ptr) => {
|
||||
let def: CFNumber = TCFType::wrap_under_get_rule(*def_ptr as CFNumberRef);
|
||||
let def: CFNumber = TCFType::wrap_under_get_rule(def_ptr as CFNumberRef);
|
||||
if !def.instance_of::<CFNumber>() {
|
||||
return ct_font;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ use api::{BorderWidths, LayoutToWorldScale, NormalBorder};
|
|||
use app_units::Au;
|
||||
use border::{BorderCacheKey, BorderRenderTaskInfo};
|
||||
use box_shadow::BLUR_SAMPLE_SCALE;
|
||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId, SpatialNodeIndex};
|
||||
use clip_scroll_tree::{ClipChainIndex, ClipScrollNodeIndex, CoordinateSystemId};
|
||||
use clip_scroll_node::ClipScrollNode;
|
||||
use clip::{ClipChain, ClipChainNode, ClipChainNodeIter, ClipChainNodeRef, ClipSource};
|
||||
use clip::{ClipSourcesHandle, ClipWorkItem};
|
||||
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
|
||||
|
@ -30,10 +31,9 @@ use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
|
|||
use resource_cache::{ImageProperties, ImageRequest, ResourceCache};
|
||||
use scene::SceneProperties;
|
||||
use segment::SegmentBuilder;
|
||||
use spatial_node::SpatialNode;
|
||||
use std::{mem, usize};
|
||||
use std::sync::Arc;
|
||||
use util::{MatrixHelpers, calculate_screen_bounding_rect};
|
||||
use util::{MatrixHelpers, WorldToLayoutFastTransform, calculate_screen_bounding_rect};
|
||||
use util::{pack_as_float, recycle_vec};
|
||||
|
||||
|
||||
|
@ -42,13 +42,13 @@ pub const VECS_PER_SEGMENT: usize = 2;
|
|||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct ScrollNodeAndClipChain {
|
||||
pub scroll_node_id: SpatialNodeIndex,
|
||||
pub scroll_node_id: ClipScrollNodeIndex,
|
||||
pub clip_chain_index: ClipChainIndex,
|
||||
}
|
||||
|
||||
impl ScrollNodeAndClipChain {
|
||||
pub fn new(
|
||||
scroll_node_id: SpatialNodeIndex,
|
||||
scroll_node_id: ClipScrollNodeIndex,
|
||||
clip_chain_index: ClipChainIndex
|
||||
) -> Self {
|
||||
ScrollNodeAndClipChain { scroll_node_id, clip_chain_index }
|
||||
|
@ -1242,7 +1242,7 @@ impl PrimitiveStore {
|
|||
composite_mode: Option<PictureCompositeMode>,
|
||||
is_in_3d_context: bool,
|
||||
pipeline_id: PipelineId,
|
||||
reference_frame_index: SpatialNodeIndex,
|
||||
reference_frame_index: ClipScrollNodeIndex,
|
||||
frame_output_pipeline_id: Option<PipelineId>,
|
||||
apply_local_clip_rect: bool,
|
||||
) -> PictureIndex {
|
||||
|
@ -1994,6 +1994,7 @@ impl PrimitiveStore {
|
|||
prim_run_context: &PrimitiveRunContext,
|
||||
clips: &Vec<ClipWorkItem>,
|
||||
has_clips_from_other_coordinate_systems: bool,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
) {
|
||||
match brush.segment_desc {
|
||||
|
@ -2046,39 +2047,19 @@ impl PrimitiveStore {
|
|||
}
|
||||
|
||||
let local_clips = frame_state.clip_store.get_opt(&clip_item.clip_sources).expect("bug");
|
||||
rect_clips_only = rect_clips_only && local_clips.only_rectangular_clips;
|
||||
|
||||
// TODO(gw): We can easily extend the segment builder to support these clip sources in
|
||||
// the future, but they are rarely used.
|
||||
// We must do this check here in case we continue early below.
|
||||
if local_clips.has_image_or_line_decoration_clip {
|
||||
clip_mask_kind = BrushClipMaskKind::Global;
|
||||
}
|
||||
|
||||
// If this clip item is positioned by another positioning node, its relative position
|
||||
// could change during scrolling. This means that we would need to resegment. Instead
|
||||
// of doing that, only segment with clips that have the same positioning node.
|
||||
// TODO(mrobinson, #2858): It may make sense to include these nodes, resegmenting only
|
||||
// when necessary while scrolling.
|
||||
if clip_item.transform_index != prim_run_context.transform_index {
|
||||
// We don't need to generate a global clip mask for rectangle clips because we are
|
||||
// in the same coordinate system and rectangular clips are handled by the local
|
||||
// clip chain rectangle.
|
||||
if !local_clips.only_rectangular_clips {
|
||||
clip_mask_kind = BrushClipMaskKind::Global;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for &(ref clip, _) in &local_clips.clips {
|
||||
let (local_clip_rect, radius, mode) = match *clip {
|
||||
ClipSource::RoundedRectangle(rect, radii, clip_mode) => {
|
||||
rect_clips_only = false;
|
||||
|
||||
(rect, Some(radii), clip_mode)
|
||||
}
|
||||
ClipSource::Rectangle(rect, mode) => {
|
||||
(rect, None, mode)
|
||||
}
|
||||
ClipSource::BoxShadow(ref info) => {
|
||||
rect_clips_only = false;
|
||||
|
||||
// For inset box shadows, we can clip out any
|
||||
// pixels that are inside the shadow region
|
||||
// and are beyond the inner rect, as they can't
|
||||
|
@ -2103,7 +2084,35 @@ impl PrimitiveStore {
|
|||
|
||||
continue;
|
||||
}
|
||||
ClipSource::LineDecoration(..) | ClipSource::Image(..) => continue,
|
||||
ClipSource::LineDecoration(..) |
|
||||
ClipSource::Image(..) => {
|
||||
rect_clips_only = false;
|
||||
|
||||
// TODO(gw): We can easily extend the segment builder
|
||||
// to support these clip sources in the
|
||||
// future, but they are rarely used.
|
||||
clip_mask_kind = BrushClipMaskKind::Global;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// If the scroll node transforms are different between the clip
|
||||
// node and the primitive, we need to get the clip rect in the
|
||||
// local space of the primitive, in order to generate correct
|
||||
// local segments.
|
||||
let local_clip_rect = if clip_item.transform_index == prim_run_context.scroll_node.transform_index {
|
||||
local_clip_rect
|
||||
} else {
|
||||
let clip_transform = frame_context
|
||||
.transforms[clip_item.transform_index.0 as usize]
|
||||
.transform;
|
||||
let prim_transform = &prim_run_context.scroll_node.world_content_transform;
|
||||
let relative_transform = prim_transform
|
||||
.inverse()
|
||||
.unwrap_or(WorldToLayoutFastTransform::identity())
|
||||
.pre_mul(&clip_transform.into());
|
||||
|
||||
relative_transform.transform_rect(&local_clip_rect)
|
||||
};
|
||||
|
||||
segment_builder.push_clip_rect(local_clip_rect, radius, mode);
|
||||
|
@ -2172,6 +2181,7 @@ impl PrimitiveStore {
|
|||
prim_run_context,
|
||||
clips,
|
||||
has_clips_from_other_coordinate_systems,
|
||||
frame_context,
|
||||
frame_state,
|
||||
);
|
||||
|
||||
|
@ -2293,11 +2303,11 @@ impl PrimitiveStore {
|
|||
|
||||
Arc::new(ClipChainNode {
|
||||
work_item: ClipWorkItem {
|
||||
transform_index: prim_run_context.transform_index,
|
||||
transform_index: prim_run_context.scroll_node.transform_index,
|
||||
clip_sources: clip_sources.weak(),
|
||||
coordinate_system_id: prim_coordinate_system_id,
|
||||
},
|
||||
// The local_clip_rect a property of ClipChain nodes that are ClipNodes.
|
||||
// The local_clip_rect a property of ClipChain nodes that are ClipScrollNodes.
|
||||
// It's used to calculate a local clipping rectangle before we reach this
|
||||
// point, so we can set it to zero here. It should be unused from this point
|
||||
// on.
|
||||
|
@ -2639,7 +2649,7 @@ impl PrimitiveStore {
|
|||
// lookups ever show up in a profile).
|
||||
let scroll_node = &frame_context
|
||||
.clip_scroll_tree
|
||||
.spatial_nodes[run.clip_and_scroll.scroll_node_id.0];
|
||||
.nodes[run.clip_and_scroll.scroll_node_id.0];
|
||||
let clip_chain = frame_context
|
||||
.clip_scroll_tree
|
||||
.get_clip_chain(run.clip_and_scroll.clip_chain_index);
|
||||
|
@ -2675,7 +2685,7 @@ impl PrimitiveStore {
|
|||
.and_then(|original_reference_frame_index| {
|
||||
frame_context
|
||||
.clip_scroll_tree
|
||||
.spatial_nodes[original_reference_frame_index.0]
|
||||
.nodes[original_reference_frame_index.0]
|
||||
.world_content_transform
|
||||
.inverse()
|
||||
})
|
||||
|
@ -2712,7 +2722,6 @@ impl PrimitiveStore {
|
|||
let child_prim_run_context = PrimitiveRunContext::new(
|
||||
clip_chain,
|
||||
scroll_node,
|
||||
run.clip_and_scroll.scroll_node_id.transform_index(),
|
||||
local_clip_chain_rect,
|
||||
);
|
||||
|
||||
|
@ -2905,7 +2914,7 @@ fn convert_clip_chain_to_clip_vector(
|
|||
}
|
||||
|
||||
fn get_local_clip_rect_for_nodes(
|
||||
scroll_node: &SpatialNode,
|
||||
scroll_node: &ClipScrollNode,
|
||||
clip_chain: &ClipChain,
|
||||
) -> Option<LayoutRect> {
|
||||
ClipChainNodeIter { current: clip_chain.nodes.clone() }
|
||||
|
|
|
@ -14,7 +14,7 @@ use api::channel::{MsgReceiver, Payload};
|
|||
use api::CaptureBits;
|
||||
#[cfg(feature = "replay")]
|
||||
use api::CapturedDocument;
|
||||
use clip_scroll_tree::{SpatialNodeIndex, ClipScrollTree};
|
||||
use clip_scroll_tree::{ClipScrollNodeIndex, ClipScrollTree};
|
||||
#[cfg(feature = "debugger")]
|
||||
use debug_server;
|
||||
use display_list_flattener::DisplayListFlattener;
|
||||
|
@ -89,9 +89,9 @@ struct Document {
|
|||
|
||||
view: DocumentView,
|
||||
|
||||
/// The ClipScrollTree for this document which tracks SpatialNodes, ClipNodes, and ClipChains.
|
||||
/// This is stored here so that we are able to preserve scrolling positions between rendered
|
||||
/// frames.
|
||||
/// The ClipScrollTree for this document which tracks both ClipScrollNodes and ClipChains.
|
||||
/// This is stored here so that we are able to preserve scrolling positions between
|
||||
/// rendered frames.
|
||||
clip_scroll_tree: ClipScrollTree,
|
||||
|
||||
/// The id of the current frame.
|
||||
|
@ -313,7 +313,7 @@ impl Document {
|
|||
pub fn scroll_nearest_scrolling_ancestor(
|
||||
&mut self,
|
||||
scroll_location: ScrollLocation,
|
||||
scroll_node_index: Option<SpatialNodeIndex>,
|
||||
scroll_node_index: Option<ClipScrollNodeIndex>,
|
||||
) -> bool {
|
||||
self.clip_scroll_tree.scroll_nearest_scrolling_ancestor(scroll_location, scroll_node_index)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, FilterOp, ImageFormat,
|
|||
use api::{MixBlendMode, PipelineId};
|
||||
use batch::{AlphaBatchBuilder, AlphaBatchContainer, ClipBatcher, resolve_image};
|
||||
use clip::{ClipStore};
|
||||
use clip_scroll_tree::{ClipScrollTree, SpatialNodeIndex};
|
||||
use clip_scroll_tree::{ClipScrollTree, ClipScrollNodeIndex};
|
||||
use device::{FrameId, Texture};
|
||||
#[cfg(feature = "pathfinder")]
|
||||
use euclid::{TypedPoint2D, TypedVector2D};
|
||||
|
@ -31,7 +31,7 @@ const MIN_TARGET_SIZE: u32 = 2048;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct ScrollbarPrimitive {
|
||||
pub scroll_frame_index: SpatialNodeIndex,
|
||||
pub scroll_frame_index: ClipScrollNodeIndex,
|
||||
pub prim_index: PrimitiveIndex,
|
||||
pub frame_rect: LayoutRect,
|
||||
}
|
||||
|
|
|
@ -18,11 +18,9 @@ struct Shader {
|
|||
|
||||
const SHADER_PREFIX: &str = "#define WR_MAX_VERTEX_TEXTURE_WIDTH 1024\n";
|
||||
|
||||
const BRUSH_FEATURES: &[&str] = &["", "ALPHA_PASS"];
|
||||
const CLIP_FEATURES: &[&str] = &["TRANSFORM"];
|
||||
const CACHE_FEATURES: &[&str] = &[""];
|
||||
const GRADIENT_FEATURES: &[&str] = &[ "", "DITHERING", "ALPHA_PASS", "DITHERING,ALPHA_PASS" ];
|
||||
const PRIM_FEATURES: &[&str] = &[""];
|
||||
const PRIM_FEATURES: &[&str] = &["", "TRANSFORM"];
|
||||
|
||||
const SHADERS: &[Shader] = &[
|
||||
// Clip mask shaders
|
||||
|
@ -45,7 +43,7 @@ const SHADERS: &[Shader] = &[
|
|||
// Cache shaders
|
||||
Shader {
|
||||
name: "cs_blur",
|
||||
features: &[ "ALPHA_TARGET", "COLOR_TARGET" ],
|
||||
features: CACHE_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "cs_border_segment",
|
||||
|
@ -58,43 +56,36 @@ const SHADERS: &[Shader] = &[
|
|||
},
|
||||
Shader {
|
||||
name: "ps_text_run",
|
||||
features: &[ "", "GLYPH_TRANSFORM" ],
|
||||
features: PRIM_FEATURES,
|
||||
},
|
||||
// Brush shaders
|
||||
Shader {
|
||||
name: "brush_yuv_image",
|
||||
features: &[
|
||||
"",
|
||||
"YUV_NV12",
|
||||
"YUV_PLANAR",
|
||||
"YUV_INTERLEAVED",
|
||||
"TEXTURE_2D,YUV_NV12",
|
||||
"YUV_NV12,ALPHA_PASS",
|
||||
],
|
||||
features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED", "YUV_NV12,TEXTURE_RECT"],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_solid",
|
||||
features: BRUSH_FEATURES,
|
||||
features: &[],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_image",
|
||||
features: BRUSH_FEATURES,
|
||||
features: &["", "ALPHA_PASS"],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_blend",
|
||||
features: BRUSH_FEATURES,
|
||||
features: &[],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_mix_blend",
|
||||
features: BRUSH_FEATURES,
|
||||
features: &[],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_radial_gradient",
|
||||
features: GRADIENT_FEATURES,
|
||||
features: &[ "DITHERING" ],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_linear_gradient",
|
||||
features: GRADIENT_FEATURES,
|
||||
features: &[],
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -117,7 +108,7 @@ fn validate_shaders() {
|
|||
features.push_str(SHADER_PREFIX);
|
||||
|
||||
for feature in config.split(",") {
|
||||
features.push_str(&format!("#define WR_FEATURE_{}\n", feature));
|
||||
features.push_str(&format!("#define WR_FEATURE_{}", feature));
|
||||
}
|
||||
|
||||
let (vs, fs) =
|
||||
|
|
|
@ -24,8 +24,8 @@ serde_bytes = "0.10"
|
|||
time = "0.1"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.6"
|
||||
core-graphics = "0.14"
|
||||
core-foundation = "0.5"
|
||||
core-graphics = "0.13"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
dwrote = "0.4.1"
|
||||
|
|
|
@ -806,7 +806,6 @@ pub struct ClipChainId(pub u64, pub PipelineId);
|
|||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum ClipId {
|
||||
Spatial(usize, PipelineId),
|
||||
Clip(usize, PipelineId),
|
||||
ClipChain(ClipChainId),
|
||||
}
|
||||
|
@ -816,16 +815,15 @@ const ROOT_SCROLL_NODE_CLIP_ID: usize = 1;
|
|||
|
||||
impl ClipId {
|
||||
pub fn root_scroll_node(pipeline_id: PipelineId) -> ClipId {
|
||||
ClipId::Spatial(ROOT_SCROLL_NODE_CLIP_ID, pipeline_id)
|
||||
ClipId::Clip(ROOT_SCROLL_NODE_CLIP_ID, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn root_reference_frame(pipeline_id: PipelineId) -> ClipId {
|
||||
ClipId::Spatial(ROOT_REFERENCE_FRAME_CLIP_ID, pipeline_id)
|
||||
ClipId::Clip(ROOT_REFERENCE_FRAME_CLIP_ID, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn pipeline_id(&self) -> PipelineId {
|
||||
match *self {
|
||||
ClipId::Spatial(_, pipeline_id) |
|
||||
ClipId::Clip(_, pipeline_id) |
|
||||
ClipId::ClipChain(ClipChainId(_, pipeline_id)) => pipeline_id,
|
||||
}
|
||||
|
@ -833,14 +831,14 @@ impl ClipId {
|
|||
|
||||
pub fn is_root_scroll_node(&self) -> bool {
|
||||
match *self {
|
||||
ClipId::Spatial(ROOT_SCROLL_NODE_CLIP_ID, _) => true,
|
||||
ClipId::Clip(1, _) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_root_reference_frame(&self) -> bool {
|
||||
match *self {
|
||||
ClipId::Spatial(ROOT_REFERENCE_FRAME_CLIP_ID, _) => true,
|
||||
ClipId::Clip(1, _) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,12 +31,7 @@ use {YuvData, YuvImageDisplayItem};
|
|||
pub const MAX_TEXT_RUN_LENGTH: usize = 2040;
|
||||
|
||||
// We start at 2, because the root reference is always 0 and the root scroll node is always 1.
|
||||
// TODO(mrobinson): It would be a good idea to eliminate the root scroll frame which is only
|
||||
// used by Servo.
|
||||
const FIRST_SPATIAL_NODE_INDEX: usize = 2;
|
||||
|
||||
// There are no default clips, so we start at the 0 index for clips.
|
||||
const FIRST_CLIP_NODE_INDEX: usize = 0;
|
||||
const FIRST_CLIP_ID: usize = 2;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
|
@ -84,10 +79,8 @@ pub struct BuiltDisplayListDescriptor {
|
|||
builder_finish_time: u64,
|
||||
/// The third IPC time stamp: just before sending
|
||||
send_start_time: u64,
|
||||
/// The amount of clipping nodes created while building this display list.
|
||||
total_clip_nodes: usize,
|
||||
/// The amount of spatial nodes created while building this display list.
|
||||
total_spatial_nodes: usize,
|
||||
/// The amount of clips ids assigned while building this display list.
|
||||
total_clip_ids: usize,
|
||||
}
|
||||
|
||||
pub struct BuiltDisplayListIter<'a> {
|
||||
|
@ -153,12 +146,8 @@ impl BuiltDisplayList {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn total_clip_nodes(&self) -> usize {
|
||||
self.descriptor.total_clip_nodes
|
||||
}
|
||||
|
||||
pub fn total_spatial_nodes(&self) -> usize {
|
||||
self.descriptor.total_spatial_nodes
|
||||
pub fn total_clip_ids(&self) -> usize {
|
||||
self.descriptor.total_clip_ids
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> BuiltDisplayListIter {
|
||||
|
@ -528,13 +517,12 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
|||
|
||||
let mut data = Vec::new();
|
||||
let mut temp = Vec::new();
|
||||
let mut total_clip_nodes = FIRST_CLIP_NODE_INDEX;
|
||||
let mut total_spatial_nodes = FIRST_SPATIAL_NODE_INDEX;
|
||||
let mut total_clip_ids = FIRST_CLIP_ID;
|
||||
for complete in list {
|
||||
let item = DisplayItem {
|
||||
item: match complete.item {
|
||||
Clip(specific_item, complex_clips) => {
|
||||
total_clip_nodes += 1;
|
||||
total_clip_ids += 1;
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, complex_clips);
|
||||
SpecificDisplayItem::Clip(specific_item)
|
||||
},
|
||||
|
@ -543,13 +531,12 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
|||
SpecificDisplayItem::ClipChain(specific_item)
|
||||
}
|
||||
ScrollFrame(specific_item, complex_clips) => {
|
||||
total_spatial_nodes += 1;
|
||||
total_clip_nodes += 1;
|
||||
total_clip_ids += 2;
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, complex_clips);
|
||||
SpecificDisplayItem::ScrollFrame(specific_item)
|
||||
},
|
||||
StickyFrame(specific_item) => {
|
||||
total_spatial_nodes += 1;
|
||||
total_clip_ids += 1;
|
||||
SpecificDisplayItem::StickyFrame(specific_item)
|
||||
}
|
||||
Rectangle(specific_item) => SpecificDisplayItem::Rectangle(specific_item),
|
||||
|
@ -567,7 +554,7 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
|||
RadialGradient(specific_item) =>
|
||||
SpecificDisplayItem::RadialGradient(specific_item),
|
||||
Iframe(specific_item) => {
|
||||
total_clip_nodes += 1;
|
||||
total_clip_ids += 1;
|
||||
SpecificDisplayItem::Iframe(specific_item)
|
||||
}
|
||||
PushStackingContext(specific_item, filters) => {
|
||||
|
@ -576,7 +563,7 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
|||
},
|
||||
PopStackingContext => SpecificDisplayItem::PopStackingContext,
|
||||
PushReferenceFrame(specific_item) => {
|
||||
total_spatial_nodes += 1;
|
||||
total_clip_ids += 1;
|
||||
SpecificDisplayItem::PushReferenceFrame(specific_item)
|
||||
}
|
||||
PopReferenceFrame => SpecificDisplayItem::PopReferenceFrame,
|
||||
|
@ -601,8 +588,7 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
|||
builder_start_time: 0,
|
||||
builder_finish_time: 1,
|
||||
send_start_time: 0,
|
||||
total_clip_nodes,
|
||||
total_spatial_nodes,
|
||||
total_clip_ids,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -827,8 +813,7 @@ impl<'a, 'b> Read for UnsafeReader<'a, 'b> {
|
|||
pub struct SaveState {
|
||||
dl_len: usize,
|
||||
clip_stack_len: usize,
|
||||
next_clip_index: usize,
|
||||
next_spatial_index: usize,
|
||||
next_clip_id: usize,
|
||||
next_clip_chain_id: u64,
|
||||
}
|
||||
|
||||
|
@ -837,8 +822,7 @@ pub struct DisplayListBuilder {
|
|||
pub data: Vec<u8>,
|
||||
pub pipeline_id: PipelineId,
|
||||
clip_stack: Vec<ClipAndScrollInfo>,
|
||||
next_clip_index: usize,
|
||||
next_spatial_index: usize,
|
||||
next_clip_id: usize,
|
||||
next_clip_chain_id: u64,
|
||||
builder_start_time: u64,
|
||||
|
||||
|
@ -866,8 +850,7 @@ impl DisplayListBuilder {
|
|||
clip_stack: vec![
|
||||
ClipAndScrollInfo::simple(ClipId::root_scroll_node(pipeline_id)),
|
||||
],
|
||||
next_clip_index: FIRST_CLIP_NODE_INDEX,
|
||||
next_spatial_index: FIRST_SPATIAL_NODE_INDEX,
|
||||
next_clip_id: FIRST_CLIP_ID,
|
||||
next_clip_chain_id: 0,
|
||||
builder_start_time: start_time,
|
||||
content_size,
|
||||
|
@ -893,8 +876,7 @@ impl DisplayListBuilder {
|
|||
self.save_state = Some(SaveState {
|
||||
clip_stack_len: self.clip_stack.len(),
|
||||
dl_len: self.data.len(),
|
||||
next_clip_index: self.next_clip_index,
|
||||
next_spatial_index: self.next_spatial_index,
|
||||
next_clip_id: self.next_clip_id,
|
||||
next_clip_chain_id: self.next_clip_chain_id,
|
||||
});
|
||||
}
|
||||
|
@ -905,8 +887,7 @@ impl DisplayListBuilder {
|
|||
|
||||
self.clip_stack.truncate(state.clip_stack_len);
|
||||
self.data.truncate(state.dl_len);
|
||||
self.next_clip_index = state.next_clip_index;
|
||||
self.next_spatial_index = state.next_spatial_index;
|
||||
self.next_clip_id = state.next_clip_id;
|
||||
self.next_clip_chain_id = state.next_clip_chain_id;
|
||||
}
|
||||
|
||||
|
@ -1307,7 +1288,7 @@ impl DisplayListBuilder {
|
|||
transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
perspective: Option<LayoutTransform>,
|
||||
) -> ClipId {
|
||||
let id = self.generate_spatial_index();
|
||||
let id = self.generate_clip_id();
|
||||
let item = SpecificDisplayItem::PushReferenceFrame(PushReferenceFrameDisplayListItem {
|
||||
reference_frame: ReferenceFrame {
|
||||
transform,
|
||||
|
@ -1357,14 +1338,9 @@ impl DisplayListBuilder {
|
|||
self.push_iter(stops);
|
||||
}
|
||||
|
||||
fn generate_clip_index(&mut self) -> ClipId {
|
||||
self.next_clip_index += 1;
|
||||
ClipId::Clip(self.next_clip_index - 1, self.pipeline_id)
|
||||
}
|
||||
|
||||
fn generate_spatial_index(&mut self) -> ClipId {
|
||||
self.next_spatial_index += 1;
|
||||
ClipId::Spatial(self.next_spatial_index - 1, self.pipeline_id)
|
||||
fn generate_clip_id(&mut self) -> ClipId {
|
||||
self.next_clip_id += 1;
|
||||
ClipId::Clip(self.next_clip_id - 1, self.pipeline_id)
|
||||
}
|
||||
|
||||
fn generate_clip_chain_id(&mut self) -> ClipChainId {
|
||||
|
@ -1410,8 +1386,8 @@ impl DisplayListBuilder {
|
|||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
{
|
||||
let clip_id = self.generate_clip_index();
|
||||
let scroll_frame_id = self.generate_spatial_index();
|
||||
let clip_id = self.generate_clip_id();
|
||||
let scroll_frame_id = self.generate_clip_id();
|
||||
let item = SpecificDisplayItem::ScrollFrame(ScrollFrameDisplayItem {
|
||||
clip_id,
|
||||
scroll_frame_id,
|
||||
|
@ -1475,7 +1451,7 @@ impl DisplayListBuilder {
|
|||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
{
|
||||
let id = self.generate_clip_index();
|
||||
let id = self.generate_clip_id();
|
||||
let item = SpecificDisplayItem::Clip(ClipDisplayItem {
|
||||
id,
|
||||
image_mask,
|
||||
|
@ -1498,7 +1474,7 @@ impl DisplayListBuilder {
|
|||
previously_applied_offset: LayoutVector2D,
|
||||
|
||||
) -> ClipId {
|
||||
let id = self.generate_spatial_index();
|
||||
let id = self.generate_clip_id();
|
||||
let item = SpecificDisplayItem::StickyFrame(StickyFrameDisplayItem {
|
||||
id,
|
||||
margins,
|
||||
|
@ -1536,7 +1512,7 @@ impl DisplayListBuilder {
|
|||
ignore_missing_pipeline: bool
|
||||
) {
|
||||
let item = SpecificDisplayItem::Iframe(IframeDisplayItem {
|
||||
clip_id: self.generate_clip_index(),
|
||||
clip_id: self.generate_clip_id(),
|
||||
pipeline_id,
|
||||
ignore_missing_pipeline,
|
||||
});
|
||||
|
@ -1565,8 +1541,7 @@ impl DisplayListBuilder {
|
|||
builder_start_time: self.builder_start_time,
|
||||
builder_finish_time: end_time,
|
||||
send_start_time: 0,
|
||||
total_clip_nodes: self.next_clip_index,
|
||||
total_spatial_nodes: self.next_spatial_index,
|
||||
total_clip_ids: self.next_clip_id,
|
||||
},
|
||||
data: self.data,
|
||||
},
|
||||
|
|
|
@ -26,7 +26,7 @@ features = ["capture", "serialize_program"]
|
|||
dwrote = "0.4.1"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.6"
|
||||
core-graphics = "0.14"
|
||||
core-foundation = "0.5"
|
||||
core-graphics = "0.13"
|
||||
foreign-types = "0.3.0"
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
e600bfe68efac6416ce2e8091d7344744771f6db
|
||||
0e9563688e575cd662570f54bc9d6f849040dbf8
|
||||
|
|
|
@ -1656,7 +1656,7 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
|
|||
|
||||
let clip_node_id_ref = unsafe { clip_node_id.as_ref() };
|
||||
let clip_node_id = match clip_node_id_ref {
|
||||
Some(clip_node_id) => Some(unpack_clip_id(*clip_node_id, state.pipeline_id)),
|
||||
Some(clip_node_id) => Some(ClipId::Clip(*clip_node_id, state.pipeline_id)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
|
@ -1710,7 +1710,13 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
|
|||
let ref_frame_id = state.frame_builder
|
||||
.dl_builder
|
||||
.push_reference_frame(&prim_info, transform_binding, perspective);
|
||||
*out_reference_frame_id = pack_clip_id(ref_frame_id);
|
||||
match ref_frame_id {
|
||||
ClipId::Clip(id, pipeline_id) => {
|
||||
assert!(pipeline_id == state.pipeline_id);
|
||||
*out_reference_frame_id = id;
|
||||
},
|
||||
_ => panic!("Pushing a reference frame must produce a ClipId::Clip"),
|
||||
}
|
||||
|
||||
prim_info.rect.origin = LayoutPoint::zero();
|
||||
prim_info.clip_rect.origin = LayoutPoint::zero();
|
||||
|
@ -1749,11 +1755,7 @@ pub extern "C" fn wr_dp_define_clipchain(state: &mut WrState,
|
|||
-> u64 {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
let parent = unsafe { parent_clipchain_id.as_ref() }.map(|id| ClipChainId(*id, state.pipeline_id));
|
||||
let clips_slice : Vec<ClipId> = make_slice(clips, clips_count)
|
||||
.iter()
|
||||
.map(|id| unpack_clip_id(*id, state.pipeline_id))
|
||||
.collect();
|
||||
|
||||
let clips_slice : Vec<ClipId> = make_slice(clips, clips_count).iter().map(|id| ClipId::Clip(*id, state.pipeline_id)).collect();
|
||||
let clipchain_id = state.frame_builder.dl_builder.define_clip_chain(parent, clips_slice);
|
||||
assert!(clipchain_id.1 == state.pipeline_id);
|
||||
clipchain_id.0
|
||||
|
@ -1776,19 +1778,26 @@ pub extern "C" fn wr_dp_define_clip(state: &mut WrState,
|
|||
|
||||
let clip_id = if let Some(&pid) = parent_id {
|
||||
state.frame_builder.dl_builder.define_clip_with_parent(
|
||||
unpack_clip_id(pid, state.pipeline_id),
|
||||
ClipId::Clip(pid, state.pipeline_id),
|
||||
clip_rect, complex_iter, mask)
|
||||
} else {
|
||||
state.frame_builder.dl_builder.define_clip(clip_rect, complex_iter, mask)
|
||||
};
|
||||
pack_clip_id(clip_id)
|
||||
// return the usize id value from inside the ClipId::Clip(..)
|
||||
match clip_id {
|
||||
ClipId::Clip(id, pipeline_id) => {
|
||||
assert!(pipeline_id == state.pipeline_id);
|
||||
id
|
||||
},
|
||||
_ => panic!("Got unexpected clip id type"),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_clip(state: &mut WrState,
|
||||
clip_id: usize) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
state.frame_builder.dl_builder.push_clip_id(unpack_clip_id(clip_id, state.pipeline_id));
|
||||
state.frame_builder.dl_builder.push_clip_id(ClipId::Clip(clip_id, state.pipeline_id));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -1817,7 +1826,13 @@ pub extern "C" fn wr_dp_define_sticky_frame(state: &mut WrState,
|
|||
unsafe { left_margin.as_ref() }.cloned()
|
||||
),
|
||||
vertical_bounds, horizontal_bounds, applied_offset);
|
||||
pack_clip_id(clip_id)
|
||||
match clip_id {
|
||||
ClipId::Clip(id, pipeline_id) => {
|
||||
assert!(pipeline_id == state.pipeline_id);
|
||||
id
|
||||
},
|
||||
_ => panic!("Got unexpected clip id type"),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -1833,7 +1848,7 @@ pub extern "C" fn wr_dp_define_scroll_layer(state: &mut WrState,
|
|||
|
||||
let new_id = if let Some(&pid) = parent_id {
|
||||
state.frame_builder.dl_builder.define_scroll_frame_with_parent(
|
||||
unpack_clip_id(pid, state.pipeline_id),
|
||||
ClipId::Clip(pid, state.pipeline_id),
|
||||
Some(ExternalScrollId(scroll_id, state.pipeline_id)),
|
||||
content_rect,
|
||||
clip_rect,
|
||||
|
@ -1852,14 +1867,20 @@ pub extern "C" fn wr_dp_define_scroll_layer(state: &mut WrState,
|
|||
)
|
||||
};
|
||||
|
||||
pack_clip_id(new_id)
|
||||
match new_id {
|
||||
ClipId::Clip(id, pipeline_id) => {
|
||||
assert!(pipeline_id == state.pipeline_id);
|
||||
id
|
||||
},
|
||||
_ => panic!("Got unexpected clip id type"),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_scroll_layer(state: &mut WrState,
|
||||
scroll_id: usize) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
let clip_id = unpack_clip_id(scroll_id, state.pipeline_id);
|
||||
let clip_id = ClipId::Clip(scroll_id, state.pipeline_id);
|
||||
state.frame_builder.dl_builder.push_clip_id(clip_id);
|
||||
}
|
||||
|
||||
|
@ -1878,10 +1899,11 @@ pub extern "C" fn wr_dp_push_clip_and_scroll_info(state: &mut WrState,
|
|||
let clip_chain_id = unsafe { clip_chain_id.as_ref() };
|
||||
let info = if let Some(&ccid) = clip_chain_id {
|
||||
ClipAndScrollInfo::new(
|
||||
unpack_clip_id(scroll_id, state.pipeline_id),
|
||||
ClipId::Clip(scroll_id, state.pipeline_id),
|
||||
ClipId::ClipChain(ClipChainId(ccid, state.pipeline_id)))
|
||||
} else {
|
||||
ClipAndScrollInfo::simple(unpack_clip_id(scroll_id, state.pipeline_id))
|
||||
ClipAndScrollInfo::simple(
|
||||
ClipId::Clip(scroll_id, state.pipeline_id))
|
||||
};
|
||||
state.frame_builder.dl_builder.push_clip_and_scroll_info(info);
|
||||
}
|
||||
|
@ -2441,27 +2463,8 @@ extern "C" {
|
|||
pub extern "C" fn wr_root_scroll_node_id() -> usize {
|
||||
// The PipelineId doesn't matter here, since we just want the numeric part of the id
|
||||
// produced for any given root reference frame.
|
||||
pack_clip_id(ClipId::root_scroll_node(PipelineId(0, 0)))
|
||||
}
|
||||
|
||||
fn pack_clip_id(id: ClipId) -> usize {
|
||||
let (id, type_value) = match id {
|
||||
ClipId::Spatial(id, _) => (id, 0),
|
||||
ClipId::Clip(id, _) => (id, 1),
|
||||
ClipId::ClipChain(..) => unreachable!("Tried to pack a clip chain id"),
|
||||
};
|
||||
|
||||
assert!(id <= usize::max_value() >> 1);
|
||||
return (id << 1) + type_value;
|
||||
}
|
||||
|
||||
fn unpack_clip_id(id: usize, pipeline_id: PipelineId) -> ClipId {
|
||||
let type_value = id & 0b01;
|
||||
let id = id >> 1;
|
||||
|
||||
match type_value {
|
||||
0 => ClipId::Spatial(id, pipeline_id),
|
||||
1 => ClipId::Clip(id, pipeline_id),
|
||||
_ => unreachable!("Got a bizarre value for the clip type"),
|
||||
match ClipId::root_scroll_node(PipelineId(0, 0)) {
|
||||
ClipId::Clip(id, _) => id,
|
||||
_ => unreachable!("Got a non Clip ClipId for root reference frame."),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -401,17 +401,14 @@ struct BuiltDisplayListDescriptor {
|
|||
uint64_t builder_finish_time;
|
||||
// The third IPC time stamp: just before sending
|
||||
uint64_t send_start_time;
|
||||
// The amount of clipping nodes created while building this display list.
|
||||
uintptr_t total_clip_nodes;
|
||||
// The amount of spatial nodes created while building this display list.
|
||||
uintptr_t total_spatial_nodes;
|
||||
// The amount of clips ids assigned while building this display list.
|
||||
uintptr_t total_clip_ids;
|
||||
|
||||
bool operator==(const BuiltDisplayListDescriptor& aOther) const {
|
||||
return builder_start_time == aOther.builder_start_time &&
|
||||
builder_finish_time == aOther.builder_finish_time &&
|
||||
send_start_time == aOther.send_start_time &&
|
||||
total_clip_nodes == aOther.total_clip_nodes &&
|
||||
total_spatial_nodes == aOther.total_spatial_nodes;
|
||||
total_clip_ids == aOther.total_clip_ids;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ byteorder = "1.0"
|
|||
env_logger = { version = "0.5", optional = true }
|
||||
euclid = "0.17"
|
||||
gleam = "0.5"
|
||||
glutin = "0.17"
|
||||
glutin = "0.15"
|
||||
app_units = "0.6"
|
||||
image = "0.19"
|
||||
clap = { version = "2", features = ["yaml"] }
|
||||
|
@ -27,12 +27,12 @@ osmesa-sys = { version = "0.1.2", optional = true }
|
|||
osmesa-src = { git = "https://github.com/jrmuizel/osmesa-src", optional = true, branch = "serialize" }
|
||||
webrender = {path = "../webrender", features=["capture","replay","debugger","png","profiler"]}
|
||||
webrender_api = {path = "../webrender_api", features=["serialize","deserialize"]}
|
||||
winit = "0.16"
|
||||
winit = "0.13"
|
||||
serde = {version = "1.0", features = ["derive"] }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-graphics = "0.14"
|
||||
core-foundation = "0.6"
|
||||
core-graphics = "0.13"
|
||||
core-foundation = "0.5"
|
||||
|
||||
[features]
|
||||
headless = [ "osmesa-sys", "osmesa-src" ]
|
||||
|
@ -43,4 +43,4 @@ dwrote = "0.4.1"
|
|||
mozangle = {version = "0.1.5", features = ["egl"]}
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
|
||||
font-loader = "0.7"
|
||||
font-loader = "0.6"
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use glutin::{self, ContextBuilder, CreationError};
|
||||
#[cfg(not(windows))]
|
||||
use glutin::dpi::PhysicalSize;
|
||||
use winit::{EventsLoop, Window, WindowBuilder};
|
||||
|
||||
#[cfg(not(windows))]
|
||||
|
@ -67,7 +65,7 @@ impl glutin::GlContext for Context {
|
|||
match *self {}
|
||||
}
|
||||
|
||||
fn resize(&self, _: PhysicalSize) {
|
||||
fn resize(&self, _: u32, _: u32) {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ use glutin::PixelFormatRequirements;
|
|||
use glutin::ReleaseBehavior;
|
||||
use glutin::Robustness;
|
||||
use glutin::Api;
|
||||
use glutin::dpi::PhysicalSize;
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::c_int;
|
||||
|
@ -207,7 +206,7 @@ impl GlContext for Context {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn resize(&self, _: PhysicalSize) {}
|
||||
fn resize(&self, _: u32, _: u32) {}
|
||||
}
|
||||
|
||||
unsafe impl Send for Context {}
|
||||
|
|
|
@ -63,7 +63,6 @@ mod cgfont_to_data;
|
|||
use binary_frame_reader::BinaryFrameReader;
|
||||
use gleam::gl;
|
||||
use glutin::GlContext;
|
||||
use glutin::dpi::{LogicalPosition, LogicalSize};
|
||||
use perf::PerfHarness;
|
||||
use png::save_flipped;
|
||||
use rawtest::RawtestHarness;
|
||||
|
@ -184,39 +183,35 @@ impl WindowWrapper {
|
|||
fn get_inner_size(&self) -> DeviceUintSize {
|
||||
//HACK: `winit` needs to figure out its hidpi story...
|
||||
#[cfg(target_os = "macos")]
|
||||
fn inner_size(window: &winit::Window) -> LogicalSize {
|
||||
let LogicalSize { width, height } = window.get_inner_size().unwrap();
|
||||
let factor = window.get_hidpi_factor();
|
||||
LogicalSize::new(width * factor, height * factor)
|
||||
fn inner_size(window: &winit::Window) -> (u32, u32) {
|
||||
let (w, h) = window.get_inner_size().unwrap();
|
||||
let factor = window.hidpi_factor();
|
||||
((w as f32 * factor) as _, (h as f32 * factor) as _)
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
fn inner_size(window: &winit::Window) -> LogicalSize {
|
||||
fn inner_size(window: &winit::Window) -> (u32, u32) {
|
||||
window.get_inner_size().unwrap()
|
||||
}
|
||||
let LogicalSize { width, height } = match *self {
|
||||
let (w, h) = match *self {
|
||||
WindowWrapper::Window(ref window, _) => inner_size(window.window()),
|
||||
WindowWrapper::Angle(ref window, ..) => inner_size(window),
|
||||
WindowWrapper::Headless(ref context, _) => LogicalSize::new(context.width as f64, context.height as f64),
|
||||
WindowWrapper::Headless(ref context, _) => (context.width, context.height),
|
||||
};
|
||||
DeviceUintSize::new(width as u32, height as u32)
|
||||
DeviceUintSize::new(w, h)
|
||||
}
|
||||
|
||||
fn hidpi_factor(&self) -> f32 {
|
||||
match *self {
|
||||
WindowWrapper::Window(ref window, _) => window.get_hidpi_factor() as f32,
|
||||
WindowWrapper::Angle(ref window, ..) => window.get_hidpi_factor() as f32,
|
||||
WindowWrapper::Window(ref window, _) => window.hidpi_factor(),
|
||||
WindowWrapper::Angle(ref window, ..) => window.hidpi_factor(),
|
||||
WindowWrapper::Headless(_, _) => 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, size: DeviceUintSize) {
|
||||
match *self {
|
||||
WindowWrapper::Window(ref mut window, _) => {
|
||||
window.set_inner_size(LogicalSize::new(size.width as f64, size.height as f64))
|
||||
},
|
||||
WindowWrapper::Angle(ref mut window, ..) => {
|
||||
window.set_inner_size(LogicalSize::new(size.width as f64, size.height as f64))
|
||||
},
|
||||
WindowWrapper::Window(ref mut window, _) => window.set_inner_size(size.width, size.height),
|
||||
WindowWrapper::Angle(ref mut window, ..) => window.set_inner_size(size.width, size.height),
|
||||
WindowWrapper::Headless(_, _) => unimplemented!(), // requites Glutin update
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +259,7 @@ fn make_window(
|
|||
let window_builder = winit::WindowBuilder::new()
|
||||
.with_title("WRench")
|
||||
.with_multitouch()
|
||||
.with_dimensions(LogicalSize::new(size.width as f64, size.height as f64));
|
||||
.with_dimensions(size.width, size.height);
|
||||
|
||||
let init = |context: &glutin::GlContext| {
|
||||
unsafe {
|
||||
|
@ -588,7 +583,7 @@ fn render<'a>(
|
|||
winit::WindowEvent::Focused(..) => {
|
||||
do_render = true;
|
||||
}
|
||||
winit::WindowEvent::CursorMoved { position: LogicalPosition { x, y }, .. } => {
|
||||
winit::WindowEvent::CursorMoved { position: (x, y), .. } => {
|
||||
cursor_position = WorldPoint::new(x as f32, y as f32);
|
||||
do_render = true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"01f34fc5a612332c1a3aca9fcd89cd254afa02a27e6e538b0a2fa4280ef4fa66","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/array.rs":"d7af185408d937354f484e3ef97cb1a56e06b39965cbdc89de4bcdafb1d57f06","src/base.rs":"3032ea5253b2d4bd323d0656fc863d1e787642121702ad741c6055d96d0b3d5c","src/boolean.rs":"f5b4d295aaf6cc3681212afebeae2974c5d551125badcc066e6089ac0d2a0873","src/bundle.rs":"de092198bbc3486f617131e9f5f321812c4839da505409abaa70217f05f40450","src/data.rs":"a1d7e6430c745731fc7b2aee49af9f14e79c8a288951c82ea6507689a3356af8","src/date.rs":"a02f6cca7b6e8fbabc7713177429012658dba5146556e14a08e7baaf81958d83","src/dictionary.rs":"429005bc00890b655c8bdf0d7361eb20187ba8725552261aeaf52690c3f2683f","src/error.rs":"22c21087d9c2c103d1bcb2c4af33b684317bbda5d4747902e510d410f8c1a14b","src/filedescriptor.rs":"6ecd8570fad620fc20726539fe11e9f914e3742af9f3208a31727e89a4cd92ba","src/lib.rs":"900179d9ada4b8f000ced4121a9981cdf5ea83277e812177f4126779b818f50c","src/number.rs":"0c2842b8ea973a2c12173a13544b7d49472df11e166540ca5c28f38f54a746f6","src/propertylist.rs":"2ef4b1f44f688fd49ab810a0c8eccc7c40320fa16f93ff1453edcd2fd0d7200f","src/runloop.rs":"bb400ffe84949c4faa4a91f196aeb0a88b31984d206cd236c9daf27005b7744a","src/set.rs":"f23edb8fc009c24600f017131ab734e91129907248713618be89a0719622a9e9","src/string.rs":"50c08f0504c718576e4f2397218a963ab701de0214422dc82e1991d4ab9a00e3","src/timezone.rs":"65859378232ee55f04bc4544b88f5dbc21f5db01bd16f2df3e82136ee3ce26b4","src/url.rs":"ee5370a1ba88823ee0eaa8615c5dafd55cedd7bd50172e9f2caa52ed305e2233","src/uuid.rs":"c532363a1a322a88e195f8606e613a68012708454b0d61ffe7abce432ec68596","tests/use_macro_outside_crate.rs":"452a1329d304bf0301929278aab275cc9b6d57e4ae799b4acd6f2210b1ed0a49"},"package":"286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"}
|
|
@ -0,0 +1,39 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "core-foundation"
|
||||
version = "0.5.1"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "Bindings to Core Foundation for OS X"
|
||||
homepage = "https://github.com/servo/core-foundation-rs"
|
||||
license = "MIT / Apache-2.0"
|
||||
repository = "https://github.com/servo/core-foundation-rs"
|
||||
[dependencies.chrono]
|
||||
version = "0.4"
|
||||
optional = true
|
||||
|
||||
[dependencies.core-foundation-sys]
|
||||
version = "0.5.1"
|
||||
|
||||
[dependencies.libc]
|
||||
version = "0.2"
|
||||
|
||||
[dependencies.uuid]
|
||||
version = "0.5"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
mac_os_10_7_support = ["core-foundation-sys/mac_os_10_7_support"]
|
||||
mac_os_10_8_features = ["core-foundation-sys/mac_os_10_8_features"]
|
||||
with-chrono = ["chrono"]
|
||||
with-uuid = ["uuid"]
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2012-2013 Mozilla Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,289 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Heterogeneous immutable arrays.
|
||||
|
||||
pub use core_foundation_sys::array::*;
|
||||
pub use core_foundation_sys::base::CFIndex;
|
||||
use core_foundation_sys::base::{CFTypeRef, CFRelease, kCFAllocatorDefault};
|
||||
use libc::c_void;
|
||||
use std::mem;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::marker::PhantomData;
|
||||
use std;
|
||||
use std::ops::Deref;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
use base::{CFIndexConvertible, TCFType, TCFTypeRef, CFRange};
|
||||
|
||||
/// A heterogeneous immutable array.
|
||||
pub struct CFArray<T = *const c_void>(CFArrayRef, PhantomData<T>);
|
||||
|
||||
/// A reference to an element inside the array
|
||||
pub struct ItemRef<'a, T: 'a>(ManuallyDrop<T>, PhantomData<&'a T>);
|
||||
|
||||
impl<'a, T> Deref for ItemRef<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Debug> Debug for ItemRef<'a, T> {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait describing how to convert from the stored *const c_void to the desired T
|
||||
pub unsafe trait FromVoid {
|
||||
unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> where Self: std::marker::Sized;
|
||||
}
|
||||
|
||||
unsafe impl FromVoid for u32 {
|
||||
unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> {
|
||||
// Functions like CGFontCopyTableTags treat the void*'s as u32's
|
||||
// so we convert by casting directly
|
||||
ItemRef(ManuallyDrop::new(x as u32), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: TCFType> FromVoid for T {
|
||||
unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> {
|
||||
ItemRef(ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for CFArray<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { CFRelease(self.as_CFTypeRef()) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CFArrayIterator<'a, T: 'a> {
|
||||
array: &'a CFArray<T>,
|
||||
index: CFIndex,
|
||||
len: CFIndex,
|
||||
}
|
||||
|
||||
impl<'a, T: FromVoid> Iterator for CFArrayIterator<'a, T> {
|
||||
type Item = ItemRef<'a, T>;
|
||||
|
||||
fn next(&mut self) -> Option<ItemRef<'a, T>> {
|
||||
if self.index >= self.len {
|
||||
None
|
||||
} else {
|
||||
let value = unsafe { self.array.get_unchecked(self.index) };
|
||||
self.index += 1;
|
||||
Some(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: FromVoid> ExactSizeIterator for CFArrayIterator<'a, T> {
|
||||
fn len(&self) -> usize {
|
||||
(self.array.len() - self.index) as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl_TCFTypeGeneric!(CFArray, CFArrayRef, CFArrayGetTypeID);
|
||||
impl_CFTypeDescriptionGeneric!(CFArray);
|
||||
|
||||
impl<T> CFArray<T> {
|
||||
/// Creates a new `CFArray` with the given elements, which must be `CFType` objects.
|
||||
pub fn from_CFTypes(elems: &[T]) -> CFArray<T> where T: TCFType {
|
||||
unsafe {
|
||||
let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
|
||||
let array_ref = CFArrayCreate(kCFAllocatorDefault,
|
||||
mem::transmute(elems.as_ptr()),
|
||||
elems.len().to_CFIndex(),
|
||||
&kCFTypeArrayCallBacks);
|
||||
TCFType::wrap_under_create_rule(array_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> CFArray {
|
||||
unsafe { CFArray::wrap_under_get_rule(self.0) }
|
||||
}
|
||||
|
||||
/// Returns the same array, but with the type reset to void pointers.
|
||||
/// Equal to `to_untyped`, but is faster since it does not increment the retain count.
|
||||
#[inline]
|
||||
pub fn into_untyped(self) -> CFArray {
|
||||
let reference = self.0;
|
||||
mem::forget(self);
|
||||
unsafe { CFArray::wrap_under_create_rule(reference) }
|
||||
}
|
||||
|
||||
/// Iterates over the elements of this `CFArray`.
|
||||
///
|
||||
/// Careful; the loop body must wrap the reference properly. Generally, when array elements are
|
||||
/// Core Foundation objects (not always true), they need to be wrapped with
|
||||
/// `TCFType::wrap_under_get_rule()`.
|
||||
#[inline]
|
||||
pub fn iter<'a>(&'a self) -> CFArrayIterator<'a, T> {
|
||||
CFArrayIterator {
|
||||
array: self,
|
||||
index: 0,
|
||||
len: self.len(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> CFIndex {
|
||||
unsafe {
|
||||
CFArrayGetCount(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn get_unchecked<'a>(&'a self, index: CFIndex) -> ItemRef<'a, T> where T: FromVoid {
|
||||
T::from_void(CFArrayGetValueAtIndex(self.0, index))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get<'a>(&'a self, index: CFIndex) -> Option<ItemRef<'a, T>> where T: FromVoid {
|
||||
if index < self.len() {
|
||||
Some(unsafe { T::from_void(CFArrayGetValueAtIndex(self.0, index)) } )
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_values(&self, range: CFRange) -> Vec<*const c_void> {
|
||||
let mut vec = Vec::with_capacity(range.length as usize);
|
||||
unsafe {
|
||||
CFArrayGetValues(self.0, range, vec.as_mut_ptr());
|
||||
vec.set_len(range.length as usize);
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all_values(&self) -> Vec<*const c_void> {
|
||||
self.get_values(CFRange {
|
||||
location: 0,
|
||||
length: self.len()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: FromVoid> IntoIterator for &'a CFArray<T> {
|
||||
type Item = ItemRef<'a, T>;
|
||||
type IntoIter = CFArrayIterator<'a, T>;
|
||||
|
||||
fn into_iter(self) -> CFArrayIterator<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::mem;
|
||||
use base::CFType;
|
||||
|
||||
#[test]
|
||||
fn to_untyped_correct_retain_count() {
|
||||
let array = CFArray::<CFType>::from_CFTypes(&[]);
|
||||
assert_eq!(array.retain_count(), 1);
|
||||
|
||||
let untyped_array = array.to_untyped();
|
||||
assert_eq!(array.retain_count(), 2);
|
||||
assert_eq!(untyped_array.retain_count(), 2);
|
||||
|
||||
mem::drop(array);
|
||||
assert_eq!(untyped_array.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into_untyped() {
|
||||
let array = CFArray::<CFType>::from_CFTypes(&[]);
|
||||
let array2 = array.to_untyped();
|
||||
assert_eq!(array.retain_count(), 2);
|
||||
|
||||
let untyped_array = array.into_untyped();
|
||||
assert_eq!(untyped_array.retain_count(), 2);
|
||||
|
||||
mem::drop(array2);
|
||||
assert_eq!(untyped_array.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn borrow() {
|
||||
use string::CFString;
|
||||
|
||||
let string = CFString::from_static_string("bar");
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
let x;
|
||||
{
|
||||
let arr: CFArray<CFString> = CFArray::from_CFTypes(&[string]);
|
||||
{
|
||||
let p = arr.get(0).unwrap();
|
||||
assert_eq!(p.retain_count(), 1);
|
||||
}
|
||||
{
|
||||
x = arr.get(0).unwrap().clone();
|
||||
assert_eq!(x.retain_count(), 2);
|
||||
assert_eq!(x.to_string(), "bar");
|
||||
}
|
||||
}
|
||||
assert_eq!(x.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_box_and_unbox() {
|
||||
use number::CFNumber;
|
||||
|
||||
let n0 = CFNumber::from(0);
|
||||
let n1 = CFNumber::from(1);
|
||||
let n2 = CFNumber::from(2);
|
||||
let n3 = CFNumber::from(3);
|
||||
let n4 = CFNumber::from(4);
|
||||
let n5 = CFNumber::from(5);
|
||||
|
||||
let arr = CFArray::from_CFTypes(&[
|
||||
n0.as_CFType(),
|
||||
n1.as_CFType(),
|
||||
n2.as_CFType(),
|
||||
n3.as_CFType(),
|
||||
n4.as_CFType(),
|
||||
n5.as_CFType(),
|
||||
]);
|
||||
|
||||
assert!(arr.get_all_values() == &[n0.as_CFTypeRef(),
|
||||
n1.as_CFTypeRef(),
|
||||
n2.as_CFTypeRef(),
|
||||
n3.as_CFTypeRef(),
|
||||
n4.as_CFTypeRef(),
|
||||
n5.as_CFTypeRef()]);
|
||||
|
||||
let mut sum = 0;
|
||||
|
||||
let mut iter = arr.iter();
|
||||
assert_eq!(iter.len(), 6);
|
||||
assert!(iter.next().is_some());
|
||||
assert_eq!(iter.len(), 5);
|
||||
|
||||
for elem in iter {
|
||||
let number: CFNumber = elem.downcast::<CFNumber>().unwrap();
|
||||
sum += number.to_i64().unwrap()
|
||||
}
|
||||
|
||||
assert!(sum == 15);
|
||||
|
||||
for elem in arr.iter() {
|
||||
let number: CFNumber = elem.downcast::<CFNumber>().unwrap();
|
||||
sum += number.to_i64().unwrap()
|
||||
}
|
||||
|
||||
assert!(sum == 30);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
|
||||
pub use core_foundation_sys::base::*;
|
||||
|
||||
use string::CFString;
|
||||
|
||||
pub trait CFIndexConvertible {
|
||||
/// Always use this method to construct a `CFIndex` value. It performs bounds checking to
|
||||
/// ensure the value is in range.
|
||||
fn to_CFIndex(self) -> CFIndex;
|
||||
}
|
||||
|
||||
impl CFIndexConvertible for usize {
|
||||
#[inline]
|
||||
fn to_CFIndex(self) -> CFIndex {
|
||||
let max_CFIndex = CFIndex::max_value();
|
||||
if self > (max_CFIndex as usize) {
|
||||
panic!("value out of range")
|
||||
}
|
||||
self as CFIndex
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType!{
|
||||
/// Superclass of all Core Foundation objects.
|
||||
CFType, CFTypeRef
|
||||
}
|
||||
|
||||
impl CFType {
|
||||
/// Try to downcast the `CFType` to a subclass. Checking if the instance is the
|
||||
/// correct subclass happens at runtime and `None` is returned if it is not the correct type.
|
||||
/// Works similar to [`Box::downcast`] and [`CFPropertyList::downcast`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use core_foundation::string::CFString;
|
||||
/// # use core_foundation::boolean::CFBoolean;
|
||||
/// # use core_foundation::base::{CFType, TCFType};
|
||||
/// #
|
||||
/// // Create a string.
|
||||
/// let string: CFString = CFString::from_static_string("FooBar");
|
||||
/// // Cast it up to a CFType.
|
||||
/// let cf_type: CFType = string.as_CFType();
|
||||
/// // Cast it down again.
|
||||
/// assert!(cf_type.downcast::<CFString>().unwrap().to_string() == "FooBar");
|
||||
/// // Casting it to some other type will yield `None`
|
||||
/// assert!(cf_type.downcast::<CFBoolean>().is_none());
|
||||
/// ```
|
||||
///
|
||||
/// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast
|
||||
/// [`CFPropertyList::downcast`]: ../propertylist/struct.CFPropertyList.html#method.downcast
|
||||
#[inline]
|
||||
pub fn downcast<T: TCFType>(&self) -> Option<T> {
|
||||
if self.instance_of::<T>() {
|
||||
unsafe {
|
||||
let reference = T::Ref::from_void_ptr(self.0);
|
||||
Some(T::wrap_under_get_rule(reference))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Similar to [`downcast`], but consumes self and can thus avoid touching the retain count.
|
||||
///
|
||||
/// [`downcast`]: #method.downcast
|
||||
#[inline]
|
||||
pub fn downcast_into<T: TCFType>(self) -> Option<T> {
|
||||
if self.instance_of::<T>() {
|
||||
unsafe {
|
||||
let reference = T::Ref::from_void_ptr(self.0);
|
||||
mem::forget(self);
|
||||
Some(T::wrap_under_create_rule(reference))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CFType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let desc = unsafe {
|
||||
CFString::wrap_under_create_rule(CFCopyDescription(self.0))
|
||||
};
|
||||
desc.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for CFType {
|
||||
#[inline]
|
||||
fn clone(&self) -> CFType {
|
||||
unsafe {
|
||||
TCFType::wrap_under_get_rule(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for CFType {
|
||||
#[inline]
|
||||
fn eq(&self, other: &CFType) -> bool {
|
||||
unsafe {
|
||||
CFEqual(self.as_CFTypeRef(), other.as_CFTypeRef()) != 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType!(CFAllocator, CFAllocatorRef);
|
||||
impl_TCFType!(CFAllocator, CFAllocatorRef, CFAllocatorGetTypeID);
|
||||
|
||||
impl CFAllocator {
|
||||
#[inline]
|
||||
pub fn new(mut context: CFAllocatorContext) -> CFAllocator {
|
||||
unsafe {
|
||||
let allocator_ref = CFAllocatorCreate(kCFAllocatorDefault, &mut context);
|
||||
TCFType::wrap_under_create_rule(allocator_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// All Core Foundation types implement this trait. The associated type `Ref` specifies the
|
||||
/// associated Core Foundation type: e.g. for `CFType` this is `CFTypeRef`; for `CFArray` this is
|
||||
/// `CFArrayRef`.
|
||||
pub trait TCFType {
|
||||
/// The reference type wrapped inside this type.
|
||||
type Ref: TCFTypeRef;
|
||||
|
||||
/// Returns the object as its concrete TypeRef.
|
||||
fn as_concrete_TypeRef(&self) -> Self::Ref;
|
||||
|
||||
/// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this
|
||||
/// when following Core Foundation's "Create Rule". The reference count is *not* bumped.
|
||||
unsafe fn wrap_under_create_rule(obj: Self::Ref) -> Self;
|
||||
|
||||
/// Returns the type ID for this class.
|
||||
fn type_id() -> CFTypeID;
|
||||
|
||||
/// Returns the object as a wrapped `CFType`. The reference count is incremented by one.
|
||||
#[inline]
|
||||
fn as_CFType(&self) -> CFType {
|
||||
unsafe {
|
||||
TCFType::wrap_under_get_rule(self.as_CFTypeRef())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the object as a wrapped `CFType`. Consumes self and avoids changing the reference
|
||||
/// count.
|
||||
#[inline]
|
||||
fn into_CFType(self) -> CFType
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let reference = self.as_CFTypeRef();
|
||||
mem::forget(self);
|
||||
unsafe { TCFType::wrap_under_create_rule(reference) }
|
||||
}
|
||||
|
||||
/// Returns the object as a raw `CFTypeRef`. The reference count is not adjusted.
|
||||
fn as_CFTypeRef(&self) -> CFTypeRef;
|
||||
|
||||
/// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this
|
||||
/// when following Core Foundation's "Get Rule". The reference count *is* bumped.
|
||||
unsafe fn wrap_under_get_rule(reference: Self::Ref) -> Self;
|
||||
|
||||
/// Returns the reference count of the object. It is unwise to do anything other than test
|
||||
/// whether the return value of this method is greater than zero.
|
||||
#[inline]
|
||||
fn retain_count(&self) -> CFIndex {
|
||||
unsafe {
|
||||
CFGetRetainCount(self.as_CFTypeRef())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the type ID of this object.
|
||||
#[inline]
|
||||
fn type_of(&self) -> CFTypeID {
|
||||
unsafe {
|
||||
CFGetTypeID(self.as_CFTypeRef())
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes a debugging version of this object on standard error.
|
||||
fn show(&self) {
|
||||
unsafe {
|
||||
CFShow(self.as_CFTypeRef())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this value is an instance of another type.
|
||||
#[inline]
|
||||
fn instance_of<OtherCFType: TCFType>(&self) -> bool {
|
||||
self.type_of() == OtherCFType::type_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl TCFType for CFType {
|
||||
type Ref = CFTypeRef;
|
||||
|
||||
#[inline]
|
||||
fn as_concrete_TypeRef(&self) -> CFTypeRef {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_get_rule(reference: CFTypeRef) -> CFType {
|
||||
let reference: CFTypeRef = CFRetain(reference);
|
||||
TCFType::wrap_under_create_rule(reference)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_CFTypeRef(&self) -> CFTypeRef {
|
||||
self.as_concrete_TypeRef()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_create_rule(obj: CFTypeRef) -> CFType {
|
||||
CFType(obj)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_id() -> CFTypeID {
|
||||
// FIXME(pcwalton): Is this right?
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::mem;
|
||||
use boolean::CFBoolean;
|
||||
|
||||
#[test]
|
||||
fn cftype_instance_of() {
|
||||
let string = CFString::from_static_string("foo");
|
||||
let cftype = string.as_CFType();
|
||||
|
||||
assert!(cftype.instance_of::<CFString>());
|
||||
assert!(!cftype.instance_of::<CFBoolean>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn as_cftype_retain_count() {
|
||||
let string = CFString::from_static_string("bar");
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
let cftype = string.as_CFType();
|
||||
assert_eq!(cftype.retain_count(), 2);
|
||||
mem::drop(string);
|
||||
assert_eq!(cftype.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into_cftype_retain_count() {
|
||||
let string = CFString::from_static_string("bar");
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
let cftype = string.into_CFType();
|
||||
assert_eq!(cftype.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn as_cftype_and_downcast() {
|
||||
let string = CFString::from_static_string("bar");
|
||||
let cftype = string.as_CFType();
|
||||
let string2 = cftype.downcast::<CFString>().unwrap();
|
||||
assert_eq!(string2.to_string(), "bar");
|
||||
|
||||
assert_eq!(string.retain_count(), 3);
|
||||
assert_eq!(cftype.retain_count(), 3);
|
||||
assert_eq!(string2.retain_count(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into_cftype_and_downcast_into() {
|
||||
let string = CFString::from_static_string("bar");
|
||||
let cftype = string.into_CFType();
|
||||
let string2 = cftype.downcast_into::<CFString>().unwrap();
|
||||
assert_eq!(string2.to_string(), "bar");
|
||||
assert_eq!(string2.retain_count(), 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! A Boolean type.
|
||||
|
||||
pub use core_foundation_sys::number::{CFBooleanRef, CFBooleanGetTypeID, kCFBooleanTrue, kCFBooleanFalse};
|
||||
|
||||
use base::TCFType;
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// A Boolean type.
|
||||
///
|
||||
/// FIXME(pcwalton): Should be a newtype struct, but that fails due to a Rust compiler bug.
|
||||
CFBoolean, CFBooleanRef
|
||||
}
|
||||
impl_TCFType!(CFBoolean, CFBooleanRef, CFBooleanGetTypeID);
|
||||
impl_CFTypeDescription!(CFBoolean);
|
||||
|
||||
impl CFBoolean {
|
||||
pub fn true_value() -> CFBoolean {
|
||||
unsafe {
|
||||
TCFType::wrap_under_get_rule(kCFBooleanTrue)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn false_value() -> CFBoolean {
|
||||
unsafe {
|
||||
TCFType::wrap_under_get_rule(kCFBooleanFalse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for CFBoolean {
|
||||
fn from(value: bool) -> CFBoolean {
|
||||
if value {
|
||||
CFBoolean::true_value()
|
||||
} else {
|
||||
CFBoolean::false_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CFBoolean> for bool {
|
||||
fn from(value: CFBoolean) -> bool {
|
||||
value.0 == unsafe { kCFBooleanTrue }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn to_and_from_bool() {
|
||||
let b_false = CFBoolean::from(false);
|
||||
let b_true = CFBoolean::from(true);
|
||||
assert_ne!(b_false, b_true);
|
||||
assert_eq!(b_false, CFBoolean::false_value());
|
||||
assert_eq!(b_true, CFBoolean::true_value());
|
||||
assert!(!bool::from(b_false));
|
||||
assert!(bool::from(b_true));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Core Foundation Bundle Type
|
||||
|
||||
pub use core_foundation_sys::bundle::*;
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
|
||||
use base::TCFType;
|
||||
use url::CFURL;
|
||||
use dictionary::CFDictionary;
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// A Bundle type.
|
||||
CFBundle, CFBundleRef
|
||||
}
|
||||
impl_TCFType!(CFBundle, CFBundleRef, CFBundleGetTypeID);
|
||||
|
||||
impl CFBundle {
|
||||
pub fn new(bundleURL: CFURL) -> Option<CFBundle> {
|
||||
unsafe {
|
||||
let bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundleURL.as_concrete_TypeRef());
|
||||
if bundle_ref.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(bundle_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_bundle() -> CFBundle {
|
||||
unsafe {
|
||||
let bundle_ref = CFBundleGetMainBundle();
|
||||
TCFType::wrap_under_get_rule(bundle_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn info_dictionary(&self) -> CFDictionary {
|
||||
unsafe {
|
||||
let info_dictionary = CFBundleGetInfoDictionary(self.0);
|
||||
TCFType::wrap_under_get_rule(info_dictionary)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn executable_url(&self) -> Option<CFURL> {
|
||||
unsafe {
|
||||
let exe_url = CFBundleCopyExecutableURL(self.0);
|
||||
if exe_url.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(exe_url))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn private_frameworks_url(&self) -> Option<CFURL> {
|
||||
unsafe {
|
||||
let fw_url = CFBundleCopyPrivateFrameworksURL(self.0);
|
||||
if fw_url.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(fw_url))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn safari_executable_url() {
|
||||
use string::CFString;
|
||||
use url::{CFURL, kCFURLPOSIXPathStyle};
|
||||
|
||||
let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
|
||||
let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
let cfurl_executable = CFBundle::new(cfurl_path)
|
||||
.expect("Safari not present")
|
||||
.executable_url();
|
||||
assert!(cfurl_executable.is_some());
|
||||
assert_eq!(cfurl_executable
|
||||
.unwrap()
|
||||
.absolute()
|
||||
.get_file_system_path(kCFURLPOSIXPathStyle)
|
||||
.to_string(),
|
||||
"/Applications/Safari.app/Contents/MacOS/Safari");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safari_private_frameworks_url() {
|
||||
use string::CFString;
|
||||
use url::{CFURL, kCFURLPOSIXPathStyle};
|
||||
|
||||
let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
|
||||
let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
let cfurl_executable = CFBundle::new(cfurl_path)
|
||||
.expect("Safari not present")
|
||||
.private_frameworks_url();
|
||||
assert!(cfurl_executable.is_some());
|
||||
assert_eq!(cfurl_executable
|
||||
.unwrap()
|
||||
.absolute()
|
||||
.get_file_system_path(kCFURLPOSIXPathStyle)
|
||||
.to_string(),
|
||||
"/Applications/Safari.app/Contents/Frameworks");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_existant_bundle() {
|
||||
use string::CFString;
|
||||
use url::{CFURL, kCFURLPOSIXPathStyle};
|
||||
|
||||
let cfstr_path = CFString::from_static_string("/usr/local/foo");
|
||||
let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
assert!(CFBundle::new(cfurl_path).is_none());
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Core Foundation byte buffers.
|
||||
|
||||
pub use core_foundation_sys::data::*;
|
||||
use core_foundation_sys::base::CFIndex;
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault};
|
||||
use std::ops::Deref;
|
||||
use std::slice;
|
||||
|
||||
use base::{CFIndexConvertible, TCFType};
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// A byte buffer.
|
||||
CFData, CFDataRef
|
||||
}
|
||||
impl_TCFType!(CFData, CFDataRef, CFDataGetTypeID);
|
||||
impl_CFTypeDescription!(CFData);
|
||||
|
||||
impl CFData {
|
||||
pub fn from_buffer(buffer: &[u8]) -> CFData {
|
||||
unsafe {
|
||||
let data_ref = CFDataCreate(kCFAllocatorDefault,
|
||||
buffer.as_ptr(),
|
||||
buffer.len().to_CFIndex());
|
||||
TCFType::wrap_under_create_rule(data_ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a pointer to the underlying bytes in this data. Note that this byte buffer is
|
||||
/// read-only.
|
||||
#[inline]
|
||||
pub fn bytes<'a>(&'a self) -> &'a [u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(CFDataGetBytePtr(self.0), self.len() as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the length of this byte buffer.
|
||||
#[inline]
|
||||
pub fn len(&self) -> CFIndex {
|
||||
unsafe {
|
||||
CFDataGetLength(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for CFData {
|
||||
type Target = [u8];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &[u8] {
|
||||
self.bytes()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Core Foundation date objects.
|
||||
|
||||
pub use core_foundation_sys::date::*;
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
|
||||
use base::TCFType;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
use chrono::NaiveDateTime;
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// A date.
|
||||
CFDate, CFDateRef
|
||||
}
|
||||
impl_TCFType!(CFDate, CFDateRef, CFDateGetTypeID);
|
||||
impl_CFTypeDescription!(CFDate);
|
||||
impl_CFComparison!(CFDate, CFDateCompare);
|
||||
|
||||
impl CFDate {
|
||||
#[inline]
|
||||
pub fn new(time: CFAbsoluteTime) -> CFDate {
|
||||
unsafe {
|
||||
let date_ref = CFDateCreate(kCFAllocatorDefault, time);
|
||||
TCFType::wrap_under_create_rule(date_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn now() -> CFDate {
|
||||
CFDate::new(unsafe { CFAbsoluteTimeGetCurrent() })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn abs_time(&self) -> CFAbsoluteTime {
|
||||
unsafe {
|
||||
CFDateGetAbsoluteTime(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub fn naive_utc(&self) -> NaiveDateTime {
|
||||
let ts = unsafe {
|
||||
self.abs_time() + kCFAbsoluteTimeIntervalSince1970
|
||||
};
|
||||
let (secs, nanos) = if ts.is_sign_positive() {
|
||||
(ts.trunc() as i64, ts.fract())
|
||||
} else {
|
||||
// nanoseconds can't be negative in NaiveDateTime
|
||||
(ts.trunc() as i64 - 1, 1.0 - ts.fract().abs())
|
||||
};
|
||||
NaiveDateTime::from_timestamp(secs, (nanos * 1e9).floor() as u32)
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub fn from_naive_utc(time: NaiveDateTime) -> CFDate {
|
||||
let secs = time.timestamp();
|
||||
let nanos = time.timestamp_subsec_nanos();
|
||||
let ts = unsafe {
|
||||
secs as f64 + (nanos as f64 / 1e9) - kCFAbsoluteTimeIntervalSince1970
|
||||
};
|
||||
CFDate::new(ts)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::CFDate;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
use chrono::NaiveDateTime;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
fn approx_eq(a: f64, b: f64) -> bool {
|
||||
use std::f64;
|
||||
|
||||
let same_sign = a.is_sign_positive() == b.is_sign_positive();
|
||||
let equal = ((a - b).abs() / f64::min(a.abs() + b.abs(), f64::MAX)) < f64::EPSILON;
|
||||
(same_sign && equal)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn date_comparison() {
|
||||
let now = CFDate::now();
|
||||
let past = CFDate::new(now.abs_time() - 1.0);
|
||||
assert_eq!(now.cmp(&past), Ordering::Greater);
|
||||
assert_eq!(now.cmp(&now), Ordering::Equal);
|
||||
assert_eq!(past.cmp(&now), Ordering::Less);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn date_equality() {
|
||||
let now = CFDate::now();
|
||||
let same_time = CFDate::new(now.abs_time());
|
||||
assert_eq!(now, same_time);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-chrono")]
|
||||
fn date_chrono_conversion_positive() {
|
||||
let date = CFDate::now();
|
||||
let datetime = date.naive_utc();
|
||||
let converted = CFDate::from_naive_utc(datetime);
|
||||
assert!(approx_eq(date.abs_time(), converted.abs_time()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-chrono")]
|
||||
fn date_chrono_conversion_negative() {
|
||||
use super::kCFAbsoluteTimeIntervalSince1970;
|
||||
|
||||
let ts = unsafe {
|
||||
kCFAbsoluteTimeIntervalSince1970 - 420.0
|
||||
};
|
||||
let date = CFDate::new(ts);
|
||||
let datetime: NaiveDateTime = date.naive_utc();
|
||||
let converted = CFDate::from_naive_utc(datetime);
|
||||
assert!(approx_eq(date.abs_time(), converted.abs_time()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,391 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Dictionaries of key-value pairs.
|
||||
|
||||
pub use core_foundation_sys::dictionary::*;
|
||||
|
||||
use core_foundation_sys::base::{CFTypeRef, kCFAllocatorDefault};
|
||||
use libc::c_void;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use base::{CFType, CFIndexConvertible, TCFType, TCFTypeRef};
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// An immutable dictionary of key-value pairs.
|
||||
CFDictionary, CFDictionaryRef
|
||||
}
|
||||
impl_TCFType!(CFDictionary, CFDictionaryRef, CFDictionaryGetTypeID);
|
||||
impl_CFTypeDescription!(CFDictionary);
|
||||
|
||||
impl CFDictionary {
|
||||
pub fn from_CFType_pairs<K: TCFType, V: TCFType>(pairs: &[(K, V)]) -> CFDictionary {
|
||||
let (keys, values): (Vec<CFTypeRef>, Vec<CFTypeRef>) = pairs
|
||||
.iter()
|
||||
.map(|&(ref key, ref value)| (key.as_CFTypeRef(), value.as_CFTypeRef()))
|
||||
.unzip();
|
||||
|
||||
unsafe {
|
||||
let dictionary_ref = CFDictionaryCreate(kCFAllocatorDefault,
|
||||
mem::transmute(keys.as_ptr()),
|
||||
mem::transmute(values.as_ptr()),
|
||||
keys.len().to_CFIndex(),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
TCFType::wrap_under_create_rule(dictionary_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe {
|
||||
CFDictionaryGetCount(self.0) as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains_key(&self, key: *const c_void) -> bool {
|
||||
unsafe { CFDictionaryContainsKey(self.0, key) != 0 }
|
||||
}
|
||||
|
||||
/// Similar to `contains_key` but acts on a higher level, automatically converting from any
|
||||
/// `TCFType` to the raw pointer of its concrete TypeRef.
|
||||
#[inline]
|
||||
pub fn contains_key2<K: TCFType>(&self, key: &K) -> bool {
|
||||
self.contains_key(key.as_concrete_TypeRef().as_void_ptr())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn find(&self, key: *const c_void) -> Option<*const c_void> {
|
||||
unsafe {
|
||||
let mut value: *const c_void = ptr::null();
|
||||
if CFDictionaryGetValueIfPresent(self.0, key, &mut value) != 0 {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Similar to `find` but acts on a higher level, automatically converting from any `TCFType`
|
||||
/// to the raw pointer of its concrete TypeRef.
|
||||
#[inline]
|
||||
pub fn find2<K: TCFType>(&self, key: &K) -> Option<*const c_void> {
|
||||
self.find(key.as_concrete_TypeRef().as_void_ptr())
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the key is not present in the dictionary. Use `find` to get an `Option` instead
|
||||
/// of panicking.
|
||||
#[inline]
|
||||
pub fn get(&self, key: *const c_void) -> *const c_void {
|
||||
self.find(key).expect(&format!("No entry found for key {:p}", key))
|
||||
}
|
||||
|
||||
/// A convenience function to retrieve `CFType` instances.
|
||||
#[inline]
|
||||
pub unsafe fn get_CFType(&self, key: *const c_void) -> CFType {
|
||||
let value: CFTypeRef = mem::transmute(self.get(key));
|
||||
TCFType::wrap_under_get_rule(value)
|
||||
}
|
||||
|
||||
pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) {
|
||||
let length = self.len();
|
||||
let mut keys = Vec::with_capacity(length);
|
||||
let mut values = Vec::with_capacity(length);
|
||||
|
||||
unsafe {
|
||||
CFDictionaryGetKeysAndValues(self.0, keys.as_mut_ptr(), values.as_mut_ptr());
|
||||
keys.set_len(length);
|
||||
values.set_len(length);
|
||||
}
|
||||
|
||||
(keys, values)
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType!{
|
||||
/// An mutable dictionary of key-value pairs.
|
||||
CFMutableDictionary, CFMutableDictionaryRef
|
||||
}
|
||||
|
||||
impl_TCFType!(CFMutableDictionary, CFMutableDictionaryRef, CFDictionaryGetTypeID);
|
||||
impl_CFTypeDescription!(CFMutableDictionary);
|
||||
|
||||
impl CFMutableDictionary {
|
||||
pub fn new() -> Self {
|
||||
Self::with_capacity(0)
|
||||
}
|
||||
|
||||
pub fn with_capacity(capacity: isize) -> Self {
|
||||
unsafe {
|
||||
let dictionary_ref = CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
capacity as _,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
TCFType::wrap_under_create_rule(dictionary_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_with_capacity(&self, capacity: isize) -> Self {
|
||||
unsafe {
|
||||
let dictionary_ref = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, capacity as _, self.0);
|
||||
TCFType::wrap_under_get_rule(dictionary_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_CFType_pairs<K: TCFType, V: TCFType>(pairs: &[(K, V)]) -> CFMutableDictionary {
|
||||
let result = Self::with_capacity(pairs.len() as _);
|
||||
unsafe {
|
||||
for &(ref key, ref value) in pairs {
|
||||
result.add(key.as_CFTypeRef(), value.as_CFTypeRef());
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
// Immutable interface
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe {
|
||||
CFDictionaryGetCount(self.0) as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains_key(&self, key: *const c_void) -> bool {
|
||||
unsafe {
|
||||
CFDictionaryContainsKey(self.0, key) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Similar to `contains_key` but acts on a higher level, automatically converting from any
|
||||
/// `TCFType` to the raw pointer of its concrete TypeRef.
|
||||
#[inline]
|
||||
pub fn contains_key2<K: TCFType>(&self, key: &K) -> bool {
|
||||
self.contains_key(key.as_concrete_TypeRef().as_void_ptr())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn find(&self, key: *const c_void) -> Option<*const c_void> {
|
||||
unsafe {
|
||||
let mut value: *const c_void = ptr::null();
|
||||
if CFDictionaryGetValueIfPresent(self.0, key, &mut value) != 0 {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Similar to `find` but acts on a higher level, automatically converting from any `TCFType`
|
||||
/// to the raw pointer of its concrete TypeRef.
|
||||
#[inline]
|
||||
pub fn find2<K: TCFType>(&self, key: &K) -> Option<*const c_void> {
|
||||
self.find(key.as_concrete_TypeRef().as_void_ptr())
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the key is not present in the dictionary. Use `find` to get an `Option` instead
|
||||
/// of panicking.
|
||||
#[inline]
|
||||
pub fn get(&self, key: *const c_void) -> *const c_void {
|
||||
self.find(key).expect(&format!("No entry found for key {:p}", key))
|
||||
}
|
||||
|
||||
/// A convenience function to retrieve `CFType` instances.
|
||||
#[inline]
|
||||
pub unsafe fn get_CFType(&self, key: *const c_void) -> CFType {
|
||||
let value: CFTypeRef = mem::transmute(self.get(key));
|
||||
TCFType::wrap_under_get_rule(value)
|
||||
}
|
||||
|
||||
pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) {
|
||||
let length = self.len();
|
||||
let mut keys = Vec::with_capacity(length);
|
||||
let mut values = Vec::with_capacity(length);
|
||||
|
||||
unsafe {
|
||||
CFDictionaryGetKeysAndValues(self.0, keys.as_mut_ptr(), values.as_mut_ptr());
|
||||
keys.set_len(length);
|
||||
values.set_len(length);
|
||||
}
|
||||
|
||||
(keys, values)
|
||||
}
|
||||
|
||||
// Mutable interface
|
||||
|
||||
/// Adds the key-value pair to the dictionary if no such key already exist.
|
||||
#[inline]
|
||||
pub unsafe fn add(&self, key: *const c_void, value: *const c_void) {
|
||||
CFDictionaryAddValue(self.0, key, value)
|
||||
}
|
||||
|
||||
/// Similar to `add` but acts on a higher level, automatically converting from any `TCFType`
|
||||
/// to the raw pointer of its concrete TypeRef.
|
||||
#[inline]
|
||||
pub fn add2<K: TCFType, V: TCFType>(&self, key: &K, value: &V) {
|
||||
unsafe {
|
||||
self.add(
|
||||
key.as_concrete_TypeRef().as_void_ptr(),
|
||||
value.as_concrete_TypeRef().as_void_ptr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the value of the key in the dictionary.
|
||||
#[inline]
|
||||
pub unsafe fn set(&self, key: *const c_void, value: *const c_void) {
|
||||
CFDictionarySetValue(self.0, key, value)
|
||||
}
|
||||
|
||||
/// Similar to `set` but acts on a higher level, automatically converting from any `TCFType`
|
||||
/// to the raw pointer of its concrete TypeRef.
|
||||
#[inline]
|
||||
pub fn set2<K: TCFType, V: TCFType>(&self, key: &K, value: &V) {
|
||||
unsafe {
|
||||
self.set(
|
||||
key.as_concrete_TypeRef().as_void_ptr(),
|
||||
value.as_concrete_TypeRef().as_void_ptr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces the value of the key in the dictionary.
|
||||
#[inline]
|
||||
pub unsafe fn replace(&self, key: *const c_void, value: *const c_void) {
|
||||
CFDictionaryReplaceValue(self.0, key, value)
|
||||
}
|
||||
|
||||
/// Similar to `replace` but acts on a higher level, automatically converting from any `TCFType`
|
||||
/// to the raw pointer of its concrete TypeRef.
|
||||
#[inline]
|
||||
pub fn replace2<K: TCFType, V: TCFType>(&self, key: &K, value: &V) {
|
||||
unsafe {
|
||||
self.replace(
|
||||
key.as_concrete_TypeRef().as_void_ptr(),
|
||||
value.as_concrete_TypeRef().as_void_ptr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the value of the key from the dictionary.
|
||||
#[inline]
|
||||
pub unsafe fn remove(&self, key: *const c_void) {
|
||||
CFDictionaryRemoveValue(self.0, key);
|
||||
}
|
||||
|
||||
/// Similar to `remove` but acts on a higher level, automatically converting from any `TCFType`
|
||||
/// to the raw pointer of its concrete TypeRef.
|
||||
#[inline]
|
||||
pub fn remove2<K: TCFType>(&self, key: &K) {
|
||||
unsafe { self.remove(key.as_concrete_TypeRef().as_void_ptr()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remove_all(&self) {
|
||||
unsafe { CFDictionaryRemoveAllValues(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use base::TCFType;
|
||||
use boolean::{CFBoolean, CFBooleanRef};
|
||||
use number::CFNumber;
|
||||
use string::CFString;
|
||||
|
||||
|
||||
#[test]
|
||||
fn dictionary() {
|
||||
let bar = CFString::from_static_string("Bar");
|
||||
let baz = CFString::from_static_string("Baz");
|
||||
let boo = CFString::from_static_string("Boo");
|
||||
let foo = CFString::from_static_string("Foo");
|
||||
let tru = CFBoolean::true_value();
|
||||
let n42 = CFNumber::from(42);
|
||||
|
||||
let d = CFDictionary::from_CFType_pairs(&[
|
||||
(bar.as_CFType(), boo.as_CFType()),
|
||||
(baz.as_CFType(), tru.as_CFType()),
|
||||
(foo.as_CFType(), n42.as_CFType()),
|
||||
]);
|
||||
|
||||
let (v1, v2) = d.get_keys_and_values();
|
||||
assert!(v1 == &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]);
|
||||
assert!(v2 == &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mutable_dictionary() {
|
||||
let bar = CFString::from_static_string("Bar");
|
||||
let baz = CFString::from_static_string("Baz");
|
||||
let boo = CFString::from_static_string("Boo");
|
||||
let foo = CFString::from_static_string("Foo");
|
||||
let tru = CFBoolean::true_value();
|
||||
let n42 = CFNumber::from(42);
|
||||
|
||||
let d = CFMutableDictionary::new();
|
||||
d.add2(&bar, &boo);
|
||||
d.add2(&baz, &tru);
|
||||
d.add2(&foo, &n42);
|
||||
assert_eq!(d.len(), 3);
|
||||
|
||||
let (v1, v2) = d.get_keys_and_values();
|
||||
assert!(v1 == &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]);
|
||||
assert!(v2 == &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]);
|
||||
|
||||
d.remove2(&baz);
|
||||
assert_eq!(d.len(), 2);
|
||||
|
||||
let (v1, v2) = d.get_keys_and_values();
|
||||
assert!(v1 == &[bar.as_CFTypeRef(), foo.as_CFTypeRef()]);
|
||||
assert!(v2 == &[boo.as_CFTypeRef(), n42.as_CFTypeRef()]);
|
||||
|
||||
d.remove_all();
|
||||
assert_eq!(d.len(), 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dict_find2_and_contains_key2() {
|
||||
let dict = CFDictionary::from_CFType_pairs(&[
|
||||
(
|
||||
CFString::from_static_string("hello"),
|
||||
CFBoolean::true_value(),
|
||||
),
|
||||
]);
|
||||
let key = CFString::from_static_string("hello");
|
||||
let invalid_key = CFString::from_static_string("foobar");
|
||||
|
||||
assert!(dict.contains_key2(&key));
|
||||
assert!(!dict.contains_key2(&invalid_key));
|
||||
|
||||
let value = unsafe { CFBoolean::wrap_under_get_rule(dict.find2(&key).unwrap() as CFBooleanRef) };
|
||||
assert_eq!(value, CFBoolean::true_value());
|
||||
assert_eq!(dict.find2(&invalid_key), None);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2016 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Core Foundation errors.
|
||||
|
||||
pub use core_foundation_sys::error::*;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use base::{CFIndex, TCFType};
|
||||
use string::CFString;
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// An error value.
|
||||
CFError, CFErrorRef
|
||||
}
|
||||
impl_TCFType!(CFError, CFErrorRef, CFErrorGetTypeID);
|
||||
|
||||
impl fmt::Debug for CFError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("CFError")
|
||||
.field("domain", &self.domain())
|
||||
.field("code", &self.code())
|
||||
.field("description", &self.description())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CFError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", self.description())
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for CFError {
|
||||
fn description(&self) -> &str {
|
||||
"a Core Foundation error"
|
||||
}
|
||||
}
|
||||
|
||||
impl CFError {
|
||||
/// Returns a string identifying the domain with which this error is
|
||||
/// associated.
|
||||
pub fn domain(&self) -> CFString {
|
||||
unsafe {
|
||||
let s = CFErrorGetDomain(self.0);
|
||||
CFString::wrap_under_get_rule(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the code identifying this type of error.
|
||||
pub fn code(&self) -> CFIndex {
|
||||
unsafe { CFErrorGetCode(self.0) }
|
||||
}
|
||||
|
||||
/// Returns a human-presentable description of the error.
|
||||
pub fn description(&self) -> CFString {
|
||||
unsafe {
|
||||
let s = CFErrorCopyDescription(self.0);
|
||||
CFString::wrap_under_create_rule(s)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
pub use core_foundation_sys::filedescriptor::*;
|
||||
|
||||
use core_foundation_sys::base::{Boolean, CFIndex};
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags};
|
||||
|
||||
use base::TCFType;
|
||||
use runloop::CFRunLoopSource;
|
||||
|
||||
use std::mem;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::ptr;
|
||||
|
||||
declare_TCFType!{
|
||||
CFFileDescriptor, CFFileDescriptorRef
|
||||
}
|
||||
impl_TCFType!(CFFileDescriptor, CFFileDescriptorRef, CFFileDescriptorGetTypeID);
|
||||
|
||||
impl CFFileDescriptor {
|
||||
pub fn new(fd: RawFd,
|
||||
closeOnInvalidate: bool,
|
||||
callout: CFFileDescriptorCallBack,
|
||||
context: Option<&CFFileDescriptorContext>) -> Option<CFFileDescriptor> {
|
||||
let context = context.map_or(ptr::null(), |c| c as *const _);
|
||||
unsafe {
|
||||
let fd_ref = CFFileDescriptorCreate(kCFAllocatorDefault,
|
||||
fd,
|
||||
closeOnInvalidate as Boolean,
|
||||
callout,
|
||||
context);
|
||||
if fd_ref.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(fd_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn context(&self) -> CFFileDescriptorContext {
|
||||
unsafe {
|
||||
let mut context: CFFileDescriptorContext = mem::uninitialized();
|
||||
CFFileDescriptorGetContext(self.0, &mut context);
|
||||
context
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable_callbacks(&self, callback_types: CFOptionFlags) {
|
||||
unsafe {
|
||||
CFFileDescriptorEnableCallBacks(self.0, callback_types)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disable_callbacks(&self, callback_types: CFOptionFlags) {
|
||||
unsafe {
|
||||
CFFileDescriptorDisableCallBacks(self.0, callback_types)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn valid(&self) -> bool {
|
||||
unsafe {
|
||||
CFFileDescriptorIsValid(self.0) != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invalidate(&self) {
|
||||
unsafe {
|
||||
CFFileDescriptorInvalidate(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_run_loop_source(&self, order: CFIndex) -> Option<CFRunLoopSource> {
|
||||
unsafe {
|
||||
let source_ref = CFFileDescriptorCreateRunLoopSource(
|
||||
kCFAllocatorDefault,
|
||||
self.0,
|
||||
order
|
||||
);
|
||||
if source_ref.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(source_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for CFFileDescriptor {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
unsafe {
|
||||
CFFileDescriptorGetNativeDescriptor(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
extern crate libc;
|
||||
|
||||
use super::*;
|
||||
use std::ffi::CString;
|
||||
use libc::{c_void, O_RDWR};
|
||||
use core_foundation_sys::base::{CFOptionFlags};
|
||||
use core_foundation_sys::runloop::{kCFRunLoopDefaultMode};
|
||||
use runloop::{CFRunLoop};
|
||||
|
||||
#[test]
|
||||
fn test_consumed() {
|
||||
let path = CString::new("/dev/null").unwrap();
|
||||
let raw_fd = unsafe { libc::open(path.as_ptr(), O_RDWR, 0) };
|
||||
let cf_fd = CFFileDescriptor::new(raw_fd, true, never_callback, None);
|
||||
assert!(cf_fd.is_some());
|
||||
let cf_fd = cf_fd.unwrap();
|
||||
|
||||
assert!(cf_fd.valid());
|
||||
cf_fd.invalidate();
|
||||
assert!(!cf_fd.valid());
|
||||
|
||||
// close() should fail
|
||||
assert_eq!(unsafe { libc::close(raw_fd) }, -1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unconsumed() {
|
||||
let path = CString::new("/dev/null").unwrap();
|
||||
let raw_fd = unsafe { libc::open(path.as_ptr(), O_RDWR, 0) };
|
||||
let cf_fd = CFFileDescriptor::new(raw_fd, false, never_callback, None);
|
||||
assert!(cf_fd.is_some());
|
||||
let cf_fd = cf_fd.unwrap();
|
||||
|
||||
assert!(cf_fd.valid());
|
||||
cf_fd.invalidate();
|
||||
assert!(!cf_fd.valid());
|
||||
|
||||
// close() should succeed
|
||||
assert_eq!(unsafe { libc::close(raw_fd) }, 0);
|
||||
}
|
||||
|
||||
extern "C" fn never_callback(_f: CFFileDescriptorRef,
|
||||
_callback_types: CFOptionFlags,
|
||||
_info_ptr: *mut c_void) {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
struct TestInfo {
|
||||
value: CFOptionFlags
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_callback() {
|
||||
let mut info = TestInfo { value: 0 };
|
||||
let context = CFFileDescriptorContext {
|
||||
version: 0,
|
||||
info: &mut info as *mut _ as *mut c_void,
|
||||
retain: None,
|
||||
release: None,
|
||||
copyDescription: None
|
||||
};
|
||||
|
||||
let path = CString::new("/dev/null").unwrap();
|
||||
let raw_fd = unsafe { libc::open(path.as_ptr(), O_RDWR, 0) };
|
||||
let cf_fd = CFFileDescriptor::new(raw_fd, true, callback, Some(&context));
|
||||
assert!(cf_fd.is_some());
|
||||
let cf_fd = cf_fd.unwrap();
|
||||
|
||||
assert!(cf_fd.valid());
|
||||
|
||||
let run_loop = CFRunLoop::get_current();
|
||||
let source = CFRunLoopSource::from_file_descriptor(&cf_fd, 0);
|
||||
assert!(source.is_some());
|
||||
unsafe {
|
||||
run_loop.add_source(&source.unwrap(), kCFRunLoopDefaultMode);
|
||||
}
|
||||
|
||||
info.value = 0;
|
||||
cf_fd.enable_callbacks(kCFFileDescriptorReadCallBack);
|
||||
CFRunLoop::run_current();
|
||||
assert_eq!(info.value, kCFFileDescriptorReadCallBack);
|
||||
|
||||
info.value = 0;
|
||||
cf_fd.enable_callbacks(kCFFileDescriptorWriteCallBack);
|
||||
CFRunLoop::run_current();
|
||||
assert_eq!(info.value, kCFFileDescriptorWriteCallBack);
|
||||
|
||||
info.value = 0;
|
||||
cf_fd.disable_callbacks(kCFFileDescriptorReadCallBack | kCFFileDescriptorWriteCallBack);
|
||||
|
||||
cf_fd.invalidate();
|
||||
assert!(!cf_fd.valid());
|
||||
}
|
||||
|
||||
extern "C" fn callback(_f: CFFileDescriptorRef, callback_types: CFOptionFlags, info_ptr: *mut c_void) {
|
||||
assert!(!info_ptr.is_null());
|
||||
|
||||
let info: *mut TestInfo = info_ptr as *mut TestInfo;
|
||||
|
||||
unsafe { (*info).value = callback_types };
|
||||
|
||||
CFRunLoop::get_current().stop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
extern crate core_foundation_sys;
|
||||
extern crate libc;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
extern crate chrono;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! declare_TCFType {
|
||||
(
|
||||
$(#[$doc:meta])*
|
||||
$ty:ident, $raw:ident
|
||||
) => {
|
||||
$(#[$doc])*
|
||||
pub struct $ty($raw);
|
||||
|
||||
impl Drop for $ty {
|
||||
fn drop(&mut self) {
|
||||
unsafe { $crate::base::CFRelease(self.as_CFTypeRef()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_TCFType {
|
||||
($ty:ident, $ty_ref:ident, $ty_id:ident) => {
|
||||
impl $crate::base::TCFType for $ty {
|
||||
type Ref = $ty_ref;
|
||||
|
||||
#[inline]
|
||||
fn as_concrete_TypeRef(&self) -> $ty_ref {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_get_rule(reference: $ty_ref) -> $ty {
|
||||
use std::mem;
|
||||
let reference = mem::transmute($crate::base::CFRetain(mem::transmute(reference)));
|
||||
$crate::base::TCFType::wrap_under_create_rule(reference)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_CFTypeRef(&self) -> $crate::base::CFTypeRef {
|
||||
unsafe {
|
||||
::std::mem::transmute(self.as_concrete_TypeRef())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_create_rule(reference: $ty_ref) -> $ty {
|
||||
$ty(reference)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_id() -> $crate::base::CFTypeID {
|
||||
unsafe {
|
||||
$ty_id()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for $ty {
|
||||
#[inline]
|
||||
fn clone(&self) -> $ty {
|
||||
unsafe {
|
||||
$ty::wrap_under_get_rule(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for $ty {
|
||||
#[inline]
|
||||
fn eq(&self, other: &$ty) -> bool {
|
||||
self.as_CFType().eq(&other.as_CFType())
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for $ty { }
|
||||
}
|
||||
}
|
||||
|
||||
// This is basically identical to the implementation above. I can't
|
||||
// think of a clean way to have them share code
|
||||
#[macro_export]
|
||||
macro_rules! impl_TCFTypeGeneric {
|
||||
($ty:ident, $ty_ref:ident, $ty_id:ident) => {
|
||||
impl<T> $crate::base::TCFType for $ty<T> {
|
||||
type Ref = $ty_ref;
|
||||
|
||||
#[inline]
|
||||
fn as_concrete_TypeRef(&self) -> $ty_ref {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_get_rule(reference: $ty_ref) -> $ty<T> {
|
||||
use std::mem;
|
||||
let reference = mem::transmute($crate::base::CFRetain(mem::transmute(reference)));
|
||||
$crate::base::TCFType::wrap_under_create_rule(reference)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_CFTypeRef(&self) -> ::core_foundation_sys::base::CFTypeRef {
|
||||
unsafe {
|
||||
::std::mem::transmute(self.as_concrete_TypeRef())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_create_rule(obj: $ty_ref) -> $ty<T> {
|
||||
$ty(obj, PhantomData)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_id() -> ::core_foundation_sys::base::CFTypeID {
|
||||
unsafe {
|
||||
$ty_id()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for $ty<T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> $ty<T> {
|
||||
unsafe {
|
||||
$ty::wrap_under_get_rule(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for $ty<T> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &$ty<T>) -> bool {
|
||||
self.as_CFType().eq(&other.as_CFType())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for $ty<T> { }
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_CFTypeDescription {
|
||||
($ty:ident) => {
|
||||
impl ::std::fmt::Debug for $ty {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
self.as_CFType().fmt(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The same as impl_CFTypeDescription but with a type parameter
|
||||
#[macro_export]
|
||||
macro_rules! impl_CFTypeDescriptionGeneric {
|
||||
($ty:ident) => {
|
||||
impl<T> ::std::fmt::Debug for $ty<T> {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
self.as_CFType().fmt(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_CFComparison {
|
||||
($ty:ident, $compare:ident) => {
|
||||
impl PartialOrd for $ty {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &$ty) -> Option<::std::cmp::Ordering> {
|
||||
unsafe {
|
||||
Some($compare(self.as_concrete_TypeRef(), other.as_concrete_TypeRef(), ::std::ptr::null_mut()).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for $ty {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &$ty) -> ::std::cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod array;
|
||||
pub mod base;
|
||||
pub mod boolean;
|
||||
pub mod data;
|
||||
pub mod date;
|
||||
pub mod dictionary;
|
||||
pub mod error;
|
||||
pub mod filedescriptor;
|
||||
pub mod number;
|
||||
pub mod set;
|
||||
pub mod string;
|
||||
pub mod url;
|
||||
pub mod bundle;
|
||||
pub mod propertylist;
|
||||
pub mod runloop;
|
||||
pub mod timezone;
|
||||
pub mod uuid;
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Immutable numbers.
|
||||
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
pub use core_foundation_sys::number::*;
|
||||
use std::mem;
|
||||
|
||||
use base::TCFType;
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// An immutable numeric value.
|
||||
CFNumber, CFNumberRef
|
||||
}
|
||||
impl_TCFType!(CFNumber, CFNumberRef, CFNumberGetTypeID);
|
||||
impl_CFTypeDescription!(CFNumber);
|
||||
impl_CFComparison!(CFNumber, CFNumberCompare);
|
||||
|
||||
impl CFNumber {
|
||||
#[inline]
|
||||
pub fn to_i64(&self) -> Option<i64> {
|
||||
unsafe {
|
||||
let mut value: i64 = 0;
|
||||
let ok = CFNumberGetValue(self.0, kCFNumberSInt64Type, mem::transmute(&mut value));
|
||||
if ok { Some(value) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Option<f32> {
|
||||
unsafe {
|
||||
let mut value: f32 = 0.0;
|
||||
let ok = CFNumberGetValue(self.0, kCFNumberFloat32Type, mem::transmute(&mut value));
|
||||
if ok { Some(value) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Option<f64> {
|
||||
unsafe {
|
||||
let mut value: f64 = 0.0;
|
||||
let ok = CFNumberGetValue(self.0, kCFNumberFloat64Type, mem::transmute(&mut value));
|
||||
if ok { Some(value) } else { None }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for CFNumber {
|
||||
#[inline]
|
||||
fn from(value: i32) -> Self {
|
||||
unsafe {
|
||||
let number_ref = CFNumberCreate(
|
||||
kCFAllocatorDefault,
|
||||
kCFNumberSInt32Type,
|
||||
mem::transmute(&value),
|
||||
);
|
||||
TCFType::wrap_under_create_rule(number_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for CFNumber {
|
||||
#[inline]
|
||||
fn from(value: i64) -> Self {
|
||||
unsafe {
|
||||
let number_ref = CFNumberCreate(
|
||||
kCFAllocatorDefault,
|
||||
kCFNumberSInt64Type,
|
||||
mem::transmute(&value),
|
||||
);
|
||||
TCFType::wrap_under_create_rule(number_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for CFNumber {
|
||||
#[inline]
|
||||
fn from(value: f32) -> Self {
|
||||
unsafe {
|
||||
let number_ref = CFNumberCreate(
|
||||
kCFAllocatorDefault,
|
||||
kCFNumberFloat32Type,
|
||||
mem::transmute(&value),
|
||||
);
|
||||
TCFType::wrap_under_create_rule(number_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for CFNumber {
|
||||
#[inline]
|
||||
fn from(value: f64) -> Self {
|
||||
unsafe {
|
||||
let number_ref = CFNumberCreate(
|
||||
kCFAllocatorDefault,
|
||||
kCFNumberFloat64Type,
|
||||
mem::transmute(&value),
|
||||
);
|
||||
TCFType::wrap_under_create_rule(number_ref)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,326 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Core Foundation property lists
|
||||
|
||||
use std::ptr;
|
||||
use std::mem;
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use error::CFError;
|
||||
use data::CFData;
|
||||
use base::{CFType, TCFType, TCFTypeRef};
|
||||
|
||||
pub use core_foundation_sys::propertylist::*;
|
||||
use core_foundation_sys::error::CFErrorRef;
|
||||
use core_foundation_sys::base::{CFGetRetainCount, CFGetTypeID, CFIndex, CFRetain,
|
||||
CFShow, CFTypeID, kCFAllocatorDefault};
|
||||
|
||||
pub fn create_with_data(data: CFData,
|
||||
options: CFPropertyListMutabilityOptions)
|
||||
-> Result<(*const c_void, CFPropertyListFormat), CFError> {
|
||||
unsafe {
|
||||
let mut error: CFErrorRef = ptr::null_mut();
|
||||
let mut format: CFPropertyListFormat = 0;
|
||||
let property_list = CFPropertyListCreateWithData(kCFAllocatorDefault,
|
||||
data.as_concrete_TypeRef(),
|
||||
options,
|
||||
&mut format,
|
||||
&mut error);
|
||||
if property_list.is_null() {
|
||||
Err(TCFType::wrap_under_create_rule(error))
|
||||
} else {
|
||||
Ok((property_list, format))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_data(property_list: *const c_void, format: CFPropertyListFormat) -> Result<CFData, CFError> {
|
||||
unsafe {
|
||||
let mut error: CFErrorRef = ptr::null_mut();
|
||||
let data_ref = CFPropertyListCreateData(kCFAllocatorDefault,
|
||||
property_list,
|
||||
format,
|
||||
0,
|
||||
&mut error);
|
||||
if data_ref.is_null() {
|
||||
Err(TCFType::wrap_under_create_rule(error))
|
||||
} else {
|
||||
Ok(TCFType::wrap_under_create_rule(data_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Trait for all subclasses of [`CFPropertyList`].
|
||||
///
|
||||
/// [`CFPropertyList`]: struct.CFPropertyList.html
|
||||
pub trait CFPropertyListSubClass: TCFType {
|
||||
/// Create an instance of the superclass type [`CFPropertyList`] for this instance.
|
||||
///
|
||||
/// [`CFPropertyList`]: struct.CFPropertyList.html
|
||||
#[inline]
|
||||
fn to_CFPropertyList(&self) -> CFPropertyList {
|
||||
unsafe { CFPropertyList::wrap_under_get_rule(self.as_concrete_TypeRef().as_void_ptr()) }
|
||||
}
|
||||
|
||||
/// Equal to [`to_CFPropertyList`], but consumes self and avoids changing the reference count.
|
||||
///
|
||||
/// [`to_CFPropertyList`]: #method.to_CFPropertyList
|
||||
#[inline]
|
||||
fn into_CFPropertyList(self) -> CFPropertyList
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let reference = self.as_concrete_TypeRef().as_void_ptr();
|
||||
mem::forget(self);
|
||||
unsafe { CFPropertyList::wrap_under_create_rule(reference) }
|
||||
}
|
||||
}
|
||||
|
||||
impl CFPropertyListSubClass for ::data::CFData {}
|
||||
impl CFPropertyListSubClass for ::string::CFString {}
|
||||
impl CFPropertyListSubClass for ::array::CFArray {}
|
||||
impl CFPropertyListSubClass for ::dictionary::CFDictionary {}
|
||||
impl CFPropertyListSubClass for ::date::CFDate {}
|
||||
impl CFPropertyListSubClass for ::boolean::CFBoolean {}
|
||||
impl CFPropertyListSubClass for ::number::CFNumber {}
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// A CFPropertyList struct. This is superclass to [`CFData`], [`CFString`], [`CFArray`],
|
||||
/// [`CFDictionary`], [`CFDate`], [`CFBoolean`], and [`CFNumber`].
|
||||
///
|
||||
/// This superclass type does not have its own `CFTypeID`, instead each instance has the `CFTypeID`
|
||||
/// of the subclass it is an instance of. Thus, this type cannot implement the [`TCFType`] trait,
|
||||
/// since it cannot implement the static [`TCFType::type_id()`] method.
|
||||
///
|
||||
/// [`CFData`]: ../data/struct.CFData.html
|
||||
/// [`CFString`]: ../string/struct.CFString.html
|
||||
/// [`CFArray`]: ../array/struct.CFArray.html
|
||||
/// [`CFDictionary`]: ../dictionary/struct.CFDictionary.html
|
||||
/// [`CFDate`]: ../date/struct.CFDate.html
|
||||
/// [`CFBoolean`]: ../boolean/struct.CFBoolean.html
|
||||
/// [`CFNumber`]: ../number/struct.CFNumber.html
|
||||
/// [`TCFType`]: ../base/trait.TCFType.html
|
||||
/// [`TCFType::type_id()`]: ../base/trait.TCFType.html#method.type_of
|
||||
CFPropertyList, CFPropertyListRef
|
||||
}
|
||||
|
||||
impl CFPropertyList {
|
||||
#[inline]
|
||||
pub fn as_concrete_TypeRef(&self) -> CFPropertyListRef {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn wrap_under_get_rule(reference: CFPropertyListRef) -> CFPropertyList {
|
||||
let reference = mem::transmute(CFRetain(mem::transmute(reference)));
|
||||
CFPropertyList(reference)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_CFType(&self) -> CFType {
|
||||
unsafe { CFType::wrap_under_get_rule(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_CFType(self) -> CFType
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let reference = self.as_CFTypeRef();
|
||||
mem::forget(self);
|
||||
unsafe { TCFType::wrap_under_create_rule(reference) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_CFTypeRef(&self) -> ::core_foundation_sys::base::CFTypeRef {
|
||||
unsafe { mem::transmute(self.as_concrete_TypeRef()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn wrap_under_create_rule(obj: CFPropertyListRef) -> CFPropertyList {
|
||||
CFPropertyList(obj)
|
||||
}
|
||||
|
||||
/// Returns the reference count of the object. It is unwise to do anything other than test
|
||||
/// whether the return value of this method is greater than zero.
|
||||
#[inline]
|
||||
pub fn retain_count(&self) -> CFIndex {
|
||||
unsafe { CFGetRetainCount(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Returns the type ID of this object. Will be one of CFData, CFString, CFArray, CFDictionary,
|
||||
/// CFDate, CFBoolean, or CFNumber.
|
||||
#[inline]
|
||||
pub fn type_of(&self) -> CFTypeID {
|
||||
unsafe { CFGetTypeID(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Writes a debugging version of this object on standard error.
|
||||
pub fn show(&self) {
|
||||
unsafe { CFShow(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Returns true if this value is an instance of another type.
|
||||
#[inline]
|
||||
pub fn instance_of<OtherCFType: TCFType>(&self) -> bool {
|
||||
self.type_of() == OtherCFType::type_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for CFPropertyList {
|
||||
#[inline]
|
||||
fn clone(&self) -> CFPropertyList {
|
||||
unsafe { CFPropertyList::wrap_under_get_rule(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for CFPropertyList {
|
||||
#[inline]
|
||||
fn eq(&self, other: &CFPropertyList) -> bool {
|
||||
self.as_CFType().eq(&other.as_CFType())
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for CFPropertyList {}
|
||||
|
||||
impl CFPropertyList {
|
||||
/// Try to downcast the [`CFPropertyList`] to a subclass. Checking if the instance is the
|
||||
/// correct subclass happens at runtime and `None` is returned if it is not the correct type.
|
||||
/// Works similar to [`Box::downcast`] and [`CFType::downcast`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use core_foundation::string::CFString;
|
||||
/// # use core_foundation::propertylist::{CFPropertyList, CFPropertyListSubClass};
|
||||
/// #
|
||||
/// // Create a string.
|
||||
/// let string: CFString = CFString::from_static_string("FooBar");
|
||||
/// // Cast it up to a property list.
|
||||
/// let propertylist: CFPropertyList = string.to_CFPropertyList();
|
||||
/// // Cast it down again.
|
||||
/// assert!(propertylist.downcast::<CFString>().unwrap().to_string() == "FooBar");
|
||||
/// ```
|
||||
///
|
||||
/// [`CFPropertyList`]: struct.CFPropertyList.html
|
||||
/// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast
|
||||
pub fn downcast<T: CFPropertyListSubClass>(&self) -> Option<T> {
|
||||
if self.instance_of::<T>() {
|
||||
unsafe {
|
||||
let subclass_ref = T::Ref::from_void_ptr(self.0);
|
||||
Some(T::wrap_under_get_rule(subclass_ref))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Similar to [`downcast`], but consumes self and can thus avoid touching the retain count.
|
||||
///
|
||||
/// [`downcast`]: #method.downcast
|
||||
pub fn downcast_into<T: CFPropertyListSubClass>(self) -> Option<T> {
|
||||
if self.instance_of::<T>() {
|
||||
unsafe {
|
||||
let subclass_ref = T::Ref::from_void_ptr(self.0);
|
||||
mem::forget(self);
|
||||
Some(T::wrap_under_create_rule(subclass_ref))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use string::CFString;
|
||||
use boolean::CFBoolean;
|
||||
|
||||
#[test]
|
||||
fn test_property_list_serialization() {
|
||||
use base::{TCFType, CFEqual};
|
||||
use boolean::CFBoolean;
|
||||
use number::CFNumber;
|
||||
use dictionary::CFDictionary;
|
||||
use string::CFString;
|
||||
use super::*;
|
||||
|
||||
let bar = CFString::from_static_string("Bar");
|
||||
let baz = CFString::from_static_string("Baz");
|
||||
let boo = CFString::from_static_string("Boo");
|
||||
let foo = CFString::from_static_string("Foo");
|
||||
let tru = CFBoolean::true_value();
|
||||
let n42 = CFNumber::from(42);
|
||||
|
||||
let dict1 = CFDictionary::from_CFType_pairs(&[(bar.as_CFType(), boo.as_CFType()),
|
||||
(baz.as_CFType(), tru.as_CFType()),
|
||||
(foo.as_CFType(), n42.as_CFType())]);
|
||||
|
||||
let data = create_data(dict1.as_CFTypeRef(), kCFPropertyListXMLFormat_v1_0).unwrap();
|
||||
let (dict2, _) = create_with_data(data, kCFPropertyListImmutable).unwrap();
|
||||
unsafe {
|
||||
assert!(CFEqual(dict1.as_CFTypeRef(), dict2) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_propertylist_retain_count() {
|
||||
let string = CFString::from_static_string("Bar");
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
|
||||
let propertylist = string.to_CFPropertyList();
|
||||
assert_eq!(string.retain_count(), 2);
|
||||
assert_eq!(propertylist.retain_count(), 2);
|
||||
|
||||
mem::drop(string);
|
||||
assert_eq!(propertylist.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn downcast_string() {
|
||||
let propertylist = CFString::from_static_string("Bar").to_CFPropertyList();
|
||||
assert!(propertylist.downcast::<CFString>().unwrap().to_string() == "Bar");
|
||||
assert!(propertylist.downcast::<CFBoolean>().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn downcast_boolean() {
|
||||
let propertylist = CFBoolean::true_value().to_CFPropertyList();
|
||||
assert!(propertylist.downcast::<CFBoolean>().is_some());
|
||||
assert!(propertylist.downcast::<CFString>().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn downcast_into_fail() {
|
||||
let string = CFString::from_static_string("Bar");
|
||||
let propertylist = string.to_CFPropertyList();
|
||||
assert_eq!(string.retain_count(), 2);
|
||||
|
||||
assert!(propertylist.downcast_into::<CFBoolean>().is_none());
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn downcast_into() {
|
||||
let string = CFString::from_static_string("Bar");
|
||||
let propertylist = string.to_CFPropertyList();
|
||||
assert_eq!(string.retain_count(), 2);
|
||||
|
||||
let string2 = propertylist.downcast_into::<CFString>().unwrap();
|
||||
assert!(string2.to_string() == "Bar");
|
||||
assert_eq!(string2.retain_count(), 2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
pub use core_foundation_sys::runloop::*;
|
||||
use core_foundation_sys::base::CFIndex;
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags};
|
||||
use core_foundation_sys::string::CFStringRef;
|
||||
|
||||
use base::{TCFType};
|
||||
use date::{CFAbsoluteTime, CFTimeInterval};
|
||||
use filedescriptor::CFFileDescriptor;
|
||||
use string::{CFString};
|
||||
|
||||
pub type CFRunLoopMode = CFStringRef;
|
||||
|
||||
|
||||
declare_TCFType!(CFRunLoop, CFRunLoopRef);
|
||||
impl_TCFType!(CFRunLoop, CFRunLoopRef, CFRunLoopGetTypeID);
|
||||
impl_CFTypeDescription!(CFRunLoop);
|
||||
|
||||
impl CFRunLoop {
|
||||
pub fn get_current() -> CFRunLoop {
|
||||
unsafe {
|
||||
let run_loop_ref = CFRunLoopGetCurrent();
|
||||
TCFType::wrap_under_get_rule(run_loop_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_main() -> CFRunLoop {
|
||||
unsafe {
|
||||
let run_loop_ref = CFRunLoopGetMain();
|
||||
TCFType::wrap_under_get_rule(run_loop_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_current() {
|
||||
unsafe {
|
||||
CFRunLoopRun();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop(&self) {
|
||||
unsafe {
|
||||
CFRunLoopStop(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_mode(&self) -> Option<String> {
|
||||
unsafe {
|
||||
let string_ref = CFRunLoopCopyCurrentMode(self.0);
|
||||
if string_ref.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let cf_string: CFString = TCFType::wrap_under_create_rule(string_ref);
|
||||
Some(cf_string.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) -> bool {
|
||||
unsafe {
|
||||
CFRunLoopContainsTimer(self.0, timer.0, mode) != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopAddTimer(self.0, timer.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopRemoveTimer(self.0, timer.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) -> bool {
|
||||
unsafe {
|
||||
CFRunLoopContainsSource(self.0, source.0, mode) != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopAddSource(self.0, source.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopRemoveSource(self.0, source.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) -> bool {
|
||||
unsafe {
|
||||
CFRunLoopContainsObserver(self.0, observer.0, mode) != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopAddObserver(self.0, observer.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopRemoveObserver(self.0, observer.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef);
|
||||
impl_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef, CFRunLoopTimerGetTypeID);
|
||||
|
||||
impl CFRunLoopTimer {
|
||||
pub fn new(fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, callout: CFRunLoopTimerCallBack, context: *mut CFRunLoopTimerContext) -> CFRunLoopTimer {
|
||||
unsafe {
|
||||
let timer_ref = CFRunLoopTimerCreate(kCFAllocatorDefault, fireDate, interval, flags, order, callout, context);
|
||||
TCFType::wrap_under_create_rule(timer_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
declare_TCFType!(CFRunLoopSource, CFRunLoopSourceRef);
|
||||
impl_TCFType!(CFRunLoopSource, CFRunLoopSourceRef, CFRunLoopSourceGetTypeID);
|
||||
|
||||
impl CFRunLoopSource {
|
||||
pub fn from_file_descriptor(fd: &CFFileDescriptor, order: CFIndex) -> Option<CFRunLoopSource> {
|
||||
fd.to_run_loop_source(order)
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef);
|
||||
impl_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef, CFRunLoopObserverGetTypeID);
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use date::{CFDate, CFAbsoluteTime};
|
||||
use std::mem;
|
||||
use libc::c_void;
|
||||
use std::sync::mpsc;
|
||||
|
||||
#[test]
|
||||
fn wait_200_milliseconds() {
|
||||
let run_loop = CFRunLoop::get_current();
|
||||
|
||||
let now = CFDate::now().abs_time();
|
||||
let (elapsed_tx, elapsed_rx) = mpsc::channel();
|
||||
let mut info = Info {
|
||||
start_time: now,
|
||||
elapsed_tx,
|
||||
};
|
||||
let mut context = unsafe { CFRunLoopTimerContext {
|
||||
version: 0,
|
||||
info: &mut info as *mut _ as *mut c_void,
|
||||
retain: mem::zeroed(),
|
||||
release: mem::zeroed(),
|
||||
copyDescription: mem::zeroed(),
|
||||
} };
|
||||
|
||||
|
||||
let run_loop_timer = CFRunLoopTimer::new(now + 0.20f64, 0f64, 0, 0, timer_popped, &mut context);
|
||||
unsafe {
|
||||
run_loop.add_timer(&run_loop_timer, kCFRunLoopDefaultMode);
|
||||
}
|
||||
CFRunLoop::run_current();
|
||||
let elapsed = elapsed_rx.try_recv().unwrap();
|
||||
println!("wait_200_milliseconds, elapsed: {}", elapsed);
|
||||
assert!(elapsed > 0.19 && elapsed < 0.30);
|
||||
}
|
||||
|
||||
struct Info {
|
||||
start_time: CFAbsoluteTime,
|
||||
elapsed_tx: mpsc::Sender<f64>,
|
||||
}
|
||||
|
||||
extern "C" fn timer_popped(_timer: CFRunLoopTimerRef, raw_info: *mut c_void) {
|
||||
let info: *mut Info = unsafe { mem::transmute(raw_info) };
|
||||
let now = CFDate::now().abs_time();
|
||||
let elapsed = now - unsafe { (*info).start_time };
|
||||
let _ = unsafe { (*info).elapsed_tx.send(elapsed) };
|
||||
CFRunLoop::get_current().stop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! An immutable bag of elements.
|
||||
|
||||
pub use core_foundation_sys::set::*;
|
||||
use core_foundation_sys::base::{CFTypeRef, kCFAllocatorDefault};
|
||||
|
||||
use base::{CFIndexConvertible, TCFType};
|
||||
|
||||
use std::mem;
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// An immutable bag of elements.
|
||||
CFSet, CFSetRef
|
||||
}
|
||||
impl_TCFType!(CFSet, CFSetRef, CFSetGetTypeID);
|
||||
impl_CFTypeDescription!(CFSet);
|
||||
|
||||
impl CFSet {
|
||||
/// Creates a new set from a list of `CFType` instances.
|
||||
pub fn from_slice<T>(elems: &[T]) -> CFSet where T: TCFType {
|
||||
unsafe {
|
||||
let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
|
||||
let set_ref = CFSetCreate(kCFAllocatorDefault,
|
||||
mem::transmute(elems.as_ptr()),
|
||||
elems.len().to_CFIndex(),
|
||||
&kCFTypeSetCallBacks);
|
||||
TCFType::wrap_under_create_rule(set_ref)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Immutable strings.
|
||||
|
||||
pub use core_foundation_sys::string::*;
|
||||
|
||||
use base::{CFIndexConvertible, TCFType};
|
||||
|
||||
use core_foundation_sys::base::{Boolean, CFIndex, CFRange};
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, kCFAllocatorNull};
|
||||
use std::fmt;
|
||||
use std::str::{self, FromStr};
|
||||
use std::ptr;
|
||||
use std::ffi::CStr;
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// An immutable string in one of a variety of encodings.
|
||||
CFString, CFStringRef
|
||||
}
|
||||
impl_TCFType!(CFString, CFStringRef, CFStringGetTypeID);
|
||||
|
||||
impl FromStr for CFString {
|
||||
type Err = ();
|
||||
|
||||
/// See also CFString::new for a variant of this which does not return a Result
|
||||
#[inline]
|
||||
fn from_str(string: &str) -> Result<CFString, ()> {
|
||||
Ok(CFString::new(string))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for CFString {
|
||||
#[inline]
|
||||
fn from(string: &'a str) -> CFString {
|
||||
CFString::new(string)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CFString {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
unsafe {
|
||||
// Do this without allocating if we can get away with it
|
||||
let c_string = CFStringGetCStringPtr(self.0, kCFStringEncodingUTF8);
|
||||
if c_string != ptr::null() {
|
||||
let c_str = CStr::from_ptr(c_string);
|
||||
fmt.write_str(str::from_utf8_unchecked(c_str.to_bytes()))
|
||||
} else {
|
||||
let char_len = self.char_len();
|
||||
|
||||
// First, ask how big the buffer ought to be.
|
||||
let mut bytes_required: CFIndex = 0;
|
||||
CFStringGetBytes(self.0,
|
||||
CFRange { location: 0, length: char_len },
|
||||
kCFStringEncodingUTF8,
|
||||
0,
|
||||
false as Boolean,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
&mut bytes_required);
|
||||
|
||||
// Then, allocate the buffer and actually copy.
|
||||
let mut buffer = vec![b'\x00'; bytes_required as usize];
|
||||
|
||||
let mut bytes_used: CFIndex = 0;
|
||||
let chars_written = CFStringGetBytes(self.0,
|
||||
CFRange { location: 0, length: char_len },
|
||||
kCFStringEncodingUTF8,
|
||||
0,
|
||||
false as Boolean,
|
||||
buffer.as_mut_ptr(),
|
||||
buffer.len().to_CFIndex(),
|
||||
&mut bytes_used) as usize;
|
||||
assert!(chars_written.to_CFIndex() == char_len);
|
||||
|
||||
// This is dangerous; we over-allocate and null-terminate the string (during
|
||||
// initialization).
|
||||
assert!(bytes_used == buffer.len().to_CFIndex());
|
||||
fmt.write_str(str::from_utf8_unchecked(&buffer))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CFString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "\"{}\"", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl CFString {
|
||||
/// Creates a new `CFString` instance from a Rust string.
|
||||
#[inline]
|
||||
pub fn new(string: &str) -> CFString {
|
||||
unsafe {
|
||||
let string_ref = CFStringCreateWithBytes(kCFAllocatorDefault,
|
||||
string.as_ptr(),
|
||||
string.len().to_CFIndex(),
|
||||
kCFStringEncodingUTF8,
|
||||
false as Boolean);
|
||||
CFString::wrap_under_create_rule(string_ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `CFString::new`, but references a string that can be used as a backing store
|
||||
/// by virtue of being statically allocated.
|
||||
#[inline]
|
||||
pub fn from_static_string(string: &'static str) -> CFString {
|
||||
unsafe {
|
||||
let string_ref = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
|
||||
string.as_ptr(),
|
||||
string.len().to_CFIndex(),
|
||||
kCFStringEncodingUTF8,
|
||||
false as Boolean,
|
||||
kCFAllocatorNull);
|
||||
TCFType::wrap_under_create_rule(string_ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of characters in the string.
|
||||
#[inline]
|
||||
pub fn char_len(&self) -> CFIndex {
|
||||
unsafe {
|
||||
CFStringGetLength(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_and_back() {
|
||||
let original = "The quick brown fox jumped over the slow lazy dog.";
|
||||
let cfstr = CFString::from_static_string(original);
|
||||
let converted = cfstr.to_string();
|
||||
assert!(converted == original);
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Core Foundation time zone objects.
|
||||
|
||||
pub use core_foundation_sys::timezone::*;
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
|
||||
use base::TCFType;
|
||||
use date::{CFDate, CFTimeInterval};
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
use chrono::{FixedOffset, NaiveDateTime};
|
||||
|
||||
|
||||
declare_TCFType!{
|
||||
/// A time zone.
|
||||
CFTimeZone, CFTimeZoneRef
|
||||
}
|
||||
impl_TCFType!(CFTimeZone, CFTimeZoneRef, CFTimeZoneGetTypeID);
|
||||
impl_CFTypeDescription!(CFTimeZone);
|
||||
|
||||
impl Default for CFTimeZone {
|
||||
fn default() -> CFTimeZone {
|
||||
unsafe {
|
||||
let tz_ref = CFTimeZoneCopyDefault();
|
||||
TCFType::wrap_under_create_rule(tz_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CFTimeZone {
|
||||
#[inline]
|
||||
pub fn new(interval: CFTimeInterval) -> CFTimeZone {
|
||||
unsafe {
|
||||
let tz_ref = CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, interval);
|
||||
TCFType::wrap_under_create_rule(tz_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn system() -> CFTimeZone {
|
||||
unsafe {
|
||||
let tz_ref = CFTimeZoneCopySystem();
|
||||
TCFType::wrap_under_create_rule(tz_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn seconds_from_gmt(&self, date: CFDate) -> CFTimeInterval {
|
||||
unsafe {
|
||||
CFTimeZoneGetSecondsFromGMT(self.0, date.abs_time())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub fn offset_at_date(&self, date: NaiveDateTime) -> FixedOffset {
|
||||
let date = CFDate::from_naive_utc(date);
|
||||
FixedOffset::east(self.seconds_from_gmt(date) as i32)
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub fn from_offset(offset: FixedOffset) -> CFTimeZone {
|
||||
CFTimeZone::new(offset.local_minus_utc() as f64)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::CFTimeZone;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
use chrono::{NaiveDateTime, FixedOffset};
|
||||
|
||||
#[test]
|
||||
fn timezone_comparison() {
|
||||
let system = CFTimeZone::system();
|
||||
let default = CFTimeZone::default();
|
||||
assert_eq!(system, default);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-chrono")]
|
||||
fn timezone_chrono_conversion() {
|
||||
let offset = FixedOffset::west(28800);
|
||||
let tz = CFTimeZone::from_offset(offset);
|
||||
let converted = tz.offset_at_date(NaiveDateTime::from_timestamp(0, 0));
|
||||
assert_eq!(offset, converted);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! A URL type for Core Foundation.
|
||||
|
||||
pub use core_foundation_sys::url::*;
|
||||
|
||||
use base::{TCFType, CFIndex};
|
||||
use string::{CFString};
|
||||
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, Boolean};
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::mem;
|
||||
|
||||
use libc::{strlen, PATH_MAX};
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
#[cfg(unix)]
|
||||
use std::ffi::OsStr;
|
||||
|
||||
|
||||
declare_TCFType!(CFURL, CFURLRef);
|
||||
impl_TCFType!(CFURL, CFURLRef, CFURLGetTypeID);
|
||||
|
||||
impl fmt::Debug for CFURL {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
unsafe {
|
||||
let string: CFString = TCFType::wrap_under_get_rule(CFURLGetString(self.0));
|
||||
write!(f, "{}", string.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CFURL {
|
||||
pub fn from_path<P: AsRef<Path>>(path: P, isDirectory: bool) -> Option<CFURL> {
|
||||
let path_bytes;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
path_bytes = path.as_ref().as_os_str().as_bytes()
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
// XXX: Getting non-valid UTF8 paths into CoreFoundation on Windows is going to be unpleasant
|
||||
// CFURLGetWideFileSystemRepresentation might help
|
||||
path_bytes = match path.as_ref().to_str() {
|
||||
Some(path) => path,
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let url_ref = CFURLCreateFromFileSystemRepresentation(ptr::null_mut(), path_bytes.as_ptr(), path_bytes.len() as CFIndex, isDirectory as u8);
|
||||
if url_ref.is_null() {
|
||||
return None;
|
||||
}
|
||||
Some(TCFType::wrap_under_create_rule(url_ref))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_file_system_path(filePath: CFString, pathStyle: CFURLPathStyle, isDirectory: bool) -> CFURL {
|
||||
unsafe {
|
||||
let url_ref = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath.as_concrete_TypeRef(), pathStyle, isDirectory as u8);
|
||||
TCFType::wrap_under_create_rule(url_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn to_path(&self) -> Option<PathBuf> {
|
||||
// implementing this on Windows is more complicated because of the different OsStr representation
|
||||
unsafe {
|
||||
let mut buf: [u8; PATH_MAX as usize] = mem::uninitialized();
|
||||
let result = CFURLGetFileSystemRepresentation(self.0, true as Boolean, buf.as_mut_ptr(), buf.len() as CFIndex);
|
||||
if result == false as Boolean {
|
||||
return None;
|
||||
}
|
||||
let len = strlen(buf.as_ptr() as *const i8);
|
||||
let path = OsStr::from_bytes(&buf[0..len]);
|
||||
Some(PathBuf::from(path))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_string(&self) -> CFString {
|
||||
unsafe {
|
||||
TCFType::wrap_under_get_rule(CFURLGetString(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_file_system_path(&self, pathStyle: CFURLPathStyle) -> CFString {
|
||||
unsafe {
|
||||
TCFType::wrap_under_create_rule(CFURLCopyFileSystemPath(self.as_concrete_TypeRef(), pathStyle))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn absolute(&self) -> CFURL {
|
||||
unsafe {
|
||||
TCFType::wrap_under_create_rule(CFURLCopyAbsoluteURL(self.as_concrete_TypeRef()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_url_from_path() {
|
||||
let path = "/usr/local/foo/";
|
||||
let cfstr_path = CFString::from_static_string(path);
|
||||
let cfurl = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
assert_eq!(cfurl.get_string().to_string(), "file:///usr/local/foo/");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn non_utf8() {
|
||||
use std::ffi::OsStr;
|
||||
let path = Path::new(OsStr::from_bytes(b"/\xC0/blame"));
|
||||
let cfurl = CFURL::from_path(path, false).unwrap();
|
||||
assert_eq!(cfurl.to_path().unwrap(), path);
|
||||
let len = unsafe { CFURLGetBytes(cfurl.as_concrete_TypeRef(), ptr::null_mut(), 0) };
|
||||
assert_eq!(len, 17);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn absolute_file_url() {
|
||||
use core_foundation_sys::url::CFURLCreateWithFileSystemPathRelativeToBase;
|
||||
use std::path::PathBuf;
|
||||
|
||||
let path = "/usr/local/foo";
|
||||
let file = "bar";
|
||||
|
||||
let cfstr_path = CFString::from_static_string(path);
|
||||
let cfstr_file = CFString::from_static_string(file);
|
||||
let cfurl_base = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
let cfurl_relative: CFURL = unsafe {
|
||||
let url_ref = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault,
|
||||
cfstr_file.as_concrete_TypeRef(),
|
||||
kCFURLPOSIXPathStyle,
|
||||
false as u8,
|
||||
cfurl_base.as_concrete_TypeRef());
|
||||
TCFType::wrap_under_create_rule(url_ref)
|
||||
};
|
||||
|
||||
let mut absolute_path = PathBuf::from(path);
|
||||
absolute_path.push(file);
|
||||
|
||||
assert_eq!(cfurl_relative.get_file_system_path(kCFURLPOSIXPathStyle).to_string(), file);
|
||||
assert_eq!(cfurl_relative.absolute().get_file_system_path(kCFURLPOSIXPathStyle).to_string(),
|
||||
absolute_path.to_str().unwrap());
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Core Foundation UUID objects.
|
||||
|
||||
#[cfg(feature = "with-uuid")]
|
||||
extern crate uuid;
|
||||
|
||||
pub use core_foundation_sys::uuid::*;
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
|
||||
use base::TCFType;
|
||||
|
||||
#[cfg(feature = "with-uuid")]
|
||||
use self::uuid::Uuid;
|
||||
|
||||
|
||||
declare_TCFType! {
|
||||
/// A UUID.
|
||||
CFUUID, CFUUIDRef
|
||||
}
|
||||
impl_TCFType!(CFUUID, CFUUIDRef, CFUUIDGetTypeID);
|
||||
impl_CFTypeDescription!(CFUUID);
|
||||
|
||||
impl CFUUID {
|
||||
#[inline]
|
||||
pub fn new() -> CFUUID {
|
||||
unsafe {
|
||||
let uuid_ref = CFUUIDCreate(kCFAllocatorDefault);
|
||||
TCFType::wrap_under_create_rule(uuid_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-uuid")]
|
||||
impl Into<Uuid> for CFUUID {
|
||||
fn into(self) -> Uuid {
|
||||
let b = unsafe {
|
||||
CFUUIDGetUUIDBytes(self.0)
|
||||
};
|
||||
let bytes = [
|
||||
b.byte0,
|
||||
b.byte1,
|
||||
b.byte2,
|
||||
b.byte3,
|
||||
b.byte4,
|
||||
b.byte5,
|
||||
b.byte6,
|
||||
b.byte7,
|
||||
b.byte8,
|
||||
b.byte9,
|
||||
b.byte10,
|
||||
b.byte11,
|
||||
b.byte12,
|
||||
b.byte13,
|
||||
b.byte14,
|
||||
b.byte15,
|
||||
];
|
||||
Uuid::from_bytes(&bytes).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-uuid")]
|
||||
impl From<Uuid> for CFUUID {
|
||||
fn from(uuid: Uuid) -> CFUUID {
|
||||
let b = uuid.as_bytes();
|
||||
let bytes = CFUUIDBytes {
|
||||
byte0: b[0],
|
||||
byte1: b[1],
|
||||
byte2: b[2],
|
||||
byte3: b[3],
|
||||
byte4: b[4],
|
||||
byte5: b[5],
|
||||
byte6: b[6],
|
||||
byte7: b[7],
|
||||
byte8: b[8],
|
||||
byte9: b[9],
|
||||
byte10: b[10],
|
||||
byte11: b[11],
|
||||
byte12: b[12],
|
||||
byte13: b[13],
|
||||
byte14: b[14],
|
||||
byte15: b[15],
|
||||
};
|
||||
unsafe {
|
||||
let uuid_ref = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, bytes);
|
||||
TCFType::wrap_under_create_rule(uuid_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "with-uuid")]
|
||||
mod test {
|
||||
use super::CFUUID;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[test]
|
||||
fn uuid_conversion() {
|
||||
let cf_uuid = CFUUID::new();
|
||||
let uuid: Uuid = cf_uuid.clone().into();
|
||||
let converted = CFUUID::from(uuid);
|
||||
assert!(cf_uuid == converted);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#[macro_use]
|
||||
extern crate core_foundation;
|
||||
extern crate libc;
|
||||
|
||||
use core_foundation::base::{CFComparisonResult, TCFType};
|
||||
use libc::c_void;
|
||||
|
||||
// sys equivalent stuff that must be declared
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFFooBar(c_void);
|
||||
|
||||
pub type CFFooBarRef = *const __CFFooBar;
|
||||
|
||||
extern "C" {
|
||||
pub fn CFFooBarGetTypeID() -> core_foundation::base::CFTypeID;
|
||||
pub fn fake_compare(
|
||||
this: CFFooBarRef,
|
||||
other: CFFooBarRef,
|
||||
context: *mut c_void,
|
||||
) -> CFComparisonResult;
|
||||
}
|
||||
|
||||
// Try to use the macros outside of the crate
|
||||
|
||||
declare_TCFType!(CFFooBar, CFFooBarRef);
|
||||
impl_TCFType!(CFFooBar, CFFooBarRef, CFFooBarGetTypeID);
|
||||
impl_CFTypeDescription!(CFFooBar);
|
||||
impl_CFComparison!(CFFooBar, fake_compare);
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"08b77adecca4222d97b0fb359b1c9ce97983e0e0914a4418834c032395af76ea","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","build.rs":"9433ed3b20cc99e716dda4c6d8507c29bc04882544cbbea8d4e48ba80fd0fa12","src/array.rs":"c70be1c0485612ac327a4fc9ca87098034e13df80dead23167560a38471fb823","src/base.rs":"37ad5b765d9e70f043f70a26da65cc46f0af5f1361e431e6f8591a143a31da31","src/bundle.rs":"b4e0e9b7ca2e35e3dc9bee316690538a5d17a470f8173f6b80c6816c847d12ec","src/data.rs":"21e968951fe56e080d33474f4438de2dfb7e0c8af426a6dfb100efdd6c530eec","src/date.rs":"90f29b07d3bd1549a3ab64adaaf153aff5ba546c1cd449f7248479d26bce9687","src/dictionary.rs":"37d881fbcf3232f90ab8648084b0f26b45ffee882b95e76831ac206f3e35f7de","src/error.rs":"61bc31a401ec6c8495668175eade9284e257da056fc666af74a5555af5daf33f","src/filedescriptor.rs":"14800c805b66f1fd6f995a6e73138d65a724163acb8a3f8f2539c807d333473d","src/lib.rs":"1038a1292f6f6c790ae055242015b8e3b91c2cccce34bfba240403399149f64c","src/messageport.rs":"f22b8552ff8b8e1edf25fe322eeabd9d7e5472b11514b95bc936387e4fa51b2a","src/number.rs":"4e69c688f24a1226fb40faec7d18861b5a617afcedbb352331c45a8e4eff292a","src/propertylist.rs":"cc2b27f8f8ebc80c03871b7b1ad50ee348539b016078ce721c86b8cd5f9d75bd","src/runloop.rs":"1d4aba9425669ef32450396c31655a90daf0e67d579e4617465fb7abe23c047f","src/set.rs":"22055b5ce6a2ce37847ee955f5e6e517348a351770d335373704776bc5412b9f","src/string.rs":"0e9373c6e48c97d7cbdb2ceaa07bc0af4e5d25ab0f91b138b4f8667cff337f4e","src/timezone.rs":"6711924b967d96ba88be4976cf17dfd3f9573033115da8e61ad07e8b0f26cdb7","src/url.rs":"b85110fe203c685719ba92517ff3c09ce0fe358e15380ecc0bd18356ac3573ed","src/uuid.rs":"e591e0bac875832acc15ea7ee0c9bff296543f4f77470101de0602ee69c2e527"},"package":"716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"}
|
|
@ -0,0 +1,27 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.5.1"
|
||||
authors = ["The Servo Project Developers"]
|
||||
build = "build.rs"
|
||||
description = "Bindings to Core Foundation for OS X"
|
||||
homepage = "https://github.com/servo/core-foundation-rs"
|
||||
license = "MIT / Apache-2.0"
|
||||
repository = "https://github.com/servo/core-foundation-rs"
|
||||
[dependencies.libc]
|
||||
version = "0.2"
|
||||
|
||||
[features]
|
||||
mac_os_10_7_support = []
|
||||
mac_os_10_8_features = []
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2012-2013 Mozilla Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
if std::env::var("TARGET").unwrap().contains("-apple") {
|
||||
println!("cargo:rustc-link-lib=framework=CoreFoundation");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFRange, CFIndex, CFAllocatorRef, CFTypeID, Boolean};
|
||||
use string::CFStringRef;
|
||||
|
||||
pub type CFArrayRetainCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void;
|
||||
pub type CFArrayReleaseCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void);
|
||||
pub type CFArrayCopyDescriptionCallBack = extern "C" fn(value: *const c_void) -> CFStringRef;
|
||||
pub type CFArrayEqualCallBack = extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CFArrayCallBacks {
|
||||
pub version: CFIndex,
|
||||
pub retain: CFArrayRetainCallBack,
|
||||
pub release: CFArrayReleaseCallBack,
|
||||
pub copyDescription: CFArrayCopyDescriptionCallBack,
|
||||
pub equal: CFArrayEqualCallBack,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFArray(c_void);
|
||||
|
||||
pub type CFArrayRef = *const __CFArray;
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFArray.h
|
||||
*/
|
||||
pub static kCFTypeArrayCallBacks: CFArrayCallBacks;
|
||||
|
||||
pub fn CFArrayCreate(allocator: CFAllocatorRef, values: *const *const c_void,
|
||||
numValues: CFIndex, callBacks: *const CFArrayCallBacks) -> CFArrayRef;
|
||||
pub fn CFArrayCreateCopy(allocator: CFAllocatorRef , theArray: CFArrayRef) -> CFArrayRef;
|
||||
|
||||
// CFArrayBSearchValues
|
||||
// CFArrayContainsValue
|
||||
pub fn CFArrayGetCount(theArray: CFArrayRef) -> CFIndex;
|
||||
// CFArrayGetCountOfValue
|
||||
// CFArrayGetFirstIndexOfValue
|
||||
// CFArrayGetLastIndexOfValue
|
||||
pub fn CFArrayGetValues(theArray: CFArrayRef, range: CFRange, values: *mut *const c_void);
|
||||
pub fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *const c_void;
|
||||
// CFArrayApplyFunction
|
||||
pub fn CFArrayGetTypeID() -> CFTypeID;
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use libc::{c_uint, c_long, c_ulong, c_void, c_int};
|
||||
use string::CFStringRef;
|
||||
|
||||
pub type Boolean = u8;
|
||||
pub type CFIndex = c_long;
|
||||
pub type mach_port_t = c_uint;
|
||||
pub type CFAllocatorRef = *const c_void;
|
||||
pub type CFNullRef = *const c_void;
|
||||
pub type CFHashCode = c_ulong;
|
||||
pub type CFTypeID = c_ulong;
|
||||
pub type CFTypeRef = *const c_void;
|
||||
pub type CFOptionFlags = u32;
|
||||
pub type OSStatus = i32;
|
||||
pub type SInt32 = c_int;
|
||||
|
||||
#[repr(i64)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum CFComparisonResult {
|
||||
LessThan = -1,
|
||||
EqualTo = 0,
|
||||
GreaterThan = 1,
|
||||
}
|
||||
|
||||
impl Into<Ordering> for CFComparisonResult {
|
||||
fn into(self) -> Ordering {
|
||||
match self {
|
||||
CFComparisonResult::LessThan => Ordering::Less,
|
||||
CFComparisonResult::EqualTo => Ordering::Equal,
|
||||
CFComparisonResult::GreaterThan => Ordering::Greater
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CFRange {
|
||||
pub location: CFIndex,
|
||||
pub length: CFIndex
|
||||
}
|
||||
|
||||
// for back-compat
|
||||
impl CFRange {
|
||||
pub fn init(location: CFIndex, length: CFIndex) -> CFRange {
|
||||
CFRange {
|
||||
location: location,
|
||||
length: length,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type CFAllocatorRetainCallBack = extern "C" fn(info: *mut c_void) -> *mut c_void;
|
||||
pub type CFAllocatorReleaseCallBack = extern "C" fn(info: *mut c_void);
|
||||
pub type CFAllocatorCopyDescriptionCallBack = extern "C" fn(info: *mut c_void) -> CFStringRef;
|
||||
pub type CFAllocatorAllocateCallBack = extern "C" fn(allocSize: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> *mut c_void;
|
||||
pub type CFAllocatorReallocateCallBack = extern "C" fn(ptr: *mut c_void, newsize: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> *mut c_void;
|
||||
pub type CFAllocatorDeallocateCallBack = extern "C" fn(ptr: *mut c_void, info: *mut c_void);
|
||||
pub type CFAllocatorPreferredSizeCallBack = extern "C" fn(size: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> CFIndex;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CFAllocatorContext {
|
||||
pub version: CFIndex,
|
||||
pub info: *mut c_void,
|
||||
pub retain: CFAllocatorRetainCallBack,
|
||||
pub release: CFAllocatorReleaseCallBack,
|
||||
pub copyDescription: CFAllocatorCopyDescriptionCallBack,
|
||||
pub allocate: CFAllocatorAllocateCallBack,
|
||||
pub reallocate: CFAllocatorReallocateCallBack,
|
||||
pub deallocate: CFAllocatorDeallocateCallBack,
|
||||
pub preferredSize: CFAllocatorPreferredSizeCallBack
|
||||
}
|
||||
|
||||
/// Trait for all types which are Core Foundation reference types.
|
||||
pub trait TCFTypeRef {
|
||||
fn as_void_ptr(&self) -> *const c_void;
|
||||
|
||||
unsafe fn from_void_ptr(ptr: *const c_void) -> Self;
|
||||
}
|
||||
|
||||
impl<T> TCFTypeRef for *const T {
|
||||
fn as_void_ptr(&self) -> *const c_void {
|
||||
(*self) as *const c_void
|
||||
}
|
||||
|
||||
unsafe fn from_void_ptr(ptr: *const c_void) -> Self {
|
||||
ptr as *const T
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> TCFTypeRef for *mut T {
|
||||
fn as_void_ptr(&self) -> *const c_void {
|
||||
(*self) as *const T as *const c_void
|
||||
}
|
||||
|
||||
unsafe fn from_void_ptr(ptr: *const c_void) -> Self {
|
||||
ptr as *const T as *mut T
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFBase.h
|
||||
*/
|
||||
|
||||
/* CFAllocator Reference */
|
||||
|
||||
pub static kCFAllocatorDefault: CFAllocatorRef;
|
||||
pub static kCFAllocatorSystemDefault: CFAllocatorRef;
|
||||
pub static kCFAllocatorMalloc: CFAllocatorRef;
|
||||
pub static kCFAllocatorMallocZone: CFAllocatorRef;
|
||||
pub static kCFAllocatorNull: CFAllocatorRef;
|
||||
pub static kCFAllocatorUseContext: CFAllocatorRef;
|
||||
|
||||
pub fn CFAllocatorCreate(allocator: CFAllocatorRef, context: *mut CFAllocatorContext) -> CFAllocatorRef;
|
||||
pub fn CFAllocatorAllocate(allocator: CFAllocatorRef, size: CFIndex, hint: CFOptionFlags) -> *mut c_void;
|
||||
pub fn CFAllocatorDeallocate(allocator: CFAllocatorRef, ptr: *mut c_void);
|
||||
pub fn CFAllocatorGetPreferredSizeForSize(allocator: CFAllocatorRef, size: CFIndex, hint: CFOptionFlags) -> CFIndex;
|
||||
pub fn CFAllocatorReallocate(allocator: CFAllocatorRef, ptr: *mut c_void, newsize: CFIndex, hint: CFOptionFlags) -> *mut c_void;
|
||||
pub fn CFAllocatorGetDefault() -> CFAllocatorRef;
|
||||
pub fn CFAllocatorSetDefault(allocator: CFAllocatorRef);
|
||||
pub fn CFAllocatorGetContext(allocator: CFAllocatorRef, context: *mut CFAllocatorContext);
|
||||
pub fn CFAllocatorGetTypeID() -> CFTypeID;
|
||||
|
||||
/* CFNull Reference */
|
||||
|
||||
pub static kCFNull: CFNullRef;
|
||||
|
||||
/* CFType Reference */
|
||||
|
||||
//fn CFCopyTypeIDDescription
|
||||
//fn CFGetAllocator
|
||||
pub fn CFCopyDescription(cf: CFTypeRef) -> CFStringRef;
|
||||
pub fn CFEqual(cf1: CFTypeRef, cf2: CFTypeRef) -> Boolean;
|
||||
pub fn CFGetRetainCount(cf: CFTypeRef) -> CFIndex;
|
||||
pub fn CFGetTypeID(cf: CFTypeRef) -> CFTypeID;
|
||||
pub fn CFHash(cf: CFTypeRef) -> CFHashCode;
|
||||
//fn CFMakeCollectable
|
||||
pub fn CFRelease(cf: CFTypeRef);
|
||||
pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
|
||||
pub fn CFShow(obj: CFTypeRef);
|
||||
|
||||
/* Base Utilities Reference */
|
||||
// N.B. Some things missing here.
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFTypeID, CFAllocatorRef};
|
||||
use url::CFURLRef;
|
||||
use dictionary::CFDictionaryRef;
|
||||
use string::CFStringRef;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFBundle(c_void);
|
||||
|
||||
pub type CFBundleRef = *mut __CFBundle;
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFBundle.h
|
||||
*/
|
||||
pub fn CFBundleCreate(allocator: CFAllocatorRef, bundleURL: CFURLRef) -> CFBundleRef;
|
||||
|
||||
pub fn CFBundleGetBundleWithIdentifier(bundleID: CFStringRef) -> CFBundleRef;
|
||||
pub fn CFBundleGetFunctionPointerForName(bundle: CFBundleRef, function_name: CFStringRef) -> *const c_void;
|
||||
pub fn CFBundleGetMainBundle() -> CFBundleRef;
|
||||
pub fn CFBundleGetInfoDictionary(bundle: CFBundleRef) -> CFDictionaryRef;
|
||||
|
||||
pub fn CFBundleGetTypeID() -> CFTypeID;
|
||||
pub fn CFBundleCopyExecutableURL(bundle: CFBundleRef) -> CFURLRef;
|
||||
pub fn CFBundleCopyPrivateFrameworksURL(bundle: CFBundleRef) -> CFURLRef;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
use libc::c_void;
|
||||
|
||||
use base::{CFAllocatorRef, CFTypeID, CFIndex};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFData(c_void);
|
||||
|
||||
pub type CFDataRef = *const __CFData;
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFData.h
|
||||
*/
|
||||
|
||||
pub fn CFDataCreate(allocator: CFAllocatorRef,
|
||||
bytes: *const u8, length: CFIndex) -> CFDataRef;
|
||||
//fn CFDataFind
|
||||
pub fn CFDataGetBytePtr(theData: CFDataRef) -> *const u8;
|
||||
pub fn CFDataGetLength(theData: CFDataRef) -> CFIndex;
|
||||
|
||||
pub fn CFDataGetTypeID() -> CFTypeID;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFAllocatorRef, CFComparisonResult, CFTypeID};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFDate(c_void);
|
||||
|
||||
pub type CFDateRef = *const __CFDate;
|
||||
|
||||
pub type CFTimeInterval = f64;
|
||||
pub type CFAbsoluteTime = CFTimeInterval;
|
||||
|
||||
extern {
|
||||
pub static kCFAbsoluteTimeIntervalSince1904: CFTimeInterval;
|
||||
pub static kCFAbsoluteTimeIntervalSince1970: CFTimeInterval;
|
||||
|
||||
pub fn CFAbsoluteTimeGetCurrent() -> CFAbsoluteTime;
|
||||
|
||||
pub fn CFDateCreate(allocator: CFAllocatorRef, at: CFAbsoluteTime) -> CFDateRef;
|
||||
pub fn CFDateGetAbsoluteTime(date: CFDateRef) -> CFAbsoluteTime;
|
||||
pub fn CFDateGetTimeIntervalSinceDate(date: CFDateRef, other: CFDateRef) -> CFTimeInterval;
|
||||
pub fn CFDateCompare(date: CFDateRef, other: CFDateRef, context: *mut c_void) -> CFComparisonResult;
|
||||
|
||||
pub fn CFDateGetTypeID() -> CFTypeID;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::{c_void};
|
||||
|
||||
use base::{CFAllocatorRef, CFHashCode, CFIndex, CFTypeID, Boolean};
|
||||
use string::CFStringRef;
|
||||
|
||||
pub type CFDictionaryApplierFunction = extern "C" fn(key: *const c_void, value: *const c_void, context: *mut c_void);
|
||||
|
||||
pub type CFDictionaryRetainCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void;
|
||||
pub type CFDictionaryReleaseCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void);
|
||||
pub type CFDictionaryCopyDescriptionCallBack = extern "C" fn(value: *const c_void) -> CFStringRef;
|
||||
pub type CFDictionaryEqualCallBack = extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean;
|
||||
pub type CFDictionaryHashCallBack = extern "C" fn(value: *const c_void) -> CFHashCode;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CFDictionaryKeyCallBacks {
|
||||
pub version: CFIndex,
|
||||
pub retain: CFDictionaryRetainCallBack,
|
||||
pub release: CFDictionaryReleaseCallBack,
|
||||
pub copyDescription: CFDictionaryCopyDescriptionCallBack,
|
||||
pub equal: CFDictionaryEqualCallBack,
|
||||
pub hash: CFDictionaryHashCallBack
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CFDictionaryValueCallBacks {
|
||||
pub version: CFIndex,
|
||||
pub retain: CFDictionaryRetainCallBack,
|
||||
pub release: CFDictionaryReleaseCallBack,
|
||||
pub copyDescription: CFDictionaryCopyDescriptionCallBack,
|
||||
pub equal: CFDictionaryEqualCallBack
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFDictionary(c_void);
|
||||
|
||||
pub type CFDictionaryRef = *const __CFDictionary;
|
||||
pub type CFMutableDictionaryRef = *mut __CFDictionary;
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFDictionary.h
|
||||
*/
|
||||
|
||||
pub static kCFTypeDictionaryKeyCallBacks: CFDictionaryKeyCallBacks;
|
||||
pub static kCFTypeDictionaryValueCallBacks: CFDictionaryValueCallBacks;
|
||||
|
||||
pub fn CFDictionaryContainsKey(theDict: CFDictionaryRef, key: *const c_void) -> Boolean;
|
||||
pub fn CFDictionaryCreate(allocator: CFAllocatorRef, keys: *const *const c_void, values: *const *const c_void,
|
||||
numValues: CFIndex, keyCallBacks: *const CFDictionaryKeyCallBacks,
|
||||
valueCallBacks: *const CFDictionaryValueCallBacks)
|
||||
-> CFDictionaryRef;
|
||||
pub fn CFDictionaryGetCount(theDict: CFDictionaryRef) -> CFIndex;
|
||||
pub fn CFDictionaryGetTypeID() -> CFTypeID;
|
||||
pub fn CFDictionaryGetValueIfPresent(theDict: CFDictionaryRef, key: *const c_void, value: *mut *const c_void)
|
||||
-> Boolean;
|
||||
pub fn CFDictionaryApplyFunction(theDict: CFDictionaryRef,
|
||||
applier: CFDictionaryApplierFunction,
|
||||
context: *mut c_void);
|
||||
pub fn CFDictionaryGetKeysAndValues(theDict: CFDictionaryRef,
|
||||
keys: *mut *const c_void,
|
||||
values: *mut *const c_void);
|
||||
|
||||
pub fn CFDictionaryCreateMutable(allocator: CFAllocatorRef, capacity: CFIndex,
|
||||
keyCallbacks: *const CFDictionaryKeyCallBacks,
|
||||
valueCallbacks: *const CFDictionaryValueCallBacks) -> CFMutableDictionaryRef;
|
||||
pub fn CFDictionaryCreateMutableCopy(allocator: CFAllocatorRef, capacity: CFIndex,
|
||||
theDict: CFDictionaryRef) -> CFMutableDictionaryRef;
|
||||
pub fn CFDictionaryAddValue(theDict: CFMutableDictionaryRef,
|
||||
key: *const c_void,
|
||||
value: *const c_void);
|
||||
pub fn CFDictionarySetValue(theDict: CFMutableDictionaryRef,
|
||||
key: *const c_void,
|
||||
value: *const c_void);
|
||||
pub fn CFDictionaryReplaceValue(theDict: CFMutableDictionaryRef,
|
||||
key: *const c_void,
|
||||
value: *const c_void);
|
||||
pub fn CFDictionaryRemoveValue(theDict: CFMutableDictionaryRef,
|
||||
key: *const c_void);
|
||||
pub fn CFDictionaryRemoveAllValues(theDict: CFMutableDictionaryRef);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2016 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFTypeID, CFIndex};
|
||||
use string::CFStringRef;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFError(c_void);
|
||||
|
||||
pub type CFErrorRef = *mut __CFError;
|
||||
|
||||
extern "C" {
|
||||
pub fn CFErrorGetTypeID() -> CFTypeID;
|
||||
|
||||
pub static kCFErrorDomainPOSIX: CFStringRef;
|
||||
pub static kCFErrorDomainOSStatus: CFStringRef;
|
||||
pub static kCFErrorDomainMach: CFStringRef;
|
||||
pub static kCFErrorDomainCocoa: CFStringRef;
|
||||
|
||||
pub fn CFErrorGetDomain(err: CFErrorRef) -> CFStringRef;
|
||||
pub fn CFErrorGetCode(err: CFErrorRef) -> CFIndex;
|
||||
|
||||
pub fn CFErrorCopyDescription(err: CFErrorRef) -> CFStringRef;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
use libc::{c_void, c_int};
|
||||
use base::{Boolean, CFIndex, CFTypeID, CFOptionFlags, CFAllocatorRef};
|
||||
use string::CFStringRef;
|
||||
use runloop::CFRunLoopSourceRef;
|
||||
|
||||
pub type CFFileDescriptorNativeDescriptor = c_int;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFFileDescriptor(c_void);
|
||||
|
||||
pub type CFFileDescriptorRef = *mut __CFFileDescriptor;
|
||||
|
||||
/* Callback Reason Types */
|
||||
pub const kCFFileDescriptorReadCallBack: CFOptionFlags = 1 << 0;
|
||||
pub const kCFFileDescriptorWriteCallBack: CFOptionFlags = 1 << 1;
|
||||
|
||||
pub type CFFileDescriptorCallBack = extern "C" fn (f: CFFileDescriptorRef, callBackTypes: CFOptionFlags, info: *mut c_void);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CFFileDescriptorContext {
|
||||
pub version: CFIndex,
|
||||
pub info: *mut c_void,
|
||||
pub retain: Option<extern "C" fn (info: *const c_void) -> *const c_void>,
|
||||
pub release: Option<extern "C" fn (info: *const c_void)>,
|
||||
pub copyDescription: Option<extern "C" fn (info: *const c_void) -> CFStringRef>,
|
||||
}
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFFileDescriptor.h
|
||||
*/
|
||||
pub fn CFFileDescriptorGetTypeID() -> CFTypeID;
|
||||
|
||||
pub fn CFFileDescriptorCreate(allocator: CFAllocatorRef, fd: CFFileDescriptorNativeDescriptor, closeOnInvalidate: Boolean, callout: CFFileDescriptorCallBack, context: *const CFFileDescriptorContext) -> CFFileDescriptorRef;
|
||||
|
||||
pub fn CFFileDescriptorGetNativeDescriptor(f: CFFileDescriptorRef) -> CFFileDescriptorNativeDescriptor;
|
||||
|
||||
pub fn CFFileDescriptorGetContext(f: CFFileDescriptorRef, context: *mut CFFileDescriptorContext);
|
||||
|
||||
pub fn CFFileDescriptorEnableCallBacks(f: CFFileDescriptorRef, callBackTypes: CFOptionFlags);
|
||||
pub fn CFFileDescriptorDisableCallBacks(f: CFFileDescriptorRef, callBackTypes: CFOptionFlags);
|
||||
|
||||
pub fn CFFileDescriptorInvalidate(f: CFFileDescriptorRef);
|
||||
pub fn CFFileDescriptorIsValid(f: CFFileDescriptorRef) -> Boolean;
|
||||
|
||||
pub fn CFFileDescriptorCreateRunLoopSource(allocator: CFAllocatorRef, f: CFFileDescriptorRef, order: CFIndex) -> CFRunLoopSourceRef;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals, improper_ctypes)]
|
||||
|
||||
#![cfg_attr(all(feature="mac_os_10_7_support", feature="mac_os_10_8_features"), feature(linkage))] // back-compat requires weak linkage
|
||||
|
||||
extern crate libc;
|
||||
|
||||
pub mod array;
|
||||
pub mod base;
|
||||
pub mod bundle;
|
||||
pub mod data;
|
||||
pub mod date;
|
||||
pub mod dictionary;
|
||||
pub mod error;
|
||||
pub mod filedescriptor;
|
||||
pub mod messageport;
|
||||
pub mod number;
|
||||
pub mod propertylist;
|
||||
pub mod runloop;
|
||||
pub mod set;
|
||||
pub mod string;
|
||||
pub mod timezone;
|
||||
pub mod url;
|
||||
pub mod uuid;
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFAllocatorRef, CFIndex, CFTypeID, Boolean};
|
||||
use data::CFDataRef;
|
||||
use date::CFTimeInterval;
|
||||
use runloop::CFRunLoopSourceRef;
|
||||
use string::CFStringRef;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug)]
|
||||
pub struct CFMessagePortContext {
|
||||
pub version: CFIndex,
|
||||
pub info: *mut c_void,
|
||||
pub retain: Option<unsafe extern fn(info: *const c_void) -> *const c_void>,
|
||||
pub release: Option<unsafe extern fn(info: *const c_void)>,
|
||||
pub copyDescription: Option<unsafe extern fn(info: *const c_void)
|
||||
-> CFStringRef>,
|
||||
}
|
||||
|
||||
pub type CFMessagePortCallBack = Option<
|
||||
unsafe extern fn(local: CFMessagePortRef,
|
||||
msgid: i32,
|
||||
data: CFDataRef,
|
||||
info: *mut c_void) -> CFDataRef>;
|
||||
|
||||
pub type CFMessagePortInvalidationCallBack = Option<
|
||||
unsafe extern "C" fn(ms: CFMessagePortRef, info: *mut c_void)>;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFMessagePort(c_void);
|
||||
pub type CFMessagePortRef = *mut __CFMessagePort;
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFMessagePort.h
|
||||
*/
|
||||
pub fn CFMessagePortGetTypeID() -> CFTypeID;
|
||||
pub fn CFMessagePortCreateLocal(allocator: CFAllocatorRef,
|
||||
name: CFStringRef,
|
||||
callout: CFMessagePortCallBack,
|
||||
context: *const CFMessagePortContext,
|
||||
shouldFreeInfo: *mut Boolean)
|
||||
-> CFMessagePortRef;
|
||||
pub fn CFMessagePortCreateRemote(allocator: CFAllocatorRef,
|
||||
name: CFStringRef) -> CFMessagePortRef;
|
||||
pub fn CFMessagePortIsRemote(ms: CFMessagePortRef) -> Boolean;
|
||||
pub fn CFMessagePortGetName(ms: CFMessagePortRef) -> CFStringRef;
|
||||
pub fn CFMessagePortSetName(ms: CFMessagePortRef, newName: CFStringRef)
|
||||
-> Boolean;
|
||||
pub fn CFMessagePortGetContext(ms: CFMessagePortRef,
|
||||
context: *mut CFMessagePortContext);
|
||||
pub fn CFMessagePortInvalidate(ms: CFMessagePortRef);
|
||||
pub fn CFMessagePortIsValid(ms: CFMessagePortRef) -> Boolean;
|
||||
pub fn CFMessagePortGetInvalidationCallBack(ms: CFMessagePortRef)
|
||||
-> CFMessagePortInvalidationCallBack;
|
||||
pub fn CFMessagePortSetInvalidationCallBack(ms: CFMessagePortRef,
|
||||
callout: CFMessagePortInvalidationCallBack);
|
||||
pub fn CFMessagePortSendRequest(remote: CFMessagePortRef, msgid: i32,
|
||||
data: CFDataRef,
|
||||
sendTimeout: CFTimeInterval,
|
||||
rcvTimeout: CFTimeInterval,
|
||||
replyMode: CFStringRef,
|
||||
returnData: *mut CFDataRef) -> i32;
|
||||
pub fn CFMessagePortCreateRunLoopSource(allocator: CFAllocatorRef,
|
||||
local: CFMessagePortRef,
|
||||
order: CFIndex)
|
||||
-> CFRunLoopSourceRef;
|
||||
// CFMessagePortSetDispatchQueue
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFAllocatorRef, CFTypeID, CFComparisonResult};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFBoolean(c_void);
|
||||
|
||||
pub type CFBooleanRef = *const __CFBoolean;
|
||||
|
||||
pub type CFNumberType = u32;
|
||||
|
||||
// members of enum CFNumberType
|
||||
// static kCFNumberSInt8Type: CFNumberType = 1;
|
||||
// static kCFNumberSInt16Type: CFNumberType = 2;
|
||||
pub static kCFNumberSInt32Type: CFNumberType = 3;
|
||||
pub static kCFNumberSInt64Type: CFNumberType = 4;
|
||||
pub static kCFNumberFloat32Type: CFNumberType = 5;
|
||||
pub static kCFNumberFloat64Type: CFNumberType = 6;
|
||||
// static kCFNumberCharType: CFNumberType = 7;
|
||||
// static kCFNumberShortType: CFNumberType = 8;
|
||||
// static kCFNumberIntType: CFNumberType = 9;
|
||||
// static kCFNumberLongType: CFNumberType = 10;
|
||||
// static kCFNumberLongLongType: CFNumberType = 11;
|
||||
// static kCFNumberFloatType: CFNumberType = 12;
|
||||
// static kCFNumberDoubleType: CFNumberType = 13;
|
||||
// static kCFNumberCFIndexType: CFNumberType = 14;
|
||||
// static kCFNumberNSIntegerType: CFNumberType = 15;
|
||||
// static kCFNumberCGFloatType: CFNumberType = 16;
|
||||
// static kCFNumberMaxType: CFNumberType = 16;
|
||||
|
||||
// This is an enum due to zero-sized types warnings.
|
||||
// For more details see https://github.com/rust-lang/rust/issues/27303
|
||||
pub enum __CFNumber {}
|
||||
|
||||
pub type CFNumberRef = *const __CFNumber;
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFNumber.h
|
||||
*/
|
||||
pub static kCFBooleanTrue: CFBooleanRef;
|
||||
pub static kCFBooleanFalse: CFBooleanRef;
|
||||
|
||||
pub fn CFBooleanGetTypeID() -> CFTypeID;
|
||||
pub fn CFNumberCreate(allocator: CFAllocatorRef, theType: CFNumberType, valuePtr: *const c_void)
|
||||
-> CFNumberRef;
|
||||
//fn CFNumberGetByteSize
|
||||
pub fn CFNumberGetValue(number: CFNumberRef, theType: CFNumberType, valuePtr: *mut c_void) -> bool;
|
||||
pub fn CFNumberCompare(date: CFNumberRef, other: CFNumberRef, context: *mut c_void) -> CFComparisonResult;
|
||||
pub fn CFNumberGetTypeID() -> CFTypeID;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
use base::{CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeRef};
|
||||
use data::CFDataRef;
|
||||
use error::CFErrorRef;
|
||||
|
||||
pub type CFPropertyListRef = CFTypeRef;
|
||||
|
||||
pub type CFPropertyListFormat = CFIndex;
|
||||
pub const kCFPropertyListOpenStepFormat: CFPropertyListFormat = 1;
|
||||
pub const kCFPropertyListXMLFormat_v1_0: CFPropertyListFormat = 100;
|
||||
pub const kCFPropertyListBinaryFormat_v1_0: CFPropertyListFormat = 200;
|
||||
|
||||
pub type CFPropertyListMutabilityOptions = CFOptionFlags;
|
||||
pub const kCFPropertyListImmutable: CFPropertyListMutabilityOptions = 0;
|
||||
pub const kCFPropertyListMutableContainers: CFPropertyListMutabilityOptions = 1;
|
||||
pub const kCFPropertyListMutableContainersAndLeaves: CFPropertyListMutabilityOptions = 2;
|
||||
|
||||
extern "C" {
|
||||
// CFPropertyList.h
|
||||
//
|
||||
|
||||
// fn CFPropertyListCreateDeepCopy
|
||||
// fn CFPropertyListIsValid
|
||||
pub fn CFPropertyListCreateWithData(allocator: CFAllocatorRef,
|
||||
data: CFDataRef,
|
||||
options: CFPropertyListMutabilityOptions,
|
||||
format: *mut CFPropertyListFormat,
|
||||
error: *mut CFErrorRef)
|
||||
-> CFPropertyListRef;
|
||||
// fn CFPropertyListCreateWithStream
|
||||
// fn CFPropertyListWrite
|
||||
pub fn CFPropertyListCreateData(allocator: CFAllocatorRef,
|
||||
propertyList: CFPropertyListRef,
|
||||
format: CFPropertyListFormat,
|
||||
options: CFOptionFlags,
|
||||
error: *mut CFErrorRef)
|
||||
-> CFDataRef;
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use array::CFArrayRef;
|
||||
use base::{Boolean, CFIndex, CFTypeID, CFAllocatorRef, CFOptionFlags, CFHashCode, mach_port_t};
|
||||
use date::{CFAbsoluteTime, CFTimeInterval};
|
||||
use string::CFStringRef;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFRunLoop(c_void);
|
||||
|
||||
pub type CFRunLoopRef = *mut __CFRunLoop;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFRunLoopSource(c_void);
|
||||
|
||||
pub type CFRunLoopSourceRef = *mut __CFRunLoopSource;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFRunLoopObserver(c_void);
|
||||
|
||||
pub type CFRunLoopObserverRef = *mut __CFRunLoopObserver;
|
||||
|
||||
// Reasons for CFRunLoopRunInMode() to Return
|
||||
pub const kCFRunLoopRunFinished: i32 = 1;
|
||||
pub const kCFRunLoopRunStopped: i32 = 2;
|
||||
pub const kCFRunLoopRunTimedOut: i32 = 3;
|
||||
pub const kCFRunLoopRunHandledSource: i32 = 4;
|
||||
|
||||
// Run Loop Observer Activities
|
||||
//typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
|
||||
pub type CFRunLoopActivity = CFOptionFlags;
|
||||
pub const kCFRunLoopEntry: CFOptionFlags = 1 << 0;
|
||||
pub const kCFRunLoopBeforeTimers: CFOptionFlags = 1 << 1;
|
||||
pub const kCFRunLoopBeforeSources: CFOptionFlags = 1 << 2;
|
||||
pub const kCFRunLoopBeforeWaiting: CFOptionFlags = 1 << 5;
|
||||
pub const kCFRunLoopAfterWaiting: CFOptionFlags = 1 << 6;
|
||||
pub const kCFRunLoopExit: CFOptionFlags = 1 << 7;
|
||||
pub const kCFRunLoopAllActivities: CFOptionFlags = 0x0FFFFFFF;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CFRunLoopSourceContext {
|
||||
pub version: CFIndex,
|
||||
pub info: *mut c_void,
|
||||
pub retain: extern "C" fn (info: *const c_void) -> *const c_void,
|
||||
pub release: extern "C" fn (info: *const c_void),
|
||||
pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef,
|
||||
pub equal: extern "C" fn (info1: *const c_void, info2: *const c_void) -> Boolean,
|
||||
pub hash: extern "C" fn (info: *const c_void) -> CFHashCode,
|
||||
pub schedule: extern "C" fn (info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef),
|
||||
pub cancel: extern "C" fn (info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef),
|
||||
pub perform: extern "C" fn (info: *const c_void),
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CFRunLoopSourceContext1 {
|
||||
pub version: CFIndex,
|
||||
pub info: *mut c_void,
|
||||
pub retain: extern "C" fn (info: *const c_void) -> *const c_void,
|
||||
pub release: extern "C" fn (info: *const c_void),
|
||||
pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef,
|
||||
pub equal: extern "C" fn (info1: *const c_void, info2: *const c_void) -> Boolean,
|
||||
pub hash: extern "C" fn (info: *const c_void) -> CFHashCode,
|
||||
// note that the following two fields are platform dependent in the C header, the ones here are for OS X
|
||||
pub getPort: extern "C" fn (info: *mut c_void) -> mach_port_t,
|
||||
pub perform: extern "C" fn (msg: *mut c_void, size: CFIndex, allocator: CFAllocatorRef, info: *mut c_void) -> *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CFRunLoopObserverContext {
|
||||
pub version: CFIndex,
|
||||
pub info: *mut c_void,
|
||||
pub retain: extern "C" fn (info: *const c_void) -> *const c_void,
|
||||
pub release: extern "C" fn (info: *const c_void),
|
||||
pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef,
|
||||
}
|
||||
|
||||
pub type CFRunLoopObserverCallBack = extern "C" fn (observer: CFRunLoopObserverRef, activity: CFRunLoopActivity, info: *mut c_void);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CFRunLoopTimerContext {
|
||||
pub version: CFIndex,
|
||||
pub info: *mut c_void,
|
||||
pub retain: extern "C" fn (info: *const c_void) -> *const c_void,
|
||||
pub release: extern "C" fn (info: *const c_void),
|
||||
pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef,
|
||||
}
|
||||
|
||||
pub type CFRunLoopTimerCallBack = extern "C" fn (timer: CFRunLoopTimerRef, info: *mut c_void);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFRunLoopTimer;
|
||||
|
||||
pub type CFRunLoopTimerRef = *mut __CFRunLoopTimer;
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFRunLoop.h
|
||||
*/
|
||||
pub static kCFRunLoopDefaultMode: CFStringRef;
|
||||
pub static kCFRunLoopCommonModes: CFStringRef;
|
||||
pub fn CFRunLoopGetTypeID() -> CFTypeID;
|
||||
pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;
|
||||
pub fn CFRunLoopGetMain() -> CFRunLoopRef;
|
||||
pub fn CFRunLoopCopyCurrentMode(rl: CFRunLoopRef) -> CFStringRef;
|
||||
pub fn CFRunLoopCopyAllModes(rl: CFRunLoopRef) -> CFArrayRef;
|
||||
pub fn CFRunLoopAddCommonMode(rl: CFRunLoopRef, mode: CFStringRef);
|
||||
pub fn CFRunLoopGetNextTimerFireDate(rl: CFRunLoopRef, mode: CFStringRef) -> CFAbsoluteTime;
|
||||
pub fn CFRunLoopRun();
|
||||
pub fn CFRunLoopRunInMode(mode: CFStringRef, seconds: CFTimeInterval, returnAfterSourceHandled: Boolean) -> i32;
|
||||
pub fn CFRunLoopIsWaiting(rl: CFRunLoopRef) -> Boolean;
|
||||
pub fn CFRunLoopWakeUp(rl: CFRunLoopRef);
|
||||
pub fn CFRunLoopStop(rl: CFRunLoopRef);
|
||||
// fn CFRunLoopPerformBlock(rl: CFRunLoopRef, mode: CFTypeRef, block: void (^)(void));
|
||||
pub fn CFRunLoopContainsSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef) -> Boolean;
|
||||
pub fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
|
||||
pub fn CFRunLoopRemoveSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
|
||||
pub fn CFRunLoopContainsObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef) -> Boolean;
|
||||
pub fn CFRunLoopAddObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef);
|
||||
pub fn CFRunLoopRemoveObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef);
|
||||
pub fn CFRunLoopContainsTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef) -> Boolean;
|
||||
pub fn CFRunLoopAddTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef);
|
||||
pub fn CFRunLoopRemoveTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef);
|
||||
|
||||
pub fn CFRunLoopSourceGetTypeID() -> CFTypeID;
|
||||
pub fn CFRunLoopSourceCreate(allocator: CFAllocatorRef, order: CFIndex, context: *mut CFRunLoopSourceContext) -> CFRunLoopSourceRef;
|
||||
pub fn CFRunLoopSourceGetOrder(source: CFRunLoopSourceRef) -> CFIndex;
|
||||
pub fn CFRunLoopSourceInvalidate(source: CFRunLoopSourceRef);
|
||||
pub fn CFRunLoopSourceIsValid(source: CFRunLoopSourceRef) -> Boolean;
|
||||
pub fn CFRunLoopSourceGetContext(source: CFRunLoopSourceRef, context: *mut CFRunLoopSourceContext);
|
||||
pub fn CFRunLoopSourceSignal(source: CFRunLoopSourceRef);
|
||||
|
||||
pub fn CFRunLoopObserverGetTypeID() -> CFTypeID;
|
||||
pub fn CFRunLoopObserverCreate(allocator: CFAllocatorRef, activities: CFOptionFlags, repeats: Boolean, order: CFIndex, callout: CFRunLoopObserverCallBack, context: *mut CFRunLoopObserverContext) -> CFRunLoopObserverRef;
|
||||
// fn CFRunLoopObserverCreateWithHandler(allocator: CFAllocatorRef, activities: CFOptionFlags, repeats: Boolean, order: CFIndex, block: void (^) (CFRunLoopObserverRef observer, CFRunLoopActivity activity)) -> CFRunLoopObserverRef;
|
||||
pub fn CFRunLoopObserverGetActivities(observer: CFRunLoopObserverRef) -> CFOptionFlags;
|
||||
pub fn CFRunLoopObserverDoesRepeat(observer: CFRunLoopObserverRef) -> Boolean;
|
||||
pub fn CFRunLoopObserverGetOrder(observer: CFRunLoopObserverRef) -> CFIndex;
|
||||
pub fn CFRunLoopObserverInvalidate(observer: CFRunLoopObserverRef);
|
||||
pub fn CFRunLoopObserverIsValid(observer: CFRunLoopObserverRef) -> Boolean;
|
||||
pub fn CFRunLoopObserverGetContext(observer: CFRunLoopObserverRef, context: *mut CFRunLoopObserverContext);
|
||||
|
||||
pub fn CFRunLoopTimerGetTypeID() -> CFTypeID;
|
||||
pub fn CFRunLoopTimerCreate(allocator: CFAllocatorRef, fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, callout: CFRunLoopTimerCallBack, context: *mut CFRunLoopTimerContext) -> CFRunLoopTimerRef;
|
||||
// fn CFRunLoopTimerCreateWithHandler(allocator: CFAllocatorRef, fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, block: void (^) (CFRunLoopTimerRef timer)) -> CFRunLoopTimerRef;
|
||||
pub fn CFRunLoopTimerGetNextFireDate(timer: CFRunLoopTimerRef) -> CFAbsoluteTime;
|
||||
pub fn CFRunLoopTimerSetNextFireDate(timer: CFRunLoopTimerRef, fireDate: CFAbsoluteTime);
|
||||
pub fn CFRunLoopTimerGetInterval(timer: CFRunLoopTimerRef) -> CFTimeInterval;
|
||||
pub fn CFRunLoopTimerDoesRepeat(timer: CFRunLoopTimerRef) -> Boolean;
|
||||
pub fn CFRunLoopTimerGetOrder(timer: CFRunLoopTimerRef) -> CFIndex;
|
||||
pub fn CFRunLoopTimerInvalidate(timer: CFRunLoopTimerRef);
|
||||
pub fn CFRunLoopTimerIsValid(timer: CFRunLoopTimerRef) -> Boolean;
|
||||
pub fn CFRunLoopTimerGetContext(timer: CFRunLoopTimerRef, context: *mut CFRunLoopTimerContext);
|
||||
pub fn CFRunLoopTimerGetTolerance(timer: CFRunLoopTimerRef) -> CFTimeInterval;
|
||||
pub fn CFRunLoopTimerSetTolerance(timer: CFRunLoopTimerRef, tolerance: CFTimeInterval);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFAllocatorRef, CFIndex, CFTypeID};
|
||||
|
||||
pub type CFSetApplierFunction = extern "C" fn (value: *const c_void,
|
||||
context: *const c_void);
|
||||
pub type CFSetRetainCallBack = *const u8;
|
||||
pub type CFSetReleaseCallBack = *const u8;
|
||||
pub type CFSetCopyDescriptionCallBack = *const u8;
|
||||
pub type CFSetEqualCallBack = *const u8;
|
||||
pub type CFSetHashCallBack = *const u8;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CFSetCallBacks {
|
||||
pub version: CFIndex,
|
||||
pub retain: CFSetRetainCallBack,
|
||||
pub release: CFSetReleaseCallBack,
|
||||
pub copyDescription: CFSetCopyDescriptionCallBack,
|
||||
pub equal: CFSetEqualCallBack,
|
||||
pub hash: CFSetHashCallBack,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFSet(c_void);
|
||||
|
||||
pub type CFSetRef = *const __CFSet;
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFSet.h
|
||||
*/
|
||||
|
||||
pub static kCFTypeSetCallBacks: CFSetCallBacks;
|
||||
|
||||
/* Creating Sets */
|
||||
pub fn CFSetCreate(allocator: CFAllocatorRef, values: *const *const c_void, numValues: CFIndex,
|
||||
callBacks: *const CFSetCallBacks) -> CFSetRef;
|
||||
|
||||
/* Applying a Function to Set Members */
|
||||
pub fn CFSetApplyFunction(theSet: CFSetRef,
|
||||
applier: CFSetApplierFunction,
|
||||
context: *const c_void);
|
||||
|
||||
pub fn CFSetGetCount(theSet: CFSetRef) -> CFIndex;
|
||||
|
||||
pub fn CFSetGetTypeID() -> CFTypeID;
|
||||
}
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::{c_char, c_ushort, c_void};
|
||||
|
||||
use base::{Boolean, CFOptionFlags, CFIndex, CFAllocatorRef, CFRange, CFTypeID};
|
||||
|
||||
pub type UniChar = c_ushort;
|
||||
|
||||
// CFString.h
|
||||
|
||||
pub type CFStringCompareFlags = CFOptionFlags;
|
||||
//static kCFCompareCaseInsensitive: CFStringCompareFlags = 1;
|
||||
//static kCFCompareBackwards: CFStringCompareFlags = 4;
|
||||
//static kCFCompareAnchored: CFStringCompareFlags = 8;
|
||||
//static kCFCompareNonliteral: CFStringCompareFlags = 16;
|
||||
//static kCFCompareLocalized: CFStringCompareFlags = 32;
|
||||
//static kCFCompareNumerically: CFStringCompareFlags = 64;
|
||||
//static kCFCompareDiacriticInsensitive: CFStringCompareFlags = 128;
|
||||
//static kCFCompareWidthInsensitive: CFStringCompareFlags = 256;
|
||||
//static kCFCompareForcedOrdering: CFStringCompareFlags = 512;
|
||||
|
||||
pub type CFStringEncoding = u32;
|
||||
|
||||
// OS X built-in encodings.
|
||||
|
||||
//static kCFStringEncodingMacRoman: CFStringEncoding = 0;
|
||||
//static kCFStringEncodingWindowsLatin1: CFStringEncoding = 0x0500;
|
||||
//static kCFStringEncodingISOLatin1: CFStringEncoding = 0x0201;
|
||||
//static kCFStringEncodingNextStepLatin: CFStringEncoding = 0x0B01;
|
||||
//static kCFStringEncodingASCII: CFStringEncoding = 0x0600;
|
||||
//static kCFStringEncodingUnicode: CFStringEncoding = 0x0100;
|
||||
pub static kCFStringEncodingUTF8: CFStringEncoding = 0x08000100;
|
||||
//static kCFStringEncodingNonLossyASCII: CFStringEncoding = 0x0BFF;
|
||||
|
||||
//static kCFStringEncodingUTF16: CFStringEncoding = 0x0100;
|
||||
//static kCFStringEncodingUTF16BE: CFStringEncoding = 0x10000100;
|
||||
//static kCFStringEncodingUTF16LE: CFStringEncoding = 0x14000100;
|
||||
//static kCFStringEncodingUTF32: CFStringEncoding = 0x0c000100;
|
||||
//static kCFStringEncodingUTF32BE: CFStringEncoding = 0x18000100;
|
||||
//static kCFStringEncodingUTF32LE: CFStringEncoding = 0x1c000100;
|
||||
|
||||
|
||||
// CFStringEncodingExt.h
|
||||
|
||||
pub type CFStringEncodings = CFIndex;
|
||||
|
||||
// External encodings, except those defined above.
|
||||
// Defined above: kCFStringEncodingMacRoman = 0
|
||||
//static kCFStringEncodingMacJapanese: CFStringEncoding = 1;
|
||||
//static kCFStringEncodingMacChineseTrad: CFStringEncoding = 2;
|
||||
//static kCFStringEncodingMacKorean: CFStringEncoding = 3;
|
||||
//static kCFStringEncodingMacArabic: CFStringEncoding = 4;
|
||||
//static kCFStringEncodingMacHebrew: CFStringEncoding = 5;
|
||||
//static kCFStringEncodingMacGreek: CFStringEncoding = 6;
|
||||
//static kCFStringEncodingMacCyrillic: CFStringEncoding = 7;
|
||||
//static kCFStringEncodingMacDevanagari: CFStringEncoding = 9;
|
||||
//static kCFStringEncodingMacGurmukhi: CFStringEncoding = 10;
|
||||
//static kCFStringEncodingMacGujarati: CFStringEncoding = 11;
|
||||
//static kCFStringEncodingMacOriya: CFStringEncoding = 12;
|
||||
//static kCFStringEncodingMacBengali: CFStringEncoding = 13;
|
||||
//static kCFStringEncodingMacTamil: CFStringEncoding = 14;
|
||||
//static kCFStringEncodingMacTelugu: CFStringEncoding = 15;
|
||||
//static kCFStringEncodingMacKannada: CFStringEncoding = 16;
|
||||
//static kCFStringEncodingMacMalayalam: CFStringEncoding = 17;
|
||||
//static kCFStringEncodingMacSinhalese: CFStringEncoding = 18;
|
||||
//static kCFStringEncodingMacBurmese: CFStringEncoding = 19;
|
||||
//static kCFStringEncodingMacKhmer: CFStringEncoding = 20;
|
||||
//static kCFStringEncodingMacThai: CFStringEncoding = 21;
|
||||
//static kCFStringEncodingMacLaotian: CFStringEncoding = 22;
|
||||
//static kCFStringEncodingMacGeorgian: CFStringEncoding = 23;
|
||||
//static kCFStringEncodingMacArmenian: CFStringEncoding = 24;
|
||||
//static kCFStringEncodingMacChineseSimp: CFStringEncoding = 25;
|
||||
//static kCFStringEncodingMacTibetan: CFStringEncoding = 26;
|
||||
//static kCFStringEncodingMacMongolian: CFStringEncoding = 27;
|
||||
//static kCFStringEncodingMacEthiopic: CFStringEncoding = 28;
|
||||
//static kCFStringEncodingMacCentralEurRoman: CFStringEncoding = 29;
|
||||
//static kCFStringEncodingMacVietnamese: CFStringEncoding = 30;
|
||||
//static kCFStringEncodingMacExtArabic: CFStringEncoding = 31;
|
||||
//static kCFStringEncodingMacSymbol: CFStringEncoding = 33;
|
||||
//static kCFStringEncodingMacDingbats: CFStringEncoding = 34;
|
||||
//static kCFStringEncodingMacTurkish: CFStringEncoding = 35;
|
||||
//static kCFStringEncodingMacCroatian: CFStringEncoding = 36;
|
||||
//static kCFStringEncodingMacIcelandic: CFStringEncoding = 37;
|
||||
//static kCFStringEncodingMacRomanian: CFStringEncoding = 38;
|
||||
//static kCFStringEncodingMacCeltic: CFStringEncoding = 39;
|
||||
//static kCFStringEncodingMacGaelic: CFStringEncoding = 40;
|
||||
//static kCFStringEncodingMacFarsi: CFStringEncoding = 0x8C;
|
||||
//static kCFStringEncodingMacUkrainian: CFStringEncoding = 0x98;
|
||||
//static kCFStringEncodingMacInuit: CFStringEncoding = 0xEC;
|
||||
//static kCFStringEncodingMacVT100: CFStringEncoding = 0xFC;
|
||||
//static kCFStringEncodingMacHFS: CFStringEncoding = 0xFF;
|
||||
// Defined above: kCFStringEncodingISOLatin1 = 0x0201
|
||||
//static kCFStringEncodingISOLatin2: CFStringEncoding = 0x0202;
|
||||
//static kCFStringEncodingISOLatin3: CFStringEncoding = 0x0203;
|
||||
//static kCFStringEncodingISOLatin4: CFStringEncoding = 0x0204;
|
||||
//static kCFStringEncodingISOLatinCyrillic: CFStringEncoding = 0x0205;
|
||||
//static kCFStringEncodingISOLatinArabic: CFStringEncoding = 0x0206;
|
||||
//static kCFStringEncodingISOLatinGreek: CFStringEncoding = 0x0207;
|
||||
//static kCFStringEncodingISOLatinHebrew: CFStringEncoding = 0x0208;
|
||||
//static kCFStringEncodingISOLatin5: CFStringEncoding = 0x0209;
|
||||
//static kCFStringEncodingISOLatin6: CFStringEncoding = 0x020A;
|
||||
//static kCFStringEncodingISOLatinThai: CFStringEncoding = 0x020B;
|
||||
//static kCFStringEncodingISOLatin7: CFStringEncoding = 0x020D;
|
||||
//static kCFStringEncodingISOLatin8: CFStringEncoding = 0x020E;
|
||||
//static kCFStringEncodingISOLatin9: CFStringEncoding = 0x020F;
|
||||
//static kCFStringEncodingISOLatin10: CFStringEncoding = 0x0210;
|
||||
//static kCFStringEncodingDOSLatinUS: CFStringEncoding = 0x0400;
|
||||
//static kCFStringEncodingDOSGreek: CFStringEncoding = 0x0405;
|
||||
//static kCFStringEncodingDOSBalticRim: CFStringEncoding = 0x0406;
|
||||
//static kCFStringEncodingDOSLatin1: CFStringEncoding = 0x0410;
|
||||
//static kCFStringEncodingDOSGreek1: CFStringEncoding = 0x0411;
|
||||
//static kCFStringEncodingDOSLatin2: CFStringEncoding = 0x0412;
|
||||
//static kCFStringEncodingDOSCyrillic: CFStringEncoding = 0x0413;
|
||||
//static kCFStringEncodingDOSTurkish: CFStringEncoding = 0x0414;
|
||||
//static kCFStringEncodingDOSPortuguese: CFStringEncoding = 0x0415;
|
||||
//static kCFStringEncodingDOSIcelandic: CFStringEncoding = 0x0416;
|
||||
//static kCFStringEncodingDOSHebrew: CFStringEncoding = 0x0417;
|
||||
//static kCFStringEncodingDOSCanadianFrench: CFStringEncoding = 0x0418;
|
||||
//static kCFStringEncodingDOSArabic: CFStringEncoding = 0x0419;
|
||||
//static kCFStringEncodingDOSNordic: CFStringEncoding = 0x041A;
|
||||
//static kCFStringEncodingDOSRussian: CFStringEncoding = 0x041B;
|
||||
//static kCFStringEncodingDOSGreek2: CFStringEncoding = 0x041C;
|
||||
//static kCFStringEncodingDOSThai: CFStringEncoding = 0x041D;
|
||||
//static kCFStringEncodingDOSJapanese: CFStringEncoding = 0x0420;
|
||||
//static kCFStringEncodingDOSChineseSimplif: CFStringEncoding = 0x0421;
|
||||
//static kCFStringEncodingDOSKorean: CFStringEncoding = 0x0422;
|
||||
//static kCFStringEncodingDOSChineseTrad: CFStringEncoding = 0x0423;
|
||||
// Defined above: kCFStringEncodingWindowsLatin1 = 0x0500
|
||||
//static kCFStringEncodingWindowsLatin2: CFStringEncoding = 0x0501;
|
||||
//static kCFStringEncodingWindowsCyrillic: CFStringEncoding = 0x0502;
|
||||
//static kCFStringEncodingWindowsGreek: CFStringEncoding = 0x0503;
|
||||
//static kCFStringEncodingWindowsLatin5: CFStringEncoding = 0x0504;
|
||||
//static kCFStringEncodingWindowsHebrew: CFStringEncoding = 0x0505;
|
||||
//static kCFStringEncodingWindowsArabic: CFStringEncoding = 0x0506;
|
||||
//static kCFStringEncodingWindowsBalticRim: CFStringEncoding = 0x0507;
|
||||
//static kCFStringEncodingWindowsVietnamese: CFStringEncoding = 0x0508;
|
||||
//static kCFStringEncodingWindowsKoreanJohab: CFStringEncoding = 0x0510;
|
||||
// Defined above: kCFStringEncodingASCII = 0x0600
|
||||
//static kCFStringEncodingANSEL: CFStringEncoding = 0x0601;
|
||||
//static kCFStringEncodingJIS_X0201_76: CFStringEncoding = 0x0620;
|
||||
//static kCFStringEncodingJIS_X0208_83: CFStringEncoding = 0x0621;
|
||||
//static kCFStringEncodingJIS_X0208_90: CFStringEncoding = 0x0622;
|
||||
//static kCFStringEncodingJIS_X0212_90: CFStringEncoding = 0x0623;
|
||||
//static kCFStringEncodingJIS_C6226_78: CFStringEncoding = 0x0624;
|
||||
//static kCFStringEncodingShiftJIS_X0213: CFStringEncoding = 0x0628;
|
||||
//static kCFStringEncodingShiftJIS_X0213_MenKuTen: CFStringEncoding = 0x0629;
|
||||
//static kCFStringEncodingGB_2312_80: CFStringEncoding = 0x0630;
|
||||
//static kCFStringEncodingGBK_95: CFStringEncoding = 0x0631;
|
||||
//static kCFStringEncodingGB_18030_2000: CFStringEncoding = 0x0632;
|
||||
//static kCFStringEncodingKSC_5601_87: CFStringEncoding = 0x0640;
|
||||
//static kCFStringEncodingKSC_5601_92_Johab: CFStringEncoding = 0x0641;
|
||||
//static kCFStringEncodingCNS_11643_92_P1: CFStringEncoding = 0x0651;
|
||||
//static kCFStringEncodingCNS_11643_92_P2: CFStringEncoding = 0x0652;
|
||||
//static kCFStringEncodingCNS_11643_92_P3: CFStringEncoding = 0x0653;
|
||||
//static kCFStringEncodingISO_2022_JP: CFStringEncoding = 0x0820;
|
||||
//static kCFStringEncodingISO_2022_JP_2: CFStringEncoding = 0x0821;
|
||||
//static kCFStringEncodingISO_2022_JP_1: CFStringEncoding = 0x0822;
|
||||
//static kCFStringEncodingISO_2022_JP_3: CFStringEncoding = 0x0823;
|
||||
//static kCFStringEncodingISO_2022_CN: CFStringEncoding = 0x0830;
|
||||
//static kCFStringEncodingISO_2022_CN_EXT: CFStringEncoding = 0x0831;
|
||||
//static kCFStringEncodingISO_2022_KR: CFStringEncoding = 0x0840;
|
||||
//static kCFStringEncodingEUC_JP: CFStringEncoding = 0x0920;
|
||||
//static kCFStringEncodingEUC_CN: CFStringEncoding = 0x0930;
|
||||
//static kCFStringEncodingEUC_TW: CFStringEncoding = 0x0931;
|
||||
//static kCFStringEncodingEUC_KR: CFStringEncoding = 0x0940;
|
||||
//static kCFStringEncodingShiftJIS: CFStringEncoding = 0x0A01;
|
||||
//static kCFStringEncodingKOI8_R: CFStringEncoding = 0x0A02;
|
||||
//static kCFStringEncodingBig5: CFStringEncoding = 0x0A03;
|
||||
//static kCFStringEncodingMacRomanLatin1: CFStringEncoding = 0x0A04;
|
||||
//static kCFStringEncodingHZ_GB_2312: CFStringEncoding = 0x0A05;
|
||||
//static kCFStringEncodingBig5_HKSCS_1999: CFStringEncoding = 0x0A06;
|
||||
//static kCFStringEncodingVISCII: CFStringEncoding = 0x0A07;
|
||||
//static kCFStringEncodingKOI8_U: CFStringEncoding = 0x0A08;
|
||||
//static kCFStringEncodingBig5_E: CFStringEncoding = 0x0A09;
|
||||
// Defined above: kCFStringEncodingNextStepLatin = 0x0B01
|
||||
//static kCFStringEncodingNextStepJapanese: CFStringEncoding = 0x0B02;
|
||||
//static kCFStringEncodingEBCDIC_US: CFStringEncoding = 0x0C01;
|
||||
//static kCFStringEncodingEBCDIC_CP037: CFStringEncoding = 0x0C02;
|
||||
//static kCFStringEncodingUTF7: CFStringEncoding = 0x04000100;
|
||||
//static kCFStringEncodingUTF7_IMAP: CFStringEncoding = 0x0A10;
|
||||
//static kCFStringEncodingShiftJIS_X0213_00: CFStringEncoding = 0x0628; /* Deprecated */
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFString(c_void);
|
||||
|
||||
pub type CFStringRef = *const __CFString;
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFString.h
|
||||
*/
|
||||
|
||||
// N.B. organized according to "Functions by task" in docs
|
||||
|
||||
/* Creating a CFString */
|
||||
//fn CFSTR
|
||||
//fn CFStringCreateArrayBySeparatingStrings
|
||||
//fn CFStringCreateByCombiningStrings
|
||||
//fn CFStringCreateCopy
|
||||
//fn CFStringCreateFromExternalRepresentation
|
||||
pub fn CFStringCreateWithBytes(alloc: CFAllocatorRef,
|
||||
bytes: *const u8,
|
||||
numBytes: CFIndex,
|
||||
encoding: CFStringEncoding,
|
||||
isExternalRepresentation: Boolean)
|
||||
-> CFStringRef;
|
||||
pub fn CFStringCreateWithBytesNoCopy(alloc: CFAllocatorRef,
|
||||
bytes: *const u8,
|
||||
numBytes: CFIndex,
|
||||
encoding: CFStringEncoding,
|
||||
isExternalRepresentation: Boolean,
|
||||
contentsDeallocator: CFAllocatorRef)
|
||||
-> CFStringRef;
|
||||
//fn CFStringCreateWithCharacters
|
||||
//fn CFStringCreateWithCharactersNoCopy
|
||||
pub fn CFStringCreateWithCString(alloc: CFAllocatorRef,
|
||||
cStr: *const c_char,
|
||||
encoding: CFStringEncoding)
|
||||
-> CFStringRef;
|
||||
//fn CFStringCreateWithCStringNoCopy
|
||||
//fn CFStringCreateWithFormat
|
||||
//fn CFStringCreateWithFormatAndArguments
|
||||
//fn CFStringCreateWithPascalString
|
||||
//fn CFStringCreateWithPascalStringNoCopy
|
||||
//fn CFStringCreateWithSubstring
|
||||
|
||||
/* Searching Strings */
|
||||
//fn CFStringCreateArrayWithFindResults
|
||||
//fn CFStringFind
|
||||
//fn CFStringFindCharacterFromSet
|
||||
//fn CFStringFindWithOptions
|
||||
//fn CFStringFindWithOptionsAndLocale
|
||||
//fn CFStringGetLineBounds
|
||||
|
||||
/* Comparing Strings */
|
||||
//fn CFStringCompare
|
||||
//fn CFStringCompareWithOptions
|
||||
//fn CFStringCompareWithOptionsAndLocale
|
||||
//fn CFStringHasPrefix
|
||||
//fn CFStringHasSuffix
|
||||
|
||||
/* Accessing Characters */
|
||||
//fn CFStringCreateExternalRepresentation
|
||||
pub fn CFStringGetBytes(theString: CFStringRef,
|
||||
range: CFRange,
|
||||
encoding: CFStringEncoding,
|
||||
lossByte: u8,
|
||||
isExternalRepresentation: Boolean,
|
||||
buffer: *mut u8,
|
||||
maxBufLen: CFIndex,
|
||||
usedBufLen: *mut CFIndex)
|
||||
-> CFIndex;
|
||||
//fn CFStringGetCharacterAtIndex
|
||||
//fn CFStringGetCharacters
|
||||
//fn CFStringGetCharactersPtr
|
||||
//fn CFStringGetCharacterFromInlineBuffer
|
||||
pub fn CFStringGetCString(theString: CFStringRef,
|
||||
buffer: *mut c_char,
|
||||
bufferSize: CFIndex,
|
||||
encoding: CFStringEncoding)
|
||||
-> Boolean;
|
||||
pub fn CFStringGetCStringPtr(theString: CFStringRef,
|
||||
encoding: CFStringEncoding)
|
||||
-> *const c_char;
|
||||
pub fn CFStringGetLength(theString: CFStringRef) -> CFIndex;
|
||||
//fn CFStringGetPascalString
|
||||
//fn CFStringGetPascalStringPtr
|
||||
//fn CFStringGetRangeOfComposedCharactersAtIndex
|
||||
//fn CFStringInitInlineBuffer
|
||||
|
||||
/* Working With Hyphenation */
|
||||
//fn CFStringGetHyphenationLocationBeforeIndex
|
||||
//fn CFStringIsHyphenationAvailableForLocale
|
||||
|
||||
/* Working With Encodings */
|
||||
//fn CFStringConvertEncodingToIANACharSetName
|
||||
//fn CFStringConvertEncodingToNSStringEncoding
|
||||
//fn CFStringConvertEncodingToWindowsCodepage
|
||||
//fn CFStringConvertIANACharSetNameToEncoding
|
||||
//fn CFStringConvertNSStringEncodingToEncoding
|
||||
//fn CFStringConvertWindowsCodepageToEncoding
|
||||
//fn CFStringGetFastestEncoding
|
||||
//fn CFStringGetListOfAvailableEncodings
|
||||
//fn CFStringGetMaximumSizeForEncoding
|
||||
//fn CFStringGetMostCompatibleMacStringEncoding
|
||||
//fn CFStringGetNameOfEncoding
|
||||
//fn CFStringGetSmallestEncoding
|
||||
//fn CFStringGetSystemEncoding
|
||||
//fn CFStringIsEncodingAvailable
|
||||
|
||||
/* Getting Numeric Values */
|
||||
//fn CFStringGetDoubleValue
|
||||
//fn CFStringGetIntValue
|
||||
|
||||
/* Getting String Properties */
|
||||
//fn CFShowStr
|
||||
pub fn CFStringGetTypeID() -> CFTypeID;
|
||||
|
||||
/* String File System Representations */
|
||||
//fn CFStringCreateWithFileSystemRepresentation
|
||||
//fn CFStringGetFileSystemRepresentation
|
||||
//fn CFStringGetMaximumSizeOfFileSystemRepresentation
|
||||
|
||||
/* Getting Paragraph Bounds */
|
||||
//fn CFStringGetParagraphBounds
|
||||
|
||||
/* Managing Surrogates */
|
||||
//fn CFStringGetLongCharacterForSurrogatePair
|
||||
//fn CFStringGetSurrogatePairForLongCharacter
|
||||
//fn CFStringIsSurrogateHighCharacter
|
||||
//fn CFStringIsSurrogateLowCharacter
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFAllocatorRef, CFTypeID};
|
||||
use date::{CFTimeInterval, CFAbsoluteTime};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFTimeZone(c_void);
|
||||
|
||||
pub type CFTimeZoneRef = *const __CFTimeZone;
|
||||
|
||||
extern {
|
||||
pub fn CFTimeZoneCopySystem() -> CFTimeZoneRef;
|
||||
pub fn CFTimeZoneCopyDefault() -> CFTimeZoneRef;
|
||||
pub fn CFTimeZoneCreateWithTimeIntervalFromGMT(allocator: CFAllocatorRef, interval: CFTimeInterval) -> CFTimeZoneRef;
|
||||
pub fn CFTimeZoneGetSecondsFromGMT(tz: CFTimeZoneRef, time: CFAbsoluteTime) -> CFTimeInterval;
|
||||
|
||||
pub fn CFTimeZoneGetTypeID() -> CFTypeID;
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFOptionFlags, CFIndex, CFAllocatorRef, Boolean, CFTypeID, CFTypeRef, SInt32};
|
||||
use string::{CFStringRef, CFStringEncoding};
|
||||
use error::CFErrorRef;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFURL(c_void);
|
||||
|
||||
pub type CFURLRef = *const __CFURL;
|
||||
|
||||
pub type CFURLBookmarkCreationOptions = CFOptionFlags;
|
||||
|
||||
pub type CFURLPathStyle = CFIndex;
|
||||
|
||||
/* typedef CF_ENUM(CFIndex, CFURLPathStyle) */
|
||||
pub const kCFURLPOSIXPathStyle: CFURLPathStyle = 0;
|
||||
pub const kCFURLHFSPathStyle: CFURLPathStyle = 1;
|
||||
pub const kCFURLWindowsPathStyle: CFURLPathStyle = 2;
|
||||
|
||||
// static kCFURLBookmarkCreationPreferFileIDResolutionMask: CFURLBookmarkCreationOptions =
|
||||
// (1 << 8) as u32;
|
||||
// static kCFURLBookmarkCreationMinimalBookmarkMask: CFURLBookmarkCreationOptions =
|
||||
// (1 << 9) as u32;
|
||||
// static kCFURLBookmarkCreationSuitableForBookmarkFile: CFURLBookmarkCreationOptions =
|
||||
// (1 << 10) as u32;
|
||||
// static kCFURLBookmarkCreationWithSecurityScope: CFURLBookmarkCreationOptions =
|
||||
// (1 << 11) as u32;
|
||||
// static kCFURLBookmarkCreationSecurityScopeAllowOnlyReadAccess: CFURLBookmarkCreationOptions =
|
||||
// (1 << 12) as u32;
|
||||
|
||||
// TODO: there are a lot of missing keys and constants. Add if you are bored or need them.
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFURL.h
|
||||
*/
|
||||
|
||||
/* Common File System Resource Keys */
|
||||
pub static kCFURLAttributeModificationDateKey: CFStringRef;
|
||||
pub static kCFURLContentAccessDateKey: CFStringRef;
|
||||
pub static kCFURLContentModificationDateKey: CFStringRef;
|
||||
pub static kCFURLCreationDateKey: CFStringRef;
|
||||
pub static kCFURLFileResourceIdentifierKey: CFStringRef;
|
||||
pub static kCFURLFileSecurityKey: CFStringRef;
|
||||
pub static kCFURLHasHiddenExtensionKey: CFStringRef;
|
||||
pub static kCFURLIsDirectoryKey: CFStringRef;
|
||||
pub static kCFURLIsExecutableKey: CFStringRef;
|
||||
pub static kCFURLIsHiddenKey: CFStringRef;
|
||||
pub static kCFURLIsPackageKey: CFStringRef;
|
||||
pub static kCFURLIsReadableKey: CFStringRef;
|
||||
pub static kCFURLIsRegularFileKey: CFStringRef;
|
||||
pub static kCFURLIsSymbolicLinkKey: CFStringRef;
|
||||
pub static kCFURLIsSystemImmutableKey: CFStringRef;
|
||||
pub static kCFURLIsUserImmutableKey: CFStringRef;
|
||||
pub static kCFURLIsVolumeKey: CFStringRef;
|
||||
pub static kCFURLIsWritableKey: CFStringRef;
|
||||
pub static kCFURLLabelNumberKey: CFStringRef;
|
||||
pub static kCFURLLinkCountKey: CFStringRef;
|
||||
pub static kCFURLLocalizedLabelKey: CFStringRef;
|
||||
pub static kCFURLLocalizedNameKey: CFStringRef;
|
||||
pub static kCFURLLocalizedTypeDescriptionKey: CFStringRef;
|
||||
pub static kCFURLNameKey: CFStringRef;
|
||||
pub static kCFURLParentDirectoryURLKey: CFStringRef;
|
||||
pub static kCFURLPreferredIOBlockSizeKey: CFStringRef;
|
||||
pub static kCFURLTypeIdentifierKey: CFStringRef;
|
||||
pub static kCFURLVolumeIdentifierKey: CFStringRef;
|
||||
pub static kCFURLVolumeURLKey: CFStringRef;
|
||||
|
||||
#[cfg(feature="mac_os_10_8_features")]
|
||||
#[cfg_attr(feature = "mac_os_10_7_support", linkage = "extern_weak")]
|
||||
pub static kCFURLIsExcludedFromBackupKey: CFStringRef;
|
||||
pub static kCFURLFileResourceTypeKey: CFStringRef;
|
||||
|
||||
/* Creating a CFURL */
|
||||
pub fn CFURLCopyAbsoluteURL(anURL: CFURLRef) -> CFURLRef;
|
||||
//fn CFURLCreateAbsoluteURLWithBytes
|
||||
//fn CFURLCreateByResolvingBookmarkData
|
||||
//fn CFURLCreateCopyAppendingPathComponent
|
||||
//fn CFURLCreateCopyAppendingPathExtension
|
||||
//fn CFURLCreateCopyDeletingLastPathComponent
|
||||
//fn CFURLCreateCopyDeletingPathExtension
|
||||
pub fn CFURLCreateFilePathURL(allocator: CFAllocatorRef, url: CFURLRef, error: *mut CFErrorRef) -> CFURLRef;
|
||||
//fn CFURLCreateFileReferenceURL
|
||||
pub fn CFURLCreateFromFileSystemRepresentation(allocator: CFAllocatorRef, buffer: *const u8, bufLen: CFIndex, isDirectory: Boolean) -> CFURLRef;
|
||||
//fn CFURLCreateFromFileSystemRepresentationRelativeToBase
|
||||
//fn CFURLCreateFromFSRef
|
||||
pub fn CFURLCreateWithBytes(allocator: CFAllocatorRef, URLBytes: *const u8, length: CFIndex, encoding: CFStringEncoding, baseURL: CFURLRef) -> CFURLRef;
|
||||
pub fn CFURLCreateWithFileSystemPath(allocator: CFAllocatorRef, filePath: CFStringRef, pathStyle: CFURLPathStyle, isDirectory: Boolean) -> CFURLRef;
|
||||
pub fn CFURLCreateWithFileSystemPathRelativeToBase(allocator: CFAllocatorRef, filePath: CFStringRef, pathStyle: CFURLPathStyle, isDirectory: Boolean, baseURL: CFURLRef) -> CFURLRef;
|
||||
//fn CFURLCreateWithString(allocator: CFAllocatorRef, urlString: CFStringRef,
|
||||
// baseURL: CFURLRef) -> CFURLRef;
|
||||
|
||||
/* Accessing the Parts of a URL */
|
||||
pub fn CFURLCanBeDecomposed(anURL: CFURLRef) -> Boolean;
|
||||
pub fn CFURLCopyFileSystemPath(anURL: CFURLRef, pathStyle: CFURLPathStyle) -> CFStringRef;
|
||||
pub fn CFURLCopyFragment(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef) -> CFStringRef;
|
||||
pub fn CFURLCopyHostName(anURL: CFURLRef) -> CFStringRef;
|
||||
pub fn CFURLCopyLastPathComponent(anURL: CFURLRef) -> CFStringRef;
|
||||
pub fn CFURLCopyNetLocation(anURL: CFURLRef) -> CFStringRef;
|
||||
pub fn CFURLCopyParameterString(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef) -> CFStringRef;
|
||||
pub fn CFURLCopyPassword(anURL: CFURLRef) -> CFStringRef;
|
||||
pub fn CFURLCopyPath(anURL: CFURLRef) -> CFStringRef;
|
||||
pub fn CFURLCopyPathExtension(anURL: CFURLRef) -> CFStringRef;
|
||||
pub fn CFURLCopyQueryString(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef) -> CFStringRef;
|
||||
pub fn CFURLCopyResourceSpecifier(anURL: CFURLRef) -> CFStringRef;
|
||||
pub fn CFURLCopyScheme(anURL: CFURLRef) -> CFStringRef;
|
||||
pub fn CFURLCopyStrictPath(anURL: CFURLRef, isAbsolute: *mut Boolean) -> CFStringRef;
|
||||
pub fn CFURLCopyUserName(anURL: CFURLRef) -> CFStringRef;
|
||||
pub fn CFURLGetPortNumber(anURL: CFURLRef) -> SInt32;
|
||||
pub fn CFURLHasDirectoryPath(anURL: CFURLRef) -> Boolean;
|
||||
|
||||
/* Converting URLs to Other Representations */
|
||||
//fn CFURLCreateData(allocator: CFAllocatorRef, url: CFURLRef,
|
||||
// encoding: CFStringEncoding, escapeWhitespace: bool) -> CFDataRef;
|
||||
//fn CFURLCreateStringByAddingPercentEscapes
|
||||
//fn CFURLCreateStringByReplacingPercentEscapes
|
||||
//fn CFURLCreateStringByReplacingPercentEscapesUsingEncoding
|
||||
pub fn CFURLGetFileSystemRepresentation(anURL: CFURLRef, resolveAgainstBase: Boolean, buffer: *mut u8, maxBufLen: CFIndex) -> Boolean;
|
||||
|
||||
//fn CFURLGetFSRef
|
||||
pub fn CFURLGetString(anURL: CFURLRef) -> CFStringRef;
|
||||
|
||||
/* Getting URL Properties */
|
||||
//fn CFURLGetBaseURL(anURL: CFURLRef) -> CFURLRef;
|
||||
pub fn CFURLGetBytes(anURL: CFURLRef, buffer: *mut u8, bufferLength: CFIndex) -> CFIndex;
|
||||
//fn CFURLGetByteRangeForComponent
|
||||
pub fn CFURLGetTypeID() -> CFTypeID;
|
||||
//fn CFURLResourceIsReachable
|
||||
|
||||
/* Getting and Setting File System Resource Properties */
|
||||
pub fn CFURLClearResourcePropertyCache(url: CFURLRef);
|
||||
//fn CFURLClearResourcePropertyCacheForKey
|
||||
//fn CFURLCopyResourcePropertiesForKeys
|
||||
//fn CFURLCopyResourcePropertyForKey
|
||||
//fn CFURLCreateResourcePropertiesForKeysFromBookmarkData
|
||||
//fn CFURLCreateResourcePropertyForKeyFromBookmarkData
|
||||
//fn CFURLSetResourcePropertiesForKeys
|
||||
pub fn CFURLSetResourcePropertyForKey(url: CFURLRef, key: CFStringRef, value: CFTypeRef, error: *mut CFErrorRef) -> Boolean;
|
||||
//fn CFURLSetTemporaryResourcePropertyForKey
|
||||
|
||||
/* Working with Bookmark Data */
|
||||
//fn CFURLCreateBookmarkData
|
||||
//fn CFURLCreateBookmarkDataFromAliasRecord
|
||||
//fn CFURLCreateBookmarkDataFromFile
|
||||
//fn CFURLWriteBookmarkDataToFile
|
||||
//fn CFURLStartAccessingSecurityScopedResource
|
||||
//fn CFURLStopAccessingSecurityScopedResource
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature="mac_os_10_8_features")]
|
||||
fn can_see_excluded_from_backup_key() {
|
||||
let _ = unsafe { kCFURLIsExcludedFromBackupKey };
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
use libc::c_void;
|
||||
|
||||
use base::{CFAllocatorRef, CFTypeID};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFUUID(c_void);
|
||||
|
||||
pub type CFUUIDRef = *const __CFUUID;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct CFUUIDBytes {
|
||||
pub byte0: u8,
|
||||
pub byte1: u8,
|
||||
pub byte2: u8,
|
||||
pub byte3: u8,
|
||||
pub byte4: u8,
|
||||
pub byte5: u8,
|
||||
pub byte6: u8,
|
||||
pub byte7: u8,
|
||||
pub byte8: u8,
|
||||
pub byte9: u8,
|
||||
pub byte10: u8,
|
||||
pub byte11: u8,
|
||||
pub byte12: u8,
|
||||
pub byte13: u8,
|
||||
pub byte14: u8,
|
||||
pub byte15: u8
|
||||
}
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CFUUID.h
|
||||
*/
|
||||
pub fn CFUUIDCreate(allocator: CFAllocatorRef) -> CFUUIDRef;
|
||||
pub fn CFUUIDCreateFromUUIDBytes(allocator: CFAllocatorRef, bytes: CFUUIDBytes) -> CFUUIDRef;
|
||||
pub fn CFUUIDGetUUIDBytes(uuid: CFUUIDRef) -> CFUUIDBytes;
|
||||
|
||||
pub fn CFUUIDGetTypeID() -> CFTypeID;
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"files":{".travis.yml":"b71b9a6f84b9263b2b89be6ec90dff5920ee68cf9e5768d73ed71957de2d0670","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"8858a9ce62839ea4f8addacfb0d228d8ae1f015a0c233d38afe68eb72763aa18","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"4a45abeb1e684e30bb361dfa7db59189423348e18d310cbae694b7c8c57cd86a","src/base.rs":"10f3eeae06c6dd25cdf3e11b7e2fbbe5d003469ebb4aa1b069625a1637633879","src/color_space.rs":"bada04ad391869474428070ad9ae5dbb5e7f5e03646226fab0b03e8e84240bfa","src/context.rs":"601cb85abd122422abdbcbd8f6116ee4622009aee717cb478f6f0937d481b212","src/data_provider.rs":"78e9fc5c1c609bfb6a29136cd334575b77c6f4c994e444291dbccc52cfd35363","src/display.rs":"3ca38e1ff0200409c95941fcb64afa043310d1c0855c7614fd236c4f83e5a343","src/event.rs":"551a228faa5a938928ee6f7030a2bfc1e40574a93e80eccaea31e3c3ff348e15","src/event_source.rs":"d55a4f5b5e62789325028febc51bbf54c74b15ab1a4e70c6ad749a2f9753e081","src/font.rs":"63b7e50243a56254c800421df586abee59aead84f735f7df838ae04693aedf4b","src/geometry.rs":"b94e50a16b8540dc6f37bfe4b1549ac68974cd6ba6c0bbd9209559f8a46d86eb","src/image.rs":"fb77ae359b918cf3341662cb858cde6111eaa358f60fdd1ebbf264e023d25401","src/lib.rs":"19d5e558cec5596d546f1753529a8e3cf951993f4500ee12fad0d7eb2dc86bc8","src/path.rs":"d8dccd0bc2a1888a0a598fcca25067e932451e220dbec75999982cef9477d3ab","src/private.rs":"da3fd61338bab2d8e26aa5433b2e18ecd2a0a408c62e1ac2b33a0f87f2dad88a","src/sys.rs":"27e00f7ad7645af05014f35939128833456cac766a2978c5da295c3757708a86"},"package":"e54c4ab33705fa1fc8af375bb7929d68e1c1546c1ecef408966d8c3e49a1d84a"}
|
||||
{"files":{".travis.yml":"b71b9a6f84b9263b2b89be6ec90dff5920ee68cf9e5768d73ed71957de2d0670","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"3ff1a11a530609452fd321f65e6d3eb0a504ea3dd1c9b9b575ead73dbfd32072","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"4a45abeb1e684e30bb361dfa7db59189423348e18d310cbae694b7c8c57cd86a","src/base.rs":"10f3eeae06c6dd25cdf3e11b7e2fbbe5d003469ebb4aa1b069625a1637633879","src/color_space.rs":"bada04ad391869474428070ad9ae5dbb5e7f5e03646226fab0b03e8e84240bfa","src/context.rs":"601cb85abd122422abdbcbd8f6116ee4622009aee717cb478f6f0937d481b212","src/data_provider.rs":"78e9fc5c1c609bfb6a29136cd334575b77c6f4c994e444291dbccc52cfd35363","src/display.rs":"1c1a2fe5e52ba31437d5155adcc73f103a62bdaabca55ba290ec0b0b15cb9c7e","src/event.rs":"5f2a645cbd9582cc6861236a3696b9fa1655457bed884fdc218fc8b5b75921cb","src/event_source.rs":"d55a4f5b5e62789325028febc51bbf54c74b15ab1a4e70c6ad749a2f9753e081","src/font.rs":"5ddb75ccb23af98bfc82deefa3100288baf5ea0e4827242d878219d3251d6d55","src/geometry.rs":"b94e50a16b8540dc6f37bfe4b1549ac68974cd6ba6c0bbd9209559f8a46d86eb","src/image.rs":"fb77ae359b918cf3341662cb858cde6111eaa358f60fdd1ebbf264e023d25401","src/lib.rs":"19d5e558cec5596d546f1753529a8e3cf951993f4500ee12fad0d7eb2dc86bc8","src/path.rs":"d8dccd0bc2a1888a0a598fcca25067e932451e220dbec75999982cef9477d3ab","src/private.rs":"da3fd61338bab2d8e26aa5433b2e18ecd2a0a408c62e1ac2b33a0f87f2dad88a","src/sys.rs":"27e00f7ad7645af05014f35939128833456cac766a2978c5da295c3757708a86"},"package":"fb0ed45fdc32f9ab426238fba9407dfead7bacd7900c9b4dd3f396f46eafdae3"}
|
|
@ -12,17 +12,17 @@
|
|||
|
||||
[package]
|
||||
name = "core-graphics"
|
||||
version = "0.14.0"
|
||||
version = "0.13.0"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "Bindings to Core Graphics for OS X"
|
||||
homepage = "https://github.com/servo/core-graphics-rs"
|
||||
license = "MIT / Apache-2.0"
|
||||
repository = "https://github.com/servo/core-foundation-rs"
|
||||
repository = "https://github.com/servo/core-graphics-rs"
|
||||
[dependencies.bitflags]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.core-foundation]
|
||||
version = "0.6"
|
||||
version = "0.5"
|
||||
|
||||
[dependencies.foreign-types]
|
||||
version = "0.3.0"
|
||||
|
|
|
@ -429,12 +429,6 @@ extern "C" {
|
|||
active_displays: *mut CGDirectDisplayID,
|
||||
display_count: *mut libc::uint32_t,
|
||||
) -> CGError;
|
||||
pub fn CGGetDisplaysWithRect(
|
||||
rect: CGRect,
|
||||
max_displays: libc::uint32_t,
|
||||
displays: *mut CGDirectDisplayID,
|
||||
matching_display_count: *mut libc::uint32_t,
|
||||
) -> CGError;
|
||||
pub fn CGDisplayModelNumber(display: CGDirectDisplayID) -> libc::uint32_t;
|
||||
pub fn CGDisplayPixelsHigh(display: CGDirectDisplayID) -> libc::size_t;
|
||||
pub fn CGDisplayPixelsWide(display: CGDirectDisplayID) -> libc::size_t;
|
||||
|
|
|
@ -10,7 +10,6 @@ use foreign_types::ForeignType;
|
|||
|
||||
pub type CGEventField = libc::uint32_t;
|
||||
pub type CGKeyCode = libc::uint16_t;
|
||||
pub type CGScrollEventUnit = libc::uint32_t;
|
||||
|
||||
/// Flags for events
|
||||
///
|
||||
|
@ -95,13 +94,6 @@ impl KeyCode {
|
|||
pub const UP_ARROW: CGKeyCode = 0x7E;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ScrollEventUnit {}
|
||||
impl ScrollEventUnit {
|
||||
pub const PIXEL: CGScrollEventUnit = 0;
|
||||
pub const LINE: CGScrollEventUnit = 1;
|
||||
}
|
||||
|
||||
/// Constants that specify the different types of input events.
|
||||
///
|
||||
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
|
||||
|
@ -443,31 +435,6 @@ impl CGEvent {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_scroll_event(
|
||||
source: CGEventSource,
|
||||
units: CGScrollEventUnit,
|
||||
wheel_count: u32,
|
||||
wheel1: i32,
|
||||
wheel2: i32,
|
||||
wheel3: i32,
|
||||
) -> Result<CGEvent, ()> {
|
||||
unsafe {
|
||||
let event_ref = CGEventCreateScrollWheelEvent2(
|
||||
source.as_ptr(),
|
||||
units,
|
||||
wheel_count,
|
||||
wheel1,
|
||||
wheel2,
|
||||
wheel3,
|
||||
);
|
||||
if !event_ref.is_null() {
|
||||
Ok(Self::from_ptr(event_ref))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn post(&self, tap_location: CGEventTapLocation) {
|
||||
unsafe {
|
||||
CGEventPost(tap_location, self.as_ptr());
|
||||
|
@ -578,21 +545,6 @@ extern {
|
|||
fn CGEventCreateMouseEvent(source: ::sys::CGEventSourceRef, mouseType: CGEventType,
|
||||
mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> ::sys::CGEventRef;
|
||||
|
||||
/// A non-variadic variant version of CGEventCreateScrollWheelEvent.
|
||||
///
|
||||
/// Returns a new Quartz scrolling event.
|
||||
///
|
||||
/// This function allows you to create a scrolling event and customize the
|
||||
/// event before posting it to the event system.
|
||||
fn CGEventCreateScrollWheelEvent2(
|
||||
source: ::sys::CGEventSourceRef,
|
||||
units: CGScrollEventUnit,
|
||||
wheelCount: libc::uint32_t,
|
||||
wheel1: libc::int32_t,
|
||||
wheel2: libc::int32_t,
|
||||
wheel3: libc::int32_t,
|
||||
) -> ::sys::CGEventRef;
|
||||
|
||||
/// Post an event into the event stream at a specified location.
|
||||
///
|
||||
/// This function posts the specified event immediately before any event taps
|
||||
|
|
|
@ -11,7 +11,6 @@ use std::ptr;
|
|||
use core_foundation::base::{CFRelease, CFRetain, CFTypeID, TCFType};
|
||||
use core_foundation::array::{CFArray, CFArrayRef};
|
||||
use core_foundation::data::{CFData, CFDataRef};
|
||||
use core_foundation::number::CFNumber;
|
||||
use core_foundation::string::{CFString, CFStringRef};
|
||||
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
|
||||
use data_provider::CGDataProvider;
|
||||
|
@ -64,7 +63,7 @@ impl CGFont {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_copy_from_variations(&self, vars: &CFDictionary<CFString, CFNumber>) -> Result<CGFont, ()> {
|
||||
pub fn create_copy_from_variations(&self, vars: &CFDictionary) -> Result<CGFont, ()> {
|
||||
unsafe {
|
||||
let font_ref = CGFontCreateCopyWithVariations(self.as_ptr(),
|
||||
vars.as_concrete_TypeRef());
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".travis.yml":"6aad961651169d31d79c0595624d1777b5c4cbb4cf2bed9a126c7e72d29411fd","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"78c71afee9b093b27d65bb9acef96349c9a172b111bd29a84015cd25ac70f1e1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"0c82015d302c9937e6376debd961350afeaeb6dde228aac95e3a3115c5813613","src/font.rs":"446485c979c0c0fed05750970b665976c7297e08207bf5ee75c2bf922bba2427","src/font_collection.rs":"b2697e5212639eb6746546893e13604766b2a1adc3918cac0481ed856fc4843f","src/font_descriptor.rs":"171b8a43f555960ae93ef0e608a83111e13d698702c1808cfee0dcdba53f94ed","src/font_manager.rs":"de5e22620528322d6811d01f03975c53b676ec743297590de5e17a45393df0f1","src/lib.rs":"bd072cf53ebb643e4d21379d4487e60745999d20eab9caee8e56daa430cb65ca"},"package":"81f59bff773954e5cd058a3f5983406b52bec7cc65202bef340ba64a0c40ac91"}
|
||||
{"files":{".travis.yml":"6aad961651169d31d79c0595624d1777b5c4cbb4cf2bed9a126c7e72d29411fd","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"7a7725d84ea421fd0b48ddaa17e6abe58e3dd1507232dc03a76e2fbcb305ebd2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"0c82015d302c9937e6376debd961350afeaeb6dde228aac95e3a3115c5813613","src/font.rs":"640f17efb3492ad0e9c318a4e2e23da87120f817d055475290e2f58f0212577d","src/font_collection.rs":"4fbe6a45d227771e148498bab5f915bd6e7cb6f060427b8f4ac626a44fcee288","src/font_descriptor.rs":"188dfad16e1081ec411dbdce1d8210be187a2dac0cf983444f01d5122e7d8e6e","src/font_manager.rs":"de5e22620528322d6811d01f03975c53b676ec743297590de5e17a45393df0f1","src/lib.rs":"bd072cf53ebb643e4d21379d4487e60745999d20eab9caee8e56daa430cb65ca"},"package":"2bd581c37283d0c23311d179aefbb891f2324ee0405da58a26e8594ab76e5748"}
|
|
@ -12,16 +12,16 @@
|
|||
|
||||
[package]
|
||||
name = "core-text"
|
||||
version = "10.0.0"
|
||||
version = "9.2.0"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "Bindings to the Core Text framework."
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/servo/core-foundation-rs"
|
||||
repository = "https://github.com/servo/core-text-rs"
|
||||
[dependencies.core-foundation]
|
||||
version = "0.6"
|
||||
version = "0.5"
|
||||
|
||||
[dependencies.core-graphics]
|
||||
version = "0.14"
|
||||
version = "0.13"
|
||||
|
||||
[dependencies.foreign-types]
|
||||
version = "0.3"
|
||||
|
|
|
@ -17,7 +17,6 @@ use core_foundation::array::{CFArray, CFArrayRef};
|
|||
use core_foundation::base::{CFIndex, CFOptionFlags, CFTypeID, CFTypeRef, TCFType};
|
||||
use core_foundation::data::{CFData, CFDataRef};
|
||||
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
|
||||
use core_foundation::number::CFNumber;
|
||||
use core_foundation::string::{CFString, CFStringRef, UniChar};
|
||||
use core_foundation::url::{CFURL, CFURLRef};
|
||||
use core_graphics::base::CGFloat;
|
||||
|
@ -99,7 +98,7 @@ pub fn new_from_CGFont(cgfont: &CGFont, pt_size: f64) -> CTFont {
|
|||
|
||||
pub fn new_from_CGFont_with_variations(cgfont: &CGFont,
|
||||
pt_size: f64,
|
||||
variations: &CFDictionary<CFString, CFNumber>)
|
||||
variations: &CFDictionary)
|
||||
-> CTFont {
|
||||
unsafe {
|
||||
let font_desc = font_descriptor::new_from_variations(variations);
|
||||
|
@ -286,11 +285,12 @@ impl CTFont {
|
|||
pub fn get_bounding_rects_for_glyphs(&self, orientation: CTFontOrientation, glyphs: &[CGGlyph])
|
||||
-> CGRect {
|
||||
unsafe {
|
||||
CTFontGetBoundingRectsForGlyphs(self.as_concrete_TypeRef(),
|
||||
orientation,
|
||||
glyphs.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
glyphs.len() as CFIndex)
|
||||
let result = CTFontGetBoundingRectsForGlyphs(self.as_concrete_TypeRef(),
|
||||
orientation,
|
||||
glyphs.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
glyphs.len() as CFIndex);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
use font_descriptor;
|
||||
use font_descriptor::{CTFontDescriptor, CTFontDescriptorCreateMatchingFontDescriptors};
|
||||
use font_manager::{CTFontManagerCopyAvailableFontFamilyNames, CTFontManagerCopyAvailablePostScriptNames};
|
||||
use font_manager::CTFontManagerCopyAvailableFontFamilyNames;
|
||||
|
||||
use core_foundation::array::{CFArray, CFArrayRef};
|
||||
use core_foundation::base::{CFTypeID, TCFType};
|
||||
|
@ -19,6 +19,7 @@ use core_foundation::set::CFSet;
|
|||
use core_foundation::string::{CFString, CFStringRef};
|
||||
|
||||
use libc::c_void;
|
||||
use std::ptr;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CTFontCollection(c_void);
|
||||
|
@ -72,7 +73,7 @@ pub fn create_for_family(family: &str) -> Option<CTFontCollection> {
|
|||
let family_attr = CFString::wrap_under_get_rule(kCTFontFamilyNameAttribute);
|
||||
let family_name: CFString = family.parse().unwrap();
|
||||
let specified_attrs = CFDictionary::from_CFType_pairs(&[
|
||||
(family_attr.clone(), family_name.as_CFType())
|
||||
(family_attr.as_CFType(), family_name.as_CFType())
|
||||
]);
|
||||
|
||||
let wildcard_desc: CTFontDescriptor =
|
||||
|
@ -81,7 +82,7 @@ pub fn create_for_family(family: &str) -> Option<CTFontCollection> {
|
|||
let matched_descs = CTFontDescriptorCreateMatchingFontDescriptors(
|
||||
wildcard_desc.as_concrete_TypeRef(),
|
||||
mandatory_attrs.as_concrete_TypeRef());
|
||||
if matched_descs.is_null() {
|
||||
if matched_descs == ptr::null() {
|
||||
return None;
|
||||
}
|
||||
let matched_descs = CFArray::wrap_under_create_rule(matched_descs);
|
||||
|
@ -97,12 +98,6 @@ pub fn get_family_names() -> CFArray<CFString> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_postscript_names() -> CFArray<CFString> {
|
||||
unsafe {
|
||||
CFArray::wrap_under_create_rule(CTFontManagerCopyAvailablePostScriptNames())
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
/*
|
||||
* CTFontCollection.h
|
||||
|
|
|
@ -15,12 +15,11 @@ use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
|
|||
use core_foundation::number::{CFNumber, CFNumberRef};
|
||||
use core_foundation::set::CFSetRef;
|
||||
use core_foundation::string::{CFString, CFStringRef};
|
||||
use core_foundation::url::CFURL;
|
||||
use core_foundation::url::{CFURLCopyFileSystemPath, kCFURLPOSIXPathStyle, CFURL};
|
||||
use core_graphics::base::CGFloat;
|
||||
|
||||
use libc::c_void;
|
||||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/*
|
||||
* CTFontTraits.h
|
||||
|
@ -93,29 +92,29 @@ impl StylisticClassAccessors for CTFontStylisticClass {
|
|||
| kCTFontSlabSerifsClass
|
||||
| kCTFontFreeformSerifsClass;
|
||||
|
||||
(*self & any_serif_class) != 0
|
||||
return (*self & any_serif_class) != 0;
|
||||
}
|
||||
|
||||
fn is_sans_serif(&self) -> bool {
|
||||
(*self & kCTFontSansSerifClass) != 0
|
||||
return (*self & kCTFontSansSerifClass) != 0;
|
||||
}
|
||||
|
||||
fn is_script(&self) -> bool {
|
||||
(*self & kCTFontScriptsClass) != 0
|
||||
return (*self & kCTFontScriptsClass) != 0;
|
||||
}
|
||||
|
||||
fn is_fantasy(&self) -> bool {
|
||||
(*self & kCTFontOrnamentalsClass) != 0
|
||||
return (*self & kCTFontOrnamentalsClass) != 0;
|
||||
}
|
||||
|
||||
fn is_symbols(&self) -> bool {
|
||||
(*self & kCTFontSymbolicClass) != 0
|
||||
return (*self & kCTFontSymbolicClass) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub type CTFontAttributes = CFDictionary;
|
||||
|
||||
pub type CTFontTraits = CFDictionary<CFString, CFType>;
|
||||
pub type CTFontTraits = CFDictionary;
|
||||
|
||||
pub trait TraitAccessors {
|
||||
fn symbolic_traits(&self) -> CTFontSymbolicTraits;
|
||||
|
@ -125,13 +124,14 @@ pub trait TraitAccessors {
|
|||
}
|
||||
|
||||
trait TraitAccessorPrivate {
|
||||
fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber;
|
||||
unsafe fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber;
|
||||
}
|
||||
|
||||
impl TraitAccessorPrivate for CTFontTraits {
|
||||
fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber {
|
||||
let cftype = self.get(key);
|
||||
cftype.downcast::<CFNumber>().unwrap()
|
||||
unsafe fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber {
|
||||
let cftype = self.get_CFType(mem::transmute(key));
|
||||
assert!(cftype.instance_of::<CFNumber>());
|
||||
CFNumber::wrap_under_get_rule(mem::transmute(cftype.as_CFTypeRef()))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ impl CTFontDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn font_path(&self) -> Option<PathBuf> {
|
||||
pub fn font_path(&self) -> Option<String> {
|
||||
unsafe {
|
||||
let value = CTFontDescriptorCopyAttribute(self.0, kCTFontURLAttribute);
|
||||
if value.is_null() {
|
||||
|
@ -250,7 +250,11 @@ impl CTFontDescriptor {
|
|||
let value = CFType::wrap_under_create_rule(value);
|
||||
assert!(value.instance_of::<CFURL>());
|
||||
let url = CFURL::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
|
||||
url.to_path()
|
||||
let path = CFString::wrap_under_create_rule(CFURLCopyFileSystemPath(
|
||||
url.as_concrete_TypeRef(),
|
||||
kCFURLPOSIXPathStyle,
|
||||
)).to_string();
|
||||
Some(path)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,7 +269,7 @@ impl CTFontDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_from_attributes(attributes: &CFDictionary<CFString, CFType>) -> CTFontDescriptor {
|
||||
pub fn new_from_attributes(attributes: &CFDictionary) -> CTFontDescriptor {
|
||||
unsafe {
|
||||
let result: CTFontDescriptorRef =
|
||||
CTFontDescriptorCreateWithAttributes(attributes.as_concrete_TypeRef());
|
||||
|
@ -273,23 +277,15 @@ pub fn new_from_attributes(attributes: &CFDictionary<CFString, CFType>) -> CTFon
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_from_variations(variations: &CFDictionary<CFString, CFNumber>) -> CTFontDescriptor {
|
||||
pub fn new_from_variations(variations: &CFDictionary) -> CTFontDescriptor {
|
||||
unsafe {
|
||||
let var_key = CFString::wrap_under_get_rule(kCTFontVariationAttribute);
|
||||
let var_key = CFType::wrap_under_get_rule(mem::transmute(kCTFontVariationAttribute));
|
||||
let var_val = CFType::wrap_under_get_rule(variations.as_CFTypeRef());
|
||||
let attributes = CFDictionary::from_CFType_pairs(&[(var_key, var_val)]);
|
||||
new_from_attributes(&attributes)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_postscript_name(name: &CFString) -> CTFontDescriptor {
|
||||
unsafe {
|
||||
let result: CTFontDescriptorRef =
|
||||
CTFontDescriptorCreateWithNameAndSize(name.as_concrete_TypeRef(), 0.0);
|
||||
CTFontDescriptor::wrap_under_create_rule(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_descriptor(desc: &CTFontDescriptor) {
|
||||
println!("family: {}", desc.family_name());
|
||||
println!("name: {}", desc.font_name());
|
||||
|
|
Загрузка…
Ссылка в новой задаче