Put most of the define_length_type macro in a trait

This is the first step to removing the LengthHorizontal/etc. newtypes.
parent 4c4796f9
......@@ -34,14 +34,13 @@ use glib_sys;
use gobject_sys::{self, GEnumValue, GFlagsValue};
use rsvg_internals::{
rsvg_log, set_gerror, DefsLookupErrorKind, Dpi, Handle, IntrinsicDimensions, LoadOptions,
LoadingError, RenderingError, RsvgDimensionData, RsvgLength, RsvgPositionData, RsvgRectangle,
RsvgSizeFunc, SizeCallback, RSVG_ERROR_FAILED, SharedImageSurface, SurfaceType,
rsvg_log, set_gerror, DefsLookupErrorKind, Dpi, Handle, IntrinsicDimensions, LengthTrait,
LoadOptions, LoadingError, RenderingError, RsvgDimensionData, RsvgLength, RsvgPositionData,
RsvgRectangle, RsvgSizeFunc, SharedImageSurface, SizeCallback, SurfaceType, RSVG_ERROR_FAILED,
};
use crate::pixbuf_utils::{empty_pixbuf, pixbuf_from_surface};
mod handle_flags {
// The following is entirely stolen from the auto-generated code
// for GBindingFlags, from gtk-rs/glib/src/gobject/auto/flags.rs
......@@ -180,10 +179,7 @@ impl BaseUrl {
fn set(&mut self, url: Url) {
let cstring = CString::new(url.as_str()).unwrap();
self.inner = Some(BaseUrlInner {
url,
cstring,
});
self.inner = Some(BaseUrlInner { url, cstring });
}
fn get(&self) -> Option<&Url> {
......@@ -191,7 +187,10 @@ impl BaseUrl {
}
fn get_ptr(&self) -> *const libc::c_char {
self.inner.as_ref().map(|b| b.cstring.as_ptr()).unwrap_or_else(|| ptr::null())
self.inner
.as_ref()
.map(|b| b.cstring.as_ptr())
.unwrap_or_else(|| ptr::null())
}
}
......@@ -520,16 +519,16 @@ impl CHandle {
*state = LoadState::Loading {
buffer: Vec::from(buf),
}
},
}
LoadState::Loading { ref mut buffer } => {
buffer.extend_from_slice(buf);
},
}
_ => {
rsvg_g_critical("Handle must not be closed in order to write to it");
return;
},
}
}
}
......@@ -664,13 +663,7 @@ impl CHandle {
let handle = self.get_handle_ref()?;
let inner = self.inner.borrow();
handle
.render_cairo_sub(
cr,
id,
inner.dpi,
&inner.size_callback,
inner.is_testing,
)
.render_cairo_sub(cr, id, inner.dpi, &inner.size_callback, inner.is_testing)
.map_err(warn_on_invalid_id)
}
......
......@@ -97,7 +97,7 @@ use std::path::Path;
use gio::{Cancellable, FileExt};
use rsvg_internals::{Dpi, Handle, LoadOptions};
use rsvg_internals::{Dpi, Handle, LengthTrait, LoadOptions};
pub use rsvg_internals::{
DefsLookupErrorKind,
......
......@@ -13,7 +13,7 @@ use crate::dpi::Dpi;
use crate::error::{AcquireError, RenderingError};
use crate::filters;
use crate::gradient::{LinearGradient, RadialGradient};
use crate::length::Dasharray;
use crate::length::{Dasharray, LengthTrait};
use crate::limits;
use crate::mask::Mask;
use crate::node::{CascadedValues, NodeDraw, NodeType, RsvgNode};
......
......@@ -5,7 +5,7 @@ use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::drawing_ctx::DrawingCtx;
use crate::error::ValueErrorKind;
use crate::length::{LengthHorizontal, LengthUnit, LengthVertical};
use crate::length::{LengthHorizontal, LengthUnit, LengthTrait, LengthVertical};
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseError, ParseValue};
use crate::properties::ComputedValues;
......
......@@ -3,7 +3,7 @@ use cairo;
use crate::bbox::BoundingBox;
use crate::drawing_ctx::DrawingCtx;
use crate::length::{LengthHorizontal, LengthVertical};
use crate::length::{LengthHorizontal, LengthTrait, LengthVertical};
use crate::rect::IRect;
use super::context::{FilterContext, FilterInput, FilterOutput};
......
......@@ -9,7 +9,7 @@ use crate::coord_units::CoordUnits;
use crate::drawing_ctx::DrawingCtx;
use crate::error::{RenderingError, ValueErrorKind};
use crate::filter::Filter;
use crate::length::{LengthHorizontal, LengthUnit, LengthVertical};
use crate::length::{LengthHorizontal, LengthUnit, LengthTrait, LengthVertical};
use crate::node::{CascadedValues, NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::parsers::{ParseError, ParseValue};
use crate::properties::ComputedValues;
......
......@@ -2,7 +2,7 @@ use cssparser::{BasicParseError, Parser, Token};
use crate::drawing_ctx::ViewParams;
use crate::error::*;
use crate::length::{LengthBoth, LengthHorizontal, LengthUnit, POINTS_PER_INCH};
use crate::length::{LengthBoth, LengthHorizontal, LengthTrait, LengthUnit, POINTS_PER_INCH};
use crate::parsers::{Parse, ParseError};
use crate::properties::ComputedValues;
......
......@@ -8,7 +8,7 @@ use crate::bbox::BoundingBox;
use crate::drawing_ctx::{ClipMode, DrawingCtx};
use crate::error::{NodeError, RenderingError};
use crate::float_eq_cairo::ApproxEqCairo;
use crate::length::{LengthHorizontal, LengthVertical};
use crate::length::{LengthHorizontal, LengthTrait, LengthVertical};
use crate::node::*;
use crate::parsers::{ParseError, ParseValue};
use crate::property_bag::PropertyBag;
......
......@@ -78,119 +78,144 @@ pub enum LengthUnit {
Pc,
}
/// Internal type used to implement the newtypes [`LengthHorizontal`], [`LengthVertical`],
/// [`LengthBoth`].
///
/// [`LengthHorizontal`]: struct.LengthHorizontal.html
/// [`LengthVertical`]: struct.LengthVertical.html
/// [`LengthBoth`]: struct.LengthBoth.html
#[derive(Debug, PartialEq, Copy, Clone)]
enum LengthDir {
Horizontal,
Vertical,
Both,
}
impl LengthDir {
pub trait Orientation {
/// Computes a direction-based scaling factor.
///
/// This is so that `LengthDir::Both` will use the "normalized
/// diagonal length" of the current viewport, per
/// https://www.w3.org/TR/SVG/coords.html#Units
fn scaling_factor(self, x: f64, y: f64) -> f64 {
match self {
LengthDir::Horizontal => x,
LengthDir::Vertical => y,
LengthDir::Both => viewport_percentage(x, y),
}
fn scaling_factor(x: f64, y: f64) -> f64;
}
pub struct Horizontal;
pub struct Vertical;
pub struct Both;
impl Orientation for Horizontal {
#[inline]
fn scaling_factor(x: f64, _y: f64) -> f64 {
x
}
}
macro_rules! define_length_type {
{$(#[$docs:meta])* $name:ident, $dir:expr} => {
$(#[$docs])*
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct $name(Length);
impl Orientation for Vertical {
#[inline]
fn scaling_factor(_x: f64, y: f64) -> f64 {
y
}
}
impl $name {
pub fn new(length: f64, unit: LengthUnit) -> Self {
$name(Length::new(length, unit))
}
impl Orientation for Both {
#[inline]
fn scaling_factor(x: f64, y: f64) -> f64 {
viewport_percentage(x, y)
}
}
pub fn length(&self) -> f64 {
self.0.length
pub trait LengthTrait: Sized {
type Orientation: Orientation;
/// Getter for the `length` field
fn length(&self) -> f64;
/// Getter for the `unit` field
fn unit(&self) -> LengthUnit;
/// Extracts the interior [`Length`].
///
/// [`Length`]: struct.Length.html
fn to_length(&self) -> Length;
/// Returns `self` if the length is >= 0, or an error.
///
/// See the documentation for [`from_cssparser`] for an example.
///
/// [`from_cssparser`]: #method.from_cssparser
fn check_nonnegative(self) -> Result<Self, ValueErrorKind> {
if self.length() >= 0.0 {
Ok(self)
} else {
Err(ValueErrorKind::Value(
"value must be non-negative".to_string(),
))
}
}
/// Normalizes a specified length into a used value.
///
/// Lengths may come with non-pixel units, and when rendering, they need to be
/// normalized to pixels based on the current viewport (e.g. for lengths with
/// percent units), and on the current element's set of `ComputedValues` (e.g. for
/// lengths with `Em` units that need to be resolved against the current font
/// size).
fn normalize(&self, values: &ComputedValues, params: &ViewParams) -> f64 {
match self.unit() {
LengthUnit::Px => self.length(),
LengthUnit::Percent => {
self.length()
* <Self::Orientation>::scaling_factor(
params.view_box_width,
params.view_box_height,
)
}
pub fn unit(&self) -> LengthUnit {
self.0.unit
LengthUnit::Em => self.length() * font_size_from_values(values, params),
LengthUnit::Ex => self.length() * font_size_from_values(values, params) / 2.0,
LengthUnit::In => {
self.length() * <Self::Orientation>::scaling_factor(params.dpi_x, params.dpi_y)
}
/// Extracts the interior [`Length`].
///
/// [`Length`]: struct.Length.html
pub fn to_length(&self) -> Length {
self.0
LengthUnit::Cm => {
self.length() * <Self::Orientation>::scaling_factor(params.dpi_x, params.dpi_y)
/ CM_PER_INCH
}
/// Returns `self` if the length is >= 0, or an error.
///
/// See the documentation for [`from_cssparser`] for an example.
///
/// [`from_cssparser`]: #method.from_cssparser
pub fn check_nonnegative(self) -> Result<Self, ValueErrorKind> {
if self.length() >= 0.0 {
Ok(self)
} else {
Err(ValueErrorKind::Value(
"value must be non-negative".to_string(),
))
}
LengthUnit::Mm => {
self.length() * <Self::Orientation>::scaling_factor(params.dpi_x, params.dpi_y)
/ MM_PER_INCH
}
/// Normalizes a specified length into a used value.
///
/// Lengths may come with non-pixel units, and when rendering, they need to be
/// normalized to pixels based on the current viewport (e.g. for lengths with
/// percent units), and on the current element's set of `ComputedValues` (e.g. for
/// lengths with `Em` units that need to be resolved against the current font
/// size).
pub fn normalize(&self, values: &ComputedValues, params: &ViewParams) -> f64 {
match self.unit() {
LengthUnit::Px => self.length(),
LengthUnit::Percent => {
self.length()
* $dir.scaling_factor(params.view_box_width, params.view_box_height)
}
LengthUnit::Pt => {
self.length() * <Self::Orientation>::scaling_factor(params.dpi_x, params.dpi_y)
/ POINTS_PER_INCH
}
LengthUnit::Em => self.length() * font_size_from_values(values, params),
LengthUnit::Pc => {
self.length() * <Self::Orientation>::scaling_factor(params.dpi_x, params.dpi_y)
/ PICA_PER_INCH
}
}
}
}
LengthUnit::Ex => self.length() * font_size_from_values(values, params) / 2.0,
macro_rules! define_length_type {
{$(#[$docs:meta])* $name:ident, $orient:ty} => {
$(#[$docs])*
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct $name(Length);
LengthUnit::In => {
self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
}
impl LengthTrait for $name {
type Orientation = $orient;
LengthUnit::Cm => {
self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
/ CM_PER_INCH
}
fn length(&self) -> f64 {
self.0.length
}
LengthUnit::Mm => {
self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
/ MM_PER_INCH
}
fn unit(&self) -> LengthUnit {
self.0.unit
}
LengthUnit::Pt => {
self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
/ POINTS_PER_INCH
}
fn to_length(&self) -> Length {
self.0
}
}
LengthUnit::Pc => {
self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
/ PICA_PER_INCH
}
}
impl $name {
pub fn new(length: f64, unit: LengthUnit) -> Self {
$name(Length::new(length, unit))
}
/// Parses a LENGTH from a `Parser`.
......@@ -232,7 +257,7 @@ define_length_type! {
/// When this is specified as a percent value, it will get normalized
/// against the current viewport's width.
LengthHorizontal, LengthDir::Horizontal
LengthHorizontal, Horizontal
}
define_length_type! {
......@@ -240,7 +265,7 @@ define_length_type! {
///
/// When this is specified as a percent value, it will get normalized
/// against the current viewport's height.
LengthVertical, LengthDir::Vertical
LengthVertical, Vertical
}
define_length_type! {
......@@ -249,7 +274,7 @@ define_length_type! {
/// When this is specified as a percent value, it will get normalized
/// against the current viewport's width and height.
LengthBoth, LengthDir::Both
LengthBoth, Both
}
/// A CSS length value.
......@@ -404,19 +429,19 @@ fn font_size_from_values(values: &ComputedValues, params: &ViewParams) -> f64 {
// This is the same default as used in Svg::get_size()
LengthUnit::Ex => v.length * 12.0 / 2.0,
// FontSize always is a LengthDir::Both, per properties.rs
LengthUnit::In => v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y),
// FontSize always is a Both, per properties.rs
LengthUnit::In => v.length * Both::scaling_factor(params.dpi_x, params.dpi_y),
LengthUnit::Cm => {
v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / CM_PER_INCH
v.length * Both::scaling_factor(params.dpi_x, params.dpi_y) / CM_PER_INCH
}
LengthUnit::Mm => {
v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / MM_PER_INCH
v.length * Both::scaling_factor(params.dpi_x, params.dpi_y) / MM_PER_INCH
}
LengthUnit::Pt => {
v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / POINTS_PER_INCH
v.length * Both::scaling_factor(params.dpi_x, params.dpi_y) / POINTS_PER_INCH
}
LengthUnit::Pc => {
v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / PICA_PER_INCH
v.length * Both::scaling_factor(params.dpi_x, params.dpi_y) / PICA_PER_INCH
}
}
}
......
......@@ -55,7 +55,7 @@ pub use crate::handle::{
Handle, LoadOptions, RsvgDimensionData, RsvgPositionData, RsvgSizeFunc, SizeCallback,
};
pub use crate::length::{Length, LengthUnit, RsvgLength};
pub use crate::length::{Length, LengthUnit, LengthTrait, RsvgLength};
pub use crate::rect::IRect;
......
......@@ -13,7 +13,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::float_eq_cairo::ApproxEqCairo;
use crate::iri::IRI;
use crate::length::{LengthHorizontal, LengthVertical};
use crate::length::{LengthHorizontal, LengthTrait, LengthVertical};
use crate::node::*;
use crate::parsers::{Parse, ParseError, ParseValue};
use crate::path_builder::*;
......
......@@ -5,7 +5,7 @@ use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::drawing_ctx::{CompositingAffines, DrawingCtx};
use crate::error::RenderingError;
use crate::length::{LengthHorizontal, LengthVertical};
use crate::length::{LengthHorizontal, LengthTrait, LengthVertical};
use crate::node::{CascadedValues, NodeDraw, NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
use crate::property_bag::PropertyBag;
......
......@@ -3,7 +3,7 @@ use cssparser::{self, Parser, Token};
use crate::error::*;
use crate::font_props::{FontSizeSpec, FontWeightSpec, LetterSpacingSpec, SingleFontFamily};
use crate::iri::IRI;
use crate::length::{Dasharray, LengthBoth, LengthUnit};
use crate::length::{Dasharray, LengthBoth, LengthTrait, LengthUnit};
use crate::paint_server::PaintServer;
use crate::parsers::{Parse, ParseError};
use crate::properties::ComputedValues;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment