Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  svg.rs   Sprache: unbekannt

 
use std::fmt;

/// `rgb({r},{g},{b})`
#[derive(Copy, Clone, PartialEq)]
pub struct Color {
    pub r: u8,
    pub g: u8,
    pub b: u8,
}

impl fmt::Display for Color {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "rgb({},{},{})", self.r, self.g, self.b)
    }
}

pub fn rgb(r: u8, g: u8, b: u8) -> Color { Color { r, g, b } }
pub fn black() -> Color { rgb(0, 0, 0) }
pub fn white() -> Color { rgb(255, 255, 255) }
pub fn red() -> Color { rgb(255, 0, 0) }
pub fn green() -> Color { rgb(0, 255, 0) }
pub fn blue() -> Color { rgb(0, 0, 255) }

/// `fill:{self}`
#[derive(Copy, Clone, PartialEq)]
pub enum Fill {
    Color(Color),
    None,
}

/// `stroke:{self}`
#[derive(Copy, Clone, PartialEq)]
pub enum Stroke {
    Color(Color, f32),
    None,
}

/// `fill:{fill};stroke:{stroke};fill-opacity:{opacity};`
#[derive(Copy, Clone, PartialEq)]
pub struct Style {
    pub fill: Fill,
    pub stroke: Stroke,
    pub opacity: f32,
    pub stroke_opacity: f32,
}

impl fmt::Display for Style {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{};{};fill-opacity:{};stroke-opacity:{};",
            self.fill,
            self.stroke,
            self.opacity,
            self.stroke_opacity,
        )
    }
}

impl Style {
    pub fn default() -> Self {
        Style {
            fill: Fill::Color(black()),
            stroke: Stroke::None,
            opacity: 1.0,
            stroke_opacity: 1.0,
        }
    }
}

impl fmt::Display for Fill {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Fill::Color(color) => write!(f, "fill:{}", color),
            Fill::None => write!(f, "fill:none"),
        }
    }
}

impl fmt::Display for Stroke {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Stroke::Color(color, radius) => write!(f, "stroke:{};stroke-width:{}", color, radius),
            Stroke::None => write!(f, "stroke:none"),
        }
    }
}

impl Into<Fill> for Color {
    fn into(self) -> Fill {
        Fill::Color(self)
    }
}

impl Into<Stroke> for Color {
    fn into(self) -> Stroke {
        Stroke::Color(self, 1.0)
    }
}

/// `<rect x="{x}" y="{y}" width="{w}" height="{h}" ... />`,
#[derive(Copy, Clone, PartialEq)]
pub struct Rectangle {
    pub x: f32,
    pub y: f32,
    pub w: f32,
    pub h: f32,
    pub style: Style,
    pub border_radius: f32,
}

pub fn rectangle(x: f32, y: f32, w: f32, h: f32) -> Rectangle {
    Rectangle {
        x, y, w, h,
        style: Style::default(),
        border_radius: 0.0,
    }
}

impl Rectangle {
    pub fn fill<F>(mut self, fill: F) -> Self
    where F: Into<Fill> {
        self.style.fill = fill.into();
        self
    }

    pub fn stroke<S>(mut self, stroke: S) -> Self
    where S: Into<Stroke> {
        self.style.stroke = stroke.into();
        self
    }

    pub fn opacity(mut self, opacity: f32) -> Self {
        self.style.opacity = opacity;
        self
    }

    pub fn stroke_opacity(mut self, opacity: f32) -> Self {
        self.style.stroke_opacity = opacity;
        self
    }

    pub fn style(mut self, style: Style) -> Self {
        self.style = style;
        self
    }

    pub fn border_radius(mut self, r: f32) -> Self {
        self.border_radius = r;
        self
    }

    pub fn offset(mut self, dx: f32, dy: f32) -> Self {
        self.x += dx;
        self.y += dy;
        self
    }

    pub fn inflate(mut self, dx: f32, dy: f32) -> Self {
        self.x -= dx;
        self.y -= dy;
        self.w += 2.0 * dx;
        self.h += 2.0 * dy;
        self
    }
}

impl fmt::Display for Rectangle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            r#"<rect x="{}" y="{}" width="{}" height="{}" ry="{}" style="{}" />""#,
            self.x, self.y, self.w, self.h,
            self.border_radius,
            self.style,
        )
    }
}

/// `<circle cx="{x}" cy="{y}" r="{radius}" .../>`
#[derive(Copy, Clone, PartialEq)]
pub struct Circle {
    pub x: f32,
    pub y: f32,
    pub radius: f32,
    pub style: Style,
}

impl Circle {
    pub fn fill<F>(mut self, fill: F) -> Self
    where F: Into<Fill> {
        self.style.fill = fill.into();
        self
    }

    pub fn stroke<S>(mut self, stroke: S) -> Self
    where S: Into<Stroke> {
        self.style.stroke = stroke.into();
        self
    }

    pub fn style(mut self, style: Style) -> Self {
        self.style = style;
        self
    }

    pub fn opacity(mut self, opacity: f32) -> Self {
        self.style.opacity = opacity;
        self
    }

    pub fn stroke_opacity(mut self, opacity: f32) -> Self {
        self.style.stroke_opacity = opacity;
        self
    }

    pub fn offset(mut self, dx: f32, dy: f32) -> Self {
        self.x += dx;
        self.y += dy;
        self
    }

    pub fn inflate(mut self, by: f32) -> Self {
        self.radius += by;
        self
    }
}

impl fmt::Display for Circle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            r#"<circle cx="{}" cy="{}" r="{}" style="{}" />""#,
            self.x, self.y, self.radius,
            self.style,
        )
    }
}

/// `<path d="..." style="..."/>`
#[derive(Clone, PartialEq)]
pub struct Polygon {
    pub points: Vec<[f32; 2]>,
    pub closed: bool,
    pub style: Style,
}

impl fmt::Display for Polygon {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, r#"<path d="#)?;
        if self.points.len() > 0 {
            write!(f, "M {} {} ", self.points[0][0], self.points[0][1])?;
            for &p in &self.points[1..] {
                write!(f, "L {} {} ", p[0], p[1])?;
            }
            if self.closed {
                write!(f, "Z")?;
            }
        }
        write!(f, r#"" style="{}"/>"#, self.style)
    }
}

pub fn polygon<T: Copy + Into<[f32; 2]>>(pts: &[T]) ->  Polygon {
    let mut points = Vec::with_capacity(pts.len());
    for p in pts {
        points.push((*p).into());
    }
    Polygon {
        points,
        closed: true,
        style: Style::default(),
    }
}

pub fn triangle(x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) -> Polygon {
    polygon(&[[x1, y1], [x2, y2], [x3, y3]])
}

impl Polygon {
    pub fn open(mut self) -> Self {
        self.closed = false;
        self
    }

    pub fn fill<F>(mut self, fill: F) -> Self
    where F: Into<Fill> {
        self.style.fill = fill.into();
        self
    }

    pub fn stroke<S>(mut self, stroke: S) -> Self
    where S: Into<Stroke> {
        self.style.stroke = stroke.into();
        self
    }

    pub fn opacity(mut self, opacity: f32) -> Self {
        self.style.opacity = opacity;
        self
    }

    pub fn stroke_opacity(mut self, opacity: f32) -> Self {
        self.style.stroke_opacity = opacity;
        self
    }

    pub fn style(mut self, style: Style) -> Self {
        self.style = style;
        self
    }
}

/// `<path d="M {x1} {y1} L {x2} {y2}" ... />`
#[derive(Copy, Clone, PartialEq)]
pub struct LineSegment {
    pub x1: f32,
    pub x2: f32,
    pub y1: f32,
    pub y2: f32,
    pub color: Color,
    pub width: f32,
}

impl fmt::Display for LineSegment {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            r#"<path d="M {} {} L {} {}" style="stroke:{};stroke-width:{}"/>"#,
            self.x1, self.y1,
            self.x2, self.y2,
            self.color,
            self.width,
        )
    }
}

pub fn line_segment(x1: f32, y1: f32, x2: f32, y2: f32) -> LineSegment {
    LineSegment {
        x1, y1, x2, y2,
        color: black(),
        width: 1.0,
    }
}

impl LineSegment {
    pub fn color(mut self, color: Color) -> Self {
        self.color = color;
        self
    }

    pub fn width(mut self, width: f32) -> Self {
        self.width = width;
        self
    }

    pub fn offset(mut self, dx: f32, dy: f32) -> Self {
        self.x1 += dx;
        self.y1 += dy;
        self.x2 += dx;
        self.y2 += dy;
        self
    }
}

/// `<path d="..." />`
#[derive(Clone, PartialEq)]
pub struct Path {
    pub ops: Vec<PathOp>,
    pub style: Style,
}

/// `M {} {} L {} {} ...`
#[derive(Copy, Clone, PartialEq)]
pub enum PathOp {
    MoveTo { x: f32, y: f32 },
    LineTo { x: f32, y: f32 },
    QuadraticTo { ctrl_x: f32, ctrl_y: f32, x: f32, y: f32 },
    CubicTo { ctrl1_x: f32, ctrl1_y: f32, ctrl2_x: f32, ctrl2_y: f32, x: f32, y: f32 },
    Close,
}
impl fmt::Display for PathOp {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            PathOp::MoveTo { x, y } => write!(f, "M {} {} ", x, y),
            PathOp::LineTo { x, y } => write!(f, "L {} {} ", x, y),
            PathOp::QuadraticTo { ctrl_x, ctrl_y, x, y } => write!(f, "Q {} {} {} {} ", ctrl_x, ctrl_y, x, y),
            PathOp::CubicTo { ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, x, y } => write!(f, "C {} {} {} {} {} {} ", ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, x, y),
            PathOp::Close => write!(f, "Z "),
        }
    }
}

impl fmt::Display for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, r#"<path d=""#)?;
        for op in &self.ops {
            op.fmt(f)?;
        }
        write!(f, r#"" style="{}" />"#, self.style)
    }
}

impl Path {
    pub fn move_to(mut self, x: f32, y: f32) -> Self {
        self.ops.push(PathOp::MoveTo { x, y });
        self
    }

    pub fn line_to(mut self, x: f32, y: f32) -> Self {
        self.ops.push(PathOp::LineTo { x, y });
        self
    }

    pub fn quadratic_bezier_to(
        mut self,
        ctrl_x: f32, ctrl_y: f32,
        x: f32, y: f32,
    ) -> Self {
        self.ops.push(PathOp::QuadraticTo { ctrl_x, ctrl_y, x, y });
        self
    }

    pub fn cubic_bezier_to(
        mut self,
        ctrl1_x: f32, ctrl1_y: f32,
        ctrl2_x: f32, ctrl2_y: f32,
        x: f32, y: f32,
    ) -> Self {
        self.ops.push(PathOp::CubicTo { ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, x, y });
        self
    }

    pub fn close(mut self) -> Self {
        self.ops.push(PathOp::Close);
        self
    }

    pub fn fill<F>(mut self, fill: F) -> Self
    where F: Into<Fill> {
        self.style.fill = fill.into();
        self
    }

    pub fn stroke<S>(mut self, stroke: S) -> Self
    where S: Into<Stroke> {
        self.style.stroke = stroke.into();
        self
    }

    pub fn opacity(mut self, opacity: f32) -> Self {
        self.style.opacity = opacity;
        self
    }

    pub fn stroke_opacity(mut self, opacity: f32) -> Self {
        self.style.stroke_opacity = opacity;
        self
    }

    pub fn style(mut self, style: Style) -> Self {
        self.style = style;
        self
    }
}

pub fn path() -> Path {
    Path {
        ops: Vec::new(),
        style: Style::default(),
    }
}

/// `<text x="{x}" y="{y}" ... > {text} </text>`
#[derive(Clone, PartialEq)]
pub struct Text {
    pub x: f32, pub y: f32,
    pub text: String,
    pub color: Color,
    pub align: Align,
    pub size: f32,
}

impl fmt::Display for Text {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            r#"<text x="{}" y="{}" style="font-size:{}px;fill:{};{}"> {} </text>"#,
            self.x, self.y,
            self.size,
            self.color,
            self.align,
            self.text,
        )
    }
}

pub fn text<T: Into<String>>(x: f32, y: f32, txt: T) -> Text {
    Text {
        x, y,
        text: txt.into(),
        color: black(),
        align: Align::Left,
        size: 10.0,
    }
}

impl Text {
    pub fn color(mut self, color: Color) -> Self {
        self.color = color;
        self
    }

    pub fn size(mut self, size: f32) -> Self {
        self.size = size;
        self
    }

    pub fn align(mut self, align: Align) -> Self {
        self.align = align;
        self
    }

    pub fn offset(mut self, dx: f32, dy: f32) -> Self {
        self.x += dx;
        self.y += dy;
        self
    }
}

pub struct Comment {
    pub text: String,
}

pub fn comment<T: Into<String>>(text: T) -> Comment {
    Comment {
        text: text.into()
    }
}

impl fmt::Display for Comment {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<!-- {} -->", self.text)
    }
}

/// `text-align:{self}`
#[derive(Copy, Clone, PartialEq)]
pub enum Align {
    Left, Right, Center
}

impl fmt::Display for Align {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Align::Left => write!(f, "text-anchor:start;text-align:left;"),
            Align::Right => write!(f, "text-anchor:end;text-align:right;"),
            Align::Center => write!(f, "text-anchor:middle;text-align:center;"),
        }
    }
}

/// `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {y}">`
#[derive(Copy, Clone, PartialEq)]
pub struct BeginSvg {
    pub w: f32,
    pub h: f32,
}

impl fmt::Display for BeginSvg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {} {}">"#,
            self.w,
            self.h,
        )
    }
}


/// `</svg>`
#[derive(Copy, Clone, PartialEq)]
pub struct EndSvg;

impl fmt::Display for EndSvg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "</svg>")
    }
}

/// `"    "`
pub struct Indentation {
    pub n: u32,
}

pub fn indent(n: u32) -> Indentation {
    Indentation { n }
}

impl Indentation {
    pub fn push(&mut self) {
        self.n += 1;
    }

    pub fn pop(&mut self) {
        self.n -= 1;
    }
}

impl fmt::Display for Indentation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for _ in 0..self.n {
            write!(f, "    ")?;
        }
        Ok(())
    }
}

#[test]
fn foo() {
    println!("{}", BeginSvg { w: 800.0, h: 600.0 });
    println!("    {}",
        rectangle(20.0, 50.0, 200.0, 100.0)
            .fill(red())
            .stroke(Stroke::Color(black(), 3.0))
            .border_radius(5.0)
    );
    println!("    {}", text(25.0, 100.0, "Foo!").size(42.0).color(white()));
    println!("{}", EndSvg);
}

[ Dauer der Verarbeitung: 0.26 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge