Initial import of plotters-backend-0.2.1.

Bug: 155309706
Change-Id: I89e5308bd8288caa03009dd6b00676a0a90f886f
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..ac3edff
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "f18b6658db651d8b4be26f12edffb80186c4da83"
+  }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0f28dff
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+/target
+**/*.rs.bk
+Cargo.lock
+.*.sw*
+backup/*
+**/Cargo.lock
+**/target
+examples/wasm-demo/www/pkg
+examples/.ipynb_checkpoints/
+tarpaulin-report.html
+.vscode/*
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..0cdc7e3
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,24 @@
+# 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]
+edition = "2018"
+name = "plotters-backend"
+version = "0.2.1"
+authors = ["Hao Hou <[email protected]>"]
+description = "Plotters Backend API"
+homepage = "https://plotters-rs.github.io"
+readme = "README.md"
+license = "MIT"
+repository = "https://github.com/plotters-rs/plotters-backend"
+
+[dependencies]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..58c12be
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,14 @@
+[package]
+name = "plotters-backend"
+version = "0.2.1"
+authors = ["Hao Hou <[email protected]>"]
+edition = "2018"
+license = "MIT"
+description = "Plotters Backend API"
+homepage = "https://plotters-rs.github.io"
+repository = "https://github.com/plotters-rs/plotters-backend"
+readme = "README.md"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..dc7720b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# plotters-backend - The base crate for implementing a backend for Plotters
+
+This is a part of plotters project. For more details, please check the following links:
+
+- For high-level intro of Plotters, see: [Plotters on crates.io](https://crates.io/crates/plotters)
+- Check the main repo at [Plotters repo](https://github.com/38/plotters.git)
+- For detailed documentation about this crate, check [plotters-backend on docs.rs](https://docs.rs/plotters-backend/)
+- You can also visit Plotters [Homepage](https://plotters-rs.github.io)
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..f4a92b0
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,326 @@
+/*!
+  The Plotters backend API crate. This is a part of Plotters, the Rust drawing and plotting library, for more details regarding the entire
+  Plotters project, please check the [main crate](https://crates.io/crates/plotters).
+
+  This is the crate that used as the connector between Plotters and different backend crates. Since Plotters 0.3, all the backends has been
+  hosted as seperate crates for the usability and maintainability reasons.
+
+  At the same time, Plotters is now supporting third-party backends and all the backends are now supports "plug-and-play":
+  To use a external backend, just depends on both the Plotters main crate and the third-party backend crate.
+
+  # Notes for implementing Backend for Plotters
+
+  To create a new Plotters backend, this crate should be imported to the crate and the trait [DrawingBackend](trait.DrawingBackend.html) should
+  be implemented. It's highly recommended that the third-party backend uses `plotters-backend` by version specification `^x.y.*`.
+  For more details, see the [compatibility note](#compatibility-note).
+
+  If the backend only implements [DrawingBackend::draw_pixel](trait.DrawingBackend.html#tymethod.draw_pixel), the default CPU rasterizer will be
+  used to give your backend ability of drawing different shapes. For those backend that supports advanced drawing instructions, such as, GPU
+  acelerated shape drawing, all the provided trait method can be overriden from the specific backend code.
+
+  If your backend have text rendering ability, you may want to override the [DrawingBackend::estimate_text_size](trait.DrawingBackend.html#tymethod.estimate_text_size)
+  to avoid wrong spacing, since the Plotters default text handling code may behaves differently from the backend in terms of text rendering.
+
+  ## Animated or Realtime Rendering
+  Backend might render the image realtimely/animated, for example, a GTK backend for realtime display or a GIF image rendering. To support these
+  features, you need to play with `ensure_prepared` and `present` method. The following figure illustrates how Plotters operates a drawing backend.
+
+  - `ensure_prepared` - Called before each time when plotters want to draw. This function should initialize the backend for current frame, if the backend is already prepared
+     for a frame, this function should simply do nothing.
+  - `present` - Called when plotters want to finish current frame drawing
+
+
+  ```text
+                                        .ensure_prepared() &&
+    +-------------+    +-------------+    .draw_pixels()             +--------------+   drop
+    |Start drwaing|--->|Ready to draw| ------------------------+---->|Finish 1 frame| --------->
+    +-------------+    +-------------+                         |     +--------------+
+           ^                  ^                                |            |
+           |                  +------------------------------- +            |
+           |                            continue drawing                    |
+           +----------------------------------------------------------------+
+                                start render the next frame
+                                        .present()
+  ```
+  - For both animated and static drawing, `DrawingBackend::present` indicates current frame should be flushed.
+  - For both animated and static drawing, `DrawingBackend::ensure_prepared` is called every time when plotters need to draw.
+  - For static drawing, the `DrawingBackend::present` is only called once manually, or from the Drop impl for the backend.
+  - For dynamic drawing, frames are defined by invocation of `DrawingBackend::present`, everything prior the invocation should belongs to previous frame
+
+  # Compatibility Note
+  Since Plotters v0.3, plotters use the "plug-and-play" schema to import backends, this requires both Plotters and the backend crates depdens on a
+  same version of `plotters-backend` crate. This crate (`plotters-backend`) will enforce that any revision (means the last number in a version number)
+  won't contains breaking change - both on the Plotters side and backend side.
+
+  Plotters main crate is always importing the backend crate with version specification `plotters-backend = "^<major>.<minor>*"`.
+  It's highly recommended that all the external crates follows the same rule to import `plotters-backend` depdendency, to avoid protential breaking
+  caused by `plotters-backend` crates gets a revision update.
+
+  We also impose a versioning rule with `plotters` and some backends:
+  The compatible main crate (`plotters`) and this crate (`plotters-backend`) are always use the same major and minor version number.
+  All the plotters main crate and second-party backends with version "x.y.*" should be compatible, and they should depens on the latest version of `plotters-backend x.y.*`
+
+*/
+use std::error::Error;
+
+pub mod rasterizer;
+mod style;
+mod text;
+
+pub use style::{BackendColor, BackendStyle};
+pub use text::{text_anchor, BackendTextStyle, FontFamily, FontStyle, FontTransform};
+
+use text_anchor::{HPos, VPos};
+
+/// A coordinate in the pixel-based backend. The coordinate follows the framebuffer's convention,
+/// which defines the top-left point as (0, 0).
+pub type BackendCoord = (i32, i32);
+
+/// The error produced by a drawing backend.
+#[derive(Debug)]
+pub enum DrawingErrorKind<E: Error + Send + Sync> {
+    /// A drawing backend error
+    DrawingError(E),
+    /// A font rendering error
+    FontError(Box<dyn Error + Send + Sync + 'static>),
+}
+
+impl<E: Error + Send + Sync> std::fmt::Display for DrawingErrorKind<E> {
+    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+        match self {
+            DrawingErrorKind::DrawingError(e) => write!(fmt, "Drawing backend error: {}", e),
+            DrawingErrorKind::FontError(e) => write!(fmt, "Font loading error: {}", e),
+        }
+    }
+}
+
+impl<E: Error + Send + Sync> Error for DrawingErrorKind<E> {}
+
+///  The drawing backend trait, which implements the low-level drawing APIs.
+///  This trait has a set of default implementation. And the minimal requirement of
+///  implementing a drawing backend is implementing the `draw_pixel` function.
+///
+///  If the drawing backend supports vector graphics, the other drawing APIs should be
+///  override by the backend specific implementation. Otherwise, the default implementation
+///  will use the pixel-based approach to draw other types of low-level shapes.
+pub trait DrawingBackend: Sized {
+    /// The error type reported by the backend
+    type ErrorType: Error + Send + Sync;
+
+    /// Get the dimension of the drawing backend in pixels
+    fn get_size(&self) -> (u32, u32);
+
+    /// Ensure the backend is ready to draw
+    fn ensure_prepared(&mut self) -> Result<(), DrawingErrorKind<Self::ErrorType>>;
+
+    /// Finalize the drawing step and present all the changes.
+    /// This is used as the real-time rendering support.
+    /// The backend may implement in the following way, when `ensure_prepared` is called
+    /// it checks if it needs a fresh buffer and `present` is called rendering all the
+    /// pending changes on the screen.
+    fn present(&mut self) -> Result<(), DrawingErrorKind<Self::ErrorType>>;
+
+    /// Draw a pixel on the drawing backend
+    /// - `point`: The backend pixel-based coordinate to draw
+    /// - `color`: The color of the pixel
+    fn draw_pixel(
+        &mut self,
+        point: BackendCoord,
+        color: BackendColor,
+    ) -> Result<(), DrawingErrorKind<Self::ErrorType>>;
+
+    /// Draw a line on the drawing backend
+    /// - `from`: The start point of the line
+    /// - `to`: The end point of the line
+    /// - `style`: The style of the line
+    fn draw_line<S: BackendStyle>(
+        &mut self,
+        from: BackendCoord,
+        to: BackendCoord,
+        style: &S,
+    ) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
+        rasterizer::draw_line(self, from, to, style)
+    }
+
+    /// Draw a rectangle on the drawing backend
+    /// - `upper_left`: The coordinate of the upper-left corner of the rect
+    /// - `bottom_right`: The coordinate of the bottom-right corner of the rect
+    /// - `style`: The style
+    /// - `fill`: If the rectangle should be filled
+    fn draw_rect<S: BackendStyle>(
+        &mut self,
+        upper_left: BackendCoord,
+        bottom_right: BackendCoord,
+        style: &S,
+        fill: bool,
+    ) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
+        rasterizer::draw_rect(self, upper_left, bottom_right, style, fill)
+    }
+
+    /// Draw a path on the drawing backend
+    /// - `path`: The iterator of key points of the path
+    /// - `style`: The style of the path
+    fn draw_path<S: BackendStyle, I: IntoIterator<Item = BackendCoord>>(
+        &mut self,
+        path: I,
+        style: &S,
+    ) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
+        if style.color().alpha == 0.0 {
+            return Ok(());
+        }
+
+        if style.stroke_width() == 1 {
+            let mut begin: Option<BackendCoord> = None;
+            for end in path.into_iter() {
+                if let Some(begin) = begin {
+                    let result = self.draw_line(begin, end, style);
+                    if result.is_err() {
+                        return result;
+                    }
+                }
+                begin = Some(end);
+            }
+        } else {
+            let p: Vec<_> = path.into_iter().collect();
+            let v = rasterizer::polygonize(&p[..], style.stroke_width());
+            return self.fill_polygon(v, &style.color());
+        }
+        Ok(())
+    }
+
+    /// Draw a circle on the drawing backend
+    /// - `center`: The center coordinate of the circle
+    /// - `radius`: The radius of the circle
+    /// - `style`: The style of the shape
+    /// - `fill`: If the circle should be filled
+    fn draw_circle<S: BackendStyle>(
+        &mut self,
+        center: BackendCoord,
+        radius: u32,
+        style: &S,
+        fill: bool,
+    ) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
+        rasterizer::draw_circle(self, center, radius, style, fill)
+    }
+
+    fn fill_polygon<S: BackendStyle, I: IntoIterator<Item = BackendCoord>>(
+        &mut self,
+        vert: I,
+        style: &S,
+    ) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
+        let vert_buf: Vec<_> = vert.into_iter().collect();
+
+        rasterizer::fill_polygon(self, &vert_buf[..], style)
+    }
+
+    /// Draw a text on the drawing backend
+    /// - `text`: The text to draw
+    /// - `style`: The text style
+    /// - `pos` : The text anchor point
+    fn draw_text<TStyle: BackendTextStyle>(
+        &mut self,
+        text: &str,
+        style: &TStyle,
+        pos: BackendCoord,
+    ) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
+        let color = style.color();
+        if color.alpha == 0.0 {
+            return Ok(());
+        }
+
+        let layout = style
+            .layout_box(text)
+            .map_err(|e| DrawingErrorKind::FontError(Box::new(e)))?;
+        let ((min_x, min_y), (max_x, max_y)) = layout;
+        let width = (max_x - min_x) as i32;
+        let height = (max_y - min_y) as i32;
+        let dx = match style.anchor().h_pos {
+            HPos::Left => 0,
+            HPos::Right => -width,
+            HPos::Center => -width / 2,
+        };
+        let dy = match style.anchor().v_pos {
+            VPos::Top => 0,
+            VPos::Center => -height / 2,
+            VPos::Bottom => -height,
+        };
+        let trans = style.transform();
+        let (w, h) = self.get_size();
+        match style.draw(text, (0, 0), |x, y, color| {
+            let (x, y) = trans.transform(x + dx - min_x, y + dy - min_y);
+            let (x, y) = (pos.0 + x, pos.1 + y);
+            if x >= 0 && x < w as i32 && y >= 0 && y < h as i32 {
+                self.draw_pixel((x, y), color)
+            } else {
+                Ok(())
+            }
+        }) {
+            Ok(drawing_result) => drawing_result,
+            Err(font_error) => Err(DrawingErrorKind::FontError(Box::new(font_error))),
+        }
+    }
+
+    /// Estimate the size of the horizontal text if rendered on this backend.
+    /// This is important because some of the backend may not have font ability.
+    /// Thus this allows those backend reports proper value rather than ask the
+    /// font rasterizer for that.
+    ///
+    /// - `text`: The text to estimate
+    /// - `font`: The font to estimate
+    /// - *Returns* The estimated text size
+    fn estimate_text_size<TStyle: BackendTextStyle>(
+        &self,
+        text: &str,
+        style: &TStyle,
+    ) -> Result<(u32, u32), DrawingErrorKind<Self::ErrorType>> {
+        let layout = style
+            .layout_box(text)
+            .map_err(|e| DrawingErrorKind::FontError(Box::new(e)))?;
+        Ok((
+            ((layout.1).0 - (layout.0).0) as u32,
+            ((layout.1).1 - (layout.0).1) as u32,
+        ))
+    }
+
+    /// Blit a bitmap on to the backend.
+    ///
+    /// - `text`: pos the left upper conner of the bitmap to blit
+    /// - `src`: The source of the image
+    ///
+    /// TODO: The default implementation of bitmap blitting assumes that the bitmap is RGB, but
+    /// this may not be the case. But for bitmap backend it's actually ok if we use the bitmap
+    /// element that matches the pixel format, but we need to fix this.
+    fn blit_bitmap<'a>(
+        &mut self,
+        pos: BackendCoord,
+        (iw, ih): (u32, u32),
+        src: &'a [u8],
+    ) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
+        let (w, h) = self.get_size();
+
+        for dx in 0..iw {
+            if pos.0 + dx as i32 >= w as i32 {
+                break;
+            }
+            for dy in 0..ih {
+                if pos.1 + dy as i32 >= h as i32 {
+                    break;
+                }
+                // FIXME: This assume we have RGB image buffer
+                let r = src[(dx + dy * w) as usize * 3];
+                let g = src[(dx + dy * w) as usize * 3 + 1];
+                let b = src[(dx + dy * w) as usize * 3 + 2];
+                let color = BackendColor {
+                    alpha: 1.0,
+                    rgb: (r, g, b),
+                };
+                let result = self.draw_pixel((pos.0 + dx as i32, pos.1 + dy as i32), color);
+                if result.is_err() {
+                    return result;
+                }
+            }
+        }
+
+        Ok(())
+    }
+}
diff --git a/src/rasterizer/circle.rs b/src/rasterizer/circle.rs
new file mode 100644
index 0000000..779f095
--- /dev/null
+++ b/src/rasterizer/circle.rs
@@ -0,0 +1,342 @@
+use crate::{BackendCoord, BackendStyle, DrawingBackend, DrawingErrorKind};
+
+fn draw_part_a<
+    B: DrawingBackend,
+    Draw: FnMut(i32, (f64, f64)) -> Result<(), DrawingErrorKind<B::ErrorType>>,
+>(
+    height: f64,
+    radius: u32,
+    mut draw: Draw,
+) -> Result<(), DrawingErrorKind<B::ErrorType>> {
+    let half_width = (radius as f64 * radius as f64
+        - (radius as f64 - height) * (radius as f64 - height))
+        .sqrt();
+
+    let x0 = (-half_width).ceil() as i32;
+    let x1 = half_width.floor() as i32;
+
+    let y0 = (radius as f64 - height).ceil();
+
+    for x in x0..=x1 {
+        let y1 = (radius as f64 * radius as f64 - x as f64 * x as f64).sqrt();
+        check_result!(draw(x, (y0, y1)));
+    }
+
+    Ok(())
+}
+
+fn draw_part_b<
+    B: DrawingBackend,
+    Draw: FnMut(i32, (f64, f64)) -> Result<(), DrawingErrorKind<B::ErrorType>>,
+>(
+    from: f64,
+    size: f64,
+    mut draw: Draw,
+) -> Result<(), DrawingErrorKind<B::ErrorType>> {
+    let from = from.floor();
+    for x in (from - size).floor() as i32..=from as i32 {
+        check_result!(draw(x, (-x as f64, x as f64)));
+    }
+    Ok(())
+}
+
+fn draw_part_c<
+    B: DrawingBackend,
+    Draw: FnMut(i32, (f64, f64)) -> Result<(), DrawingErrorKind<B::ErrorType>>,
+>(
+    r: i32,
+    r_limit: i32,
+    mut draw: Draw,
+) -> Result<(), DrawingErrorKind<B::ErrorType>> {
+    let half_size = r as f64 / (2f64).sqrt();
+
+    let (x0, x1) = ((-half_size).ceil() as i32, half_size.floor() as i32);
+
+    for x in x0..x1 {
+        let outter_y0 = ((r_limit as f64) * (r_limit as f64) - x as f64 * x as f64).sqrt();
+        let inner_y0 = r as f64 - 1.0;
+        let mut y1 = outter_y0.min(inner_y0);
+        let y0 = ((r as f64) * (r as f64) - x as f64 * x as f64).sqrt();
+
+        if y0 > y1 {
+            y1 = y0.ceil();
+            if y1 >= r as f64 {
+                continue;
+            }
+        }
+
+        check_result!(draw(x, (y0, y1)));
+    }
+
+    for x in x1 + 1..r {
+        let outter_y0 = ((r_limit as f64) * (r_limit as f64) - x as f64 * x as f64).sqrt();
+        let inner_y0 = r as f64 - 1.0;
+        let y0 = outter_y0.min(inner_y0);
+        let y1 = x as f64;
+
+        if y1 < y0 {
+            check_result!(draw(x, (y0, y1 + 1.0)));
+            check_result!(draw(-x, (y0, y1 + 1.0)));
+        }
+    }
+
+    Ok(())
+}
+
+fn draw_sweep_line<B: DrawingBackend, S: BackendStyle>(
+    b: &mut B,
+    style: &S,
+    (x0, y0): BackendCoord,
+    (dx, dy): (i32, i32),
+    p0: i32,
+    (s, e): (f64, f64),
+) -> Result<(), DrawingErrorKind<B::ErrorType>> {
+    let mut s = if dx < 0 || dy < 0 { -s } else { s };
+    let mut e = if dx < 0 || dy < 0 { -e } else { e };
+    if s > e {
+        std::mem::swap(&mut s, &mut e);
+    }
+
+    let vs = s.ceil() - s;
+    let ve = e - e.floor();
+
+    if dx == 0 {
+        check_result!(b.draw_line(
+            (p0 + x0, s.ceil() as i32 + y0),
+            (p0 + x0, e.floor() as i32 + y0),
+            &style.color()
+        ));
+        check_result!(b.draw_pixel((p0 + x0, s.ceil() as i32 + y0 - 1), style.color().mix(vs)));
+        check_result!(b.draw_pixel((p0 + x0, e.floor() as i32 + y0 + 1), style.color().mix(ve)));
+    } else {
+        check_result!(b.draw_line(
+            (s.ceil() as i32 + x0, p0 + y0),
+            (e.floor() as i32 + x0, p0 + y0),
+            &style.color()
+        ));
+        check_result!(b.draw_pixel((s.ceil() as i32 + x0 - 1, p0 + y0), style.color().mix(vs)));
+        check_result!(b.draw_pixel((e.floor() as i32 + x0 + 1, p0 + y0), style.color().mix(ve)));
+    }
+
+    Ok(())
+}
+
+fn draw_annulus<B: DrawingBackend, S: BackendStyle>(
+    b: &mut B,
+    center: BackendCoord,
+    radius: (u32, u32),
+    style: &S,
+) -> Result<(), DrawingErrorKind<B::ErrorType>> {
+    let a0 = ((radius.0 - radius.1) as f64).min(radius.0 as f64 * (1.0 - 1.0 / (2f64).sqrt()));
+    let a1 = (radius.0 as f64 - a0 - radius.1 as f64).max(0.0);
+
+    check_result!(draw_part_a::<B, _>(a0, radius.0, |p, r| draw_sweep_line(
+        b,
+        style,
+        center,
+        (0, 1),
+        p,
+        r
+    )));
+    check_result!(draw_part_a::<B, _>(a0, radius.0, |p, r| draw_sweep_line(
+        b,
+        style,
+        center,
+        (0, -1),
+        p,
+        r
+    )));
+    check_result!(draw_part_a::<B, _>(a0, radius.0, |p, r| draw_sweep_line(
+        b,
+        style,
+        center,
+        (1, 0),
+        p,
+        r
+    )));
+    check_result!(draw_part_a::<B, _>(a0, radius.0, |p, r| draw_sweep_line(
+        b,
+        style,
+        center,
+        (-1, 0),
+        p,
+        r
+    )));
+
+    if a1 > 0.0 {
+        check_result!(draw_part_b::<B, _>(
+            radius.0 as f64 - a0,
+            a1.floor(),
+            |h, (f, t)| {
+                let h = h as i32;
+                let f = f as i32;
+                let t = t as i32;
+                check_result!(b.draw_line(
+                    (center.0 + h, center.1 + f),
+                    (center.0 + h, center.1 + t),
+                    &style.color()
+                ));
+                check_result!(b.draw_line(
+                    (center.0 - h, center.1 + f),
+                    (center.0 - h, center.1 + t),
+                    &style.color()
+                ));
+
+                check_result!(b.draw_line(
+                    (center.0 + f + 1, center.1 + h),
+                    (center.0 + t - 1, center.1 + h),
+                    &style.color()
+                ));
+                check_result!(b.draw_line(
+                    (center.0 + f + 1, center.1 - h),
+                    (center.0 + t - 1, center.1 - h),
+                    &style.color()
+                ));
+
+                Ok(())
+            }
+        ));
+    }
+
+    check_result!(draw_part_c::<B, _>(
+        radius.1 as i32,
+        radius.0 as i32,
+        |p, r| draw_sweep_line(b, style, center, (0, 1), p, r)
+    ));
+    check_result!(draw_part_c::<B, _>(
+        radius.1 as i32,
+        radius.0 as i32,
+        |p, r| draw_sweep_line(b, style, center, (0, -1), p, r)
+    ));
+    check_result!(draw_part_c::<B, _>(
+        radius.1 as i32,
+        radius.0 as i32,
+        |p, r| draw_sweep_line(b, style, center, (1, 0), p, r)
+    ));
+    check_result!(draw_part_c::<B, _>(
+        radius.1 as i32,
+        radius.0 as i32,
+        |p, r| draw_sweep_line(b, style, center, (-1, 0), p, r)
+    ));
+
+    let d_inner = ((radius.1 as f64) / (2f64).sqrt()) as i32;
+    let d_outter = (((radius.0 as f64) / (2f64).sqrt()) as i32).min(radius.1 as i32 - 1);
+    let d_outter_actually = (radius.1 as i32).min(
+        (radius.0 as f64 * radius.0 as f64 - radius.1 as f64 * radius.1 as f64 / 2.0)
+            .sqrt()
+            .ceil() as i32,
+    );
+
+    check_result!(b.draw_line(
+        (center.0 - d_inner, center.1 - d_inner),
+        (center.0 - d_outter, center.1 - d_outter),
+        &style.color()
+    ));
+    check_result!(b.draw_line(
+        (center.0 + d_inner, center.1 - d_inner),
+        (center.0 + d_outter, center.1 - d_outter),
+        &style.color()
+    ));
+    check_result!(b.draw_line(
+        (center.0 - d_inner, center.1 + d_inner),
+        (center.0 - d_outter, center.1 + d_outter),
+        &style.color()
+    ));
+    check_result!(b.draw_line(
+        (center.0 + d_inner, center.1 + d_inner),
+        (center.0 + d_outter, center.1 + d_outter),
+        &style.color()
+    ));
+
+    check_result!(b.draw_line(
+        (center.0 - d_inner, center.1 + d_inner),
+        (center.0 - d_outter_actually, center.1 + d_inner),
+        &style.color()
+    ));
+    check_result!(b.draw_line(
+        (center.0 + d_inner, center.1 - d_inner),
+        (center.0 + d_inner, center.1 - d_outter_actually),
+        &style.color()
+    ));
+    check_result!(b.draw_line(
+        (center.0 + d_inner, center.1 + d_inner),
+        (center.0 + d_inner, center.1 + d_outter_actually),
+        &style.color()
+    ));
+    check_result!(b.draw_line(
+        (center.0 + d_inner, center.1 + d_inner),
+        (center.0 + d_outter_actually, center.1 + d_inner),
+        &style.color()
+    ));
+
+    Ok(())
+}
+
+pub fn draw_circle<B: DrawingBackend, S: BackendStyle>(
+    b: &mut B,
+    center: BackendCoord,
+    mut radius: u32,
+    style: &S,
+    mut fill: bool,
+) -> Result<(), DrawingErrorKind<B::ErrorType>> {
+    if style.color().alpha == 0.0 {
+        return Ok(());
+    }
+
+    if !fill && style.stroke_width() != 1 {
+        let inner_radius = radius - (style.stroke_width() / 2).min(radius);
+        radius += style.stroke_width() / 2;
+        if inner_radius > 0 {
+            return draw_annulus(b, center, (radius, inner_radius), style);
+        } else {
+            fill = true;
+        }
+    }
+
+    let min = (f64::from(radius) * (1.0 - (2f64).sqrt() / 2.0)).ceil() as i32;
+    let max = (f64::from(radius) * (1.0 + (2f64).sqrt() / 2.0)).floor() as i32;
+
+    let range = min..=max;
+
+    let (up, down) = (
+        range.start() + center.1 - radius as i32,
+        range.end() + center.1 - radius as i32,
+    );
+
+    for dy in range {
+        let dy = dy - radius as i32;
+        let y = center.1 + dy;
+
+        let lx = (f64::from(radius) * f64::from(radius)
+            - (f64::from(dy) * f64::from(dy)).max(1e-5))
+        .sqrt();
+
+        let left = center.0 - lx.floor() as i32;
+        let right = center.0 + lx.floor() as i32;
+
+        let v = lx - lx.floor();
+
+        let x = center.0 + dy;
+        let top = center.1 - lx.floor() as i32;
+        let bottom = center.1 + lx.floor() as i32;
+
+        if fill {
+            check_result!(b.draw_line((left, y), (right, y), &style.color()));
+            check_result!(b.draw_line((x, top), (x, up), &style.color()));
+            check_result!(b.draw_line((x, down), (x, bottom), &style.color()));
+        } else {
+            check_result!(b.draw_pixel((left, y), style.color().mix(1.0 - v)));
+            check_result!(b.draw_pixel((right, y), style.color().mix(1.0 - v)));
+
+            check_result!(b.draw_pixel((x, top), style.color().mix(1.0 - v)));
+            check_result!(b.draw_pixel((x, bottom), style.color().mix(1.0 - v)));
+        }
+
+        check_result!(b.draw_pixel((left - 1, y), style.color().mix(v)));
+        check_result!(b.draw_pixel((right + 1, y), style.color().mix(v)));
+        check_result!(b.draw_pixel((x, top - 1), style.color().mix(v)));
+        check_result!(b.draw_pixel((x, bottom + 1), style.color().mix(v)));
+    }
+
+    Ok(())
+}
diff --git a/src/rasterizer/line.rs b/src/rasterizer/line.rs
new file mode 100644
index 0000000..0f24b0a
--- /dev/null
+++ b/src/rasterizer/line.rs
@@ -0,0 +1,123 @@
+use crate::{BackendCoord, BackendStyle, DrawingBackend, DrawingErrorKind};
+
+pub fn draw_line<DB: DrawingBackend, S: BackendStyle>(
+    back: &mut DB,
+    mut from: BackendCoord,
+    mut to: BackendCoord,
+    style: &S,
+) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
+    if style.color().alpha == 0.0 {
+        return Ok(());
+    }
+
+    if style.stroke_width() != 1 {
+        // If the line is wider than 1px, then we need to make it a polygon
+        let v = (i64::from(to.0 - from.0), i64::from(to.1 - from.1));
+        let l = ((v.0 * v.0 + v.1 * v.1) as f64).sqrt();
+
+        if l < 1e-5 {
+            return Ok(());
+        }
+
+        let v = (v.0 as f64 / l, v.1 as f64 / l);
+
+        let r = f64::from(style.stroke_width()) / 2.0;
+        let mut trans = [(v.1 * r, -v.0 * r), (-v.1 * r, v.0 * r)];
+        let mut vertices = vec![];
+
+        for point in [from, to].iter() {
+            for t in trans.iter() {
+                vertices.push((
+                    (f64::from(point.0) + t.0) as i32,
+                    (f64::from(point.1) + t.1) as i32,
+                ))
+            }
+
+            trans.swap(0, 1);
+        }
+
+        return back.fill_polygon(vertices, style);
+    }
+
+    if from.0 == to.0 {
+        if from.1 > to.1 {
+            std::mem::swap(&mut from, &mut to);
+        }
+        for y in from.1..=to.1 {
+            check_result!(back.draw_pixel((from.0, y), style.color()));
+        }
+        return Ok(());
+    }
+
+    if from.1 == to.1 {
+        if from.0 > to.0 {
+            std::mem::swap(&mut from, &mut to);
+        }
+        for x in from.0..=to.0 {
+            check_result!(back.draw_pixel((x, from.1), style.color()));
+        }
+        return Ok(());
+    }
+
+    let steep = (from.0 - to.0).abs() < (from.1 - to.1).abs();
+
+    if steep {
+        from = (from.1, from.0);
+        to = (to.1, to.0);
+    }
+
+    let (from, to) = if from.0 > to.0 {
+        (to, from)
+    } else {
+        (from, to)
+    };
+
+    let mut size_limit = back.get_size();
+
+    if steep {
+        size_limit = (size_limit.1, size_limit.0);
+    }
+
+    let grad = f64::from(to.1 - from.1) / f64::from(to.0 - from.0);
+
+    let mut put_pixel = |(x, y): BackendCoord, b: f64| {
+        if steep {
+            back.draw_pixel((y, x), style.color().mix(b))
+        } else {
+            back.draw_pixel((x, y), style.color().mix(b))
+        }
+    };
+
+    let y_step_limit =
+        (f64::from(to.1.min(size_limit.1 as i32 - 1).max(0) - from.1) / grad).floor() as i32;
+
+    let batch_start = (f64::from(from.1.min(size_limit.1 as i32 - 2).max(0) - from.1) / grad)
+        .abs()
+        .ceil() as i32
+        + from.0;
+
+    let batch_limit =
+        to.0.min(size_limit.0 as i32 - 2)
+            .min(from.0 + y_step_limit - 1);
+
+    let mut y = f64::from(from.1) + f64::from(batch_start - from.0) * grad;
+
+    for x in batch_start..=batch_limit {
+        check_result!(put_pixel((x, y as i32), 1.0 + y.floor() - y));
+        check_result!(put_pixel((x, y as i32 + 1), y - y.floor()));
+
+        y += grad;
+    }
+
+    if to.0 >= batch_limit + 1 && y < f64::from(to.1) {
+        let x = batch_limit as i32 + 1;
+        if 1.0 + y.floor() - y > 1e-5 {
+            check_result!(put_pixel((x, y as i32), 1.0 + y.floor() - y));
+        }
+        if y - y.floor() > 1e-5 && y + 1.0 < f64::from(to.1) {
+            check_result!(put_pixel((x, y as i32 + 1), y - y.floor()));
+        }
+    }
+
+    Ok(())
+}
diff --git a/src/rasterizer/mod.rs b/src/rasterizer/mod.rs
new file mode 100644
index 0000000..11835f4
--- /dev/null
+++ b/src/rasterizer/mod.rs
@@ -0,0 +1,32 @@
+/*! # The built-in rasterizers.
+
+  Plotters make a minimal backend ability assumption - which is drawing a pixel on
+  backend. And this is the rasterizer that utilize this minimal ability to build a
+  fully functioning backend.
+
+*/
+
+// TODO: ? operator is very slow. See issue #58 for details
+macro_rules! check_result {
+    ($e:expr) => {
+        let result = $e;
+        if result.is_err() {
+            return result;
+        }
+    };
+}
+
+mod line;
+pub use line::draw_line;
+
+mod rect;
+pub use rect::draw_rect;
+
+mod circle;
+pub use circle::draw_circle;
+
+mod polygon;
+pub use polygon::fill_polygon;
+
+mod path;
+pub use path::polygonize;
diff --git a/src/rasterizer/path.rs b/src/rasterizer/path.rs
new file mode 100644
index 0000000..b2db356
--- /dev/null
+++ b/src/rasterizer/path.rs
@@ -0,0 +1,115 @@
+use crate::BackendCoord;
+
+fn get_dir_vector(from: BackendCoord, to: BackendCoord, flag: bool) -> ((f64, f64), (f64, f64)) {
+    let v = (i64::from(to.0 - from.0), i64::from(to.1 - from.1));
+    let l = ((v.0 * v.0 + v.1 * v.1) as f64).sqrt();
+
+    let v = (v.0 as f64 / l, v.1 as f64 / l);
+
+    if flag {
+        (v, (v.1, -v.0))
+    } else {
+        (v, (-v.1, v.0))
+    }
+}
+
+fn compute_polygon_vertex(triple: &[BackendCoord; 3], d: f64) -> BackendCoord {
+    let (a_t, a_n) = get_dir_vector(triple[0], triple[1], false);
+    let (b_t, b_n) = get_dir_vector(triple[2], triple[1], true);
+
+    let a_p = (
+        f64::from(triple[1].0) + d * a_n.0,
+        f64::from(triple[1].1) + d * a_n.1,
+    );
+    let b_p = (
+        f64::from(triple[1].0) + d * b_n.0,
+        f64::from(triple[1].1) + d * b_n.1,
+    );
+
+    // u * a_t + a_p = v * b_t + b_p
+    // u * a_t.0 - v * b_t.0 = b_p.0 - a_p.0
+    // u * a_t.1 - v * b_t.1 = b_p.1 - a_p.1
+    if a_p.0 as i32 == b_p.0 as i32 && a_p.1 as i32 == b_p.1 as i32 {
+        return (a_p.0 as i32, a_p.1 as i32);
+    }
+
+    let a0 = a_t.0;
+    let b0 = -b_t.0;
+    let c0 = b_p.0 - a_p.0;
+    let a1 = a_t.1;
+    let b1 = -b_t.1;
+    let c1 = b_p.1 - a_p.1;
+
+    // This is the coner case that
+    if (a0 * b1 - a1 * b0).abs() < 1e-10 {
+        return (a_p.0 as i32, a_p.1 as i32);
+    }
+
+    let u = (c0 * b1 - c1 * b0) / (a0 * b1 - a1 * b0);
+
+    let x = a_p.0 + u * a_t.0;
+    let y = a_p.1 + u * a_t.1;
+
+    (x.round() as i32, y.round() as i32)
+}
+
+fn traverse_vertices<'a>(
+    mut vertices: impl Iterator<Item = &'a BackendCoord>,
+    width: u32,
+    mut op: impl FnMut(BackendCoord),
+) {
+    let mut a = vertices.next().unwrap();
+    let mut b = vertices.next().unwrap();
+
+    while a == b {
+        a = b;
+        if let Some(new_b) = vertices.next() {
+            b = new_b;
+        } else {
+            return;
+        }
+    }
+
+    let (_, n) = get_dir_vector(*a, *b, false);
+
+    op((
+        (f64::from(a.0) + n.0 * f64::from(width) / 2.0).round() as i32,
+        (f64::from(a.1) + n.1 * f64::from(width) / 2.0).round() as i32,
+    ));
+
+    let mut recent = [(0, 0), *a, *b];
+
+    for p in vertices {
+        if *p == recent[2] {
+            continue;
+        }
+        recent.swap(0, 1);
+        recent.swap(1, 2);
+        recent[2] = *p;
+        op(compute_polygon_vertex(&recent, f64::from(width) / 2.0));
+    }
+
+    let b = recent[1];
+    let a = recent[2];
+
+    let (_, n) = get_dir_vector(a, b, true);
+
+    op((
+        (f64::from(a.0) + n.0 * f64::from(width) / 2.0).round() as i32,
+        (f64::from(a.1) + n.1 * f64::from(width) / 2.0).round() as i32,
+    ));
+}
+
+/// Covert a path with >1px stroke width into polygon.
+pub fn polygonize(vertices: &[BackendCoord], stroke_width: u32) -> Vec<BackendCoord> {
+    if vertices.len() < 2 {
+        return vec![];
+    }
+
+    let mut ret = vec![];
+
+    traverse_vertices(vertices.iter(), stroke_width, |v| ret.push(v));
+    traverse_vertices(vertices.iter().rev(), stroke_width, |v| ret.push(v));
+
+    ret
+}
diff --git a/src/rasterizer/polygon.rs b/src/rasterizer/polygon.rs
new file mode 100644
index 0000000..ce33c5c
--- /dev/null
+++ b/src/rasterizer/polygon.rs
@@ -0,0 +1,242 @@
+use crate::{BackendCoord, BackendStyle, DrawingBackend, DrawingErrorKind};
+
+use std::cmp::{Ord, Ordering, PartialOrd};
+
+#[derive(Clone, Debug)]
+struct Edge {
+    epoch: u32,
+    total_epoch: u32,
+    slave_begin: i32,
+    slave_end: i32,
+}
+
+impl Edge {
+    fn horizontal_sweep(mut from: BackendCoord, mut to: BackendCoord) -> Option<Edge> {
+        if from.0 == to.0 {
+            return None;
+        }
+
+        if from.0 > to.0 {
+            std::mem::swap(&mut from, &mut to);
+        }
+
+        Some(Edge {
+            epoch: 0,
+            total_epoch: (to.0 - from.0) as u32,
+            slave_begin: from.1,
+            slave_end: to.1,
+        })
+    }
+
+    fn vertical_sweep(from: BackendCoord, to: BackendCoord) -> Option<Edge> {
+        Edge::horizontal_sweep((from.1, from.0), (to.1, to.0))
+    }
+
+    fn get_master_pos(&self) -> i32 {
+        (self.total_epoch - self.epoch) as i32
+    }
+
+    fn inc_epoch(&mut self) {
+        self.epoch += 1;
+    }
+
+    fn get_slave_pos(&self) -> f64 {
+        f64::from(self.slave_begin)
+            + (i64::from(self.slave_end - self.slave_begin) * i64::from(self.epoch)) as f64
+                / f64::from(self.total_epoch)
+    }
+}
+
+impl PartialOrd for Edge {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.get_slave_pos().partial_cmp(&other.get_slave_pos())
+    }
+}
+
+impl PartialEq for Edge {
+    fn eq(&self, other: &Self) -> bool {
+        self.get_slave_pos() == other.get_slave_pos()
+    }
+}
+
+impl Eq for Edge {}
+
+impl Ord for Edge {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.get_slave_pos()
+            .partial_cmp(&other.get_slave_pos())
+            .unwrap()
+    }
+}
+
+pub fn fill_polygon<DB: DrawingBackend, S: BackendStyle>(
+    back: &mut DB,
+    vertices: &[BackendCoord],
+    style: &S,
+) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
+    if let Some((x_span, y_span)) =
+        vertices
+            .iter()
+            .fold(None, |res: Option<((i32, i32), (i32, i32))>, (x, y)| {
+                Some(
+                    res.map(|((min_x, max_x), (min_y, max_y))| {
+                        (
+                            (min_x.min(*x), max_x.max(*x)),
+                            (min_y.min(*y), max_y.max(*y)),
+                        )
+                    })
+                    .unwrap_or(((*x, *x), (*y, *y))),
+                )
+            })
+    {
+        // First of all, let's handle the case that all the points is in a same vertical or
+        // horizontal line
+        if x_span.0 == x_span.1 || y_span.0 == y_span.1 {
+            return back.draw_line((x_span.0, y_span.0), (x_span.1, y_span.1), style);
+        }
+
+        let horizontal_sweep = x_span.1 - x_span.0 > y_span.1 - y_span.0;
+
+        let mut edges: Vec<_> = vertices
+            .iter()
+            .zip(vertices.iter().skip(1))
+            .map(|(a, b)| (*a, *b))
+            .collect();
+        edges.push((vertices[vertices.len() - 1], vertices[0]));
+        edges.sort_by_key(|((x1, y1), (x2, y2))| {
+            if horizontal_sweep {
+                *x1.min(x2)
+            } else {
+                *y1.min(y2)
+            }
+        });
+
+        for edge in &mut edges.iter_mut() {
+            if horizontal_sweep {
+                if (edge.0).0 > (edge.1).0 {
+                    std::mem::swap(&mut edge.0, &mut edge.1);
+                }
+            } else if (edge.0).1 > (edge.1).1 {
+                std::mem::swap(&mut edge.0, &mut edge.1);
+            }
+        }
+
+        let (low, high) = if horizontal_sweep { x_span } else { y_span };
+
+        let mut idx = 0;
+
+        let mut active_edge: Vec<Edge> = vec![];
+
+        for sweep_line in low..=high {
+            let mut new_vec = vec![];
+
+            for mut e in active_edge {
+                if e.get_master_pos() > 0 {
+                    e.inc_epoch();
+                    new_vec.push(e);
+                }
+            }
+
+            active_edge = new_vec;
+
+            loop {
+                if idx >= edges.len() {
+                    break;
+                }
+                let line = if horizontal_sweep {
+                    (edges[idx].0).0
+                } else {
+                    (edges[idx].0).1
+                };
+                if line > sweep_line {
+                    break;
+                }
+
+                let edge_obj = if horizontal_sweep {
+                    Edge::horizontal_sweep(edges[idx].0, edges[idx].1)
+                } else {
+                    Edge::vertical_sweep(edges[idx].0, edges[idx].1)
+                };
+
+                if let Some(edge_obj) = edge_obj {
+                    active_edge.push(edge_obj);
+                }
+
+                idx += 1;
+            }
+
+            active_edge.sort();
+
+            let mut first = None;
+            let mut second = None;
+
+            for edge in active_edge.iter() {
+                if first.is_none() {
+                    first = Some(edge.clone())
+                } else if second.is_none() {
+                    second = Some(edge.clone())
+                }
+
+                if let Some(a) = first.clone() {
+                    if let Some(b) = second.clone() {
+                        if a.get_master_pos() == 0 && b.get_master_pos() != 0 {
+                            first = Some(b);
+                            second = None;
+                            continue;
+                        }
+
+                        if a.get_master_pos() != 0 && b.get_master_pos() == 0 {
+                            first = Some(a);
+                            second = None;
+                            continue;
+                        }
+
+                        let from = a.get_slave_pos();
+                        let to = b.get_slave_pos();
+
+                        if a.get_master_pos() == 0 && b.get_master_pos() == 0 && to - from > 1.0 {
+                            first = None;
+                            second = None;
+                            continue;
+                        }
+
+                        if horizontal_sweep {
+                            check_result!(back.draw_line(
+                                (sweep_line, from.ceil() as i32),
+                                (sweep_line, to.floor() as i32),
+                                &style.color(),
+                            ));
+                            check_result!(back.draw_pixel(
+                                (sweep_line, from.floor() as i32),
+                                style.color().mix(from.ceil() - from),
+                            ));
+                            check_result!(back.draw_pixel(
+                                (sweep_line, to.ceil() as i32),
+                                style.color().mix(to - to.floor()),
+                            ));
+                        } else {
+                            check_result!(back.draw_line(
+                                (from.ceil() as i32, sweep_line),
+                                (to.floor() as i32, sweep_line),
+                                &style.color(),
+                            ));
+                            check_result!(back.draw_pixel(
+                                (from.floor() as i32, sweep_line),
+                                style.color().mix(from.ceil() - from),
+                            ));
+                            check_result!(back.draw_pixel(
+                                (to.ceil() as i32, sweep_line),
+                                style.color().mix(to.floor() - to),
+                            ));
+                        }
+
+                        first = None;
+                        second = None;
+                    }
+                }
+            }
+        }
+    }
+
+    Ok(())
+}
diff --git a/src/rasterizer/rect.rs b/src/rasterizer/rect.rs
new file mode 100644
index 0000000..cd6c774
--- /dev/null
+++ b/src/rasterizer/rect.rs
@@ -0,0 +1,57 @@
+use crate::{BackendCoord, BackendStyle, DrawingBackend, DrawingErrorKind};
+
+pub fn draw_rect<B: DrawingBackend, S: BackendStyle>(
+    b: &mut B,
+    upper_left: BackendCoord,
+    bottom_right: BackendCoord,
+    style: &S,
+    fill: bool,
+) -> Result<(), DrawingErrorKind<B::ErrorType>> {
+    if style.color().alpha == 0.0 {
+        return Ok(());
+    }
+    let (upper_left, bottom_right) = (
+        (
+            upper_left.0.min(bottom_right.0),
+            upper_left.1.min(bottom_right.1),
+        ),
+        (
+            upper_left.0.max(bottom_right.0),
+            upper_left.1.max(bottom_right.1),
+        ),
+    );
+
+    if fill {
+        if bottom_right.0 - upper_left.0 < bottom_right.1 - upper_left.1 {
+            for x in upper_left.0..=bottom_right.0 {
+                check_result!(b.draw_line((x, upper_left.1), (x, bottom_right.1), style));
+            }
+        } else {
+            for y in upper_left.1..=bottom_right.1 {
+                check_result!(b.draw_line((upper_left.0, y), (bottom_right.0, y), style));
+            }
+        }
+    } else {
+        b.draw_line(
+            (upper_left.0, upper_left.1),
+            (upper_left.0, bottom_right.1),
+            style,
+        )?;
+        b.draw_line(
+            (upper_left.0, upper_left.1),
+            (bottom_right.0, upper_left.1),
+            style,
+        )?;
+        b.draw_line(
+            (bottom_right.0, bottom_right.1),
+            (upper_left.0, bottom_right.1),
+            style,
+        )?;
+        b.draw_line(
+            (bottom_right.0, bottom_right.1),
+            (bottom_right.0, upper_left.1),
+            style,
+        )?;
+    }
+    Ok(())
+}
diff --git a/src/style.rs b/src/style.rs
new file mode 100644
index 0000000..028a06b
--- /dev/null
+++ b/src/style.rs
@@ -0,0 +1,33 @@
+/// The color type that is used by all the backend
+#[derive(Clone, Copy)]
+pub struct BackendColor {
+    pub alpha: f64,
+    pub rgb: (u8, u8, u8),
+}
+
+impl BackendColor {
+    #[inline(always)]
+    pub fn mix(&self, alpha: f64) -> Self {
+        Self {
+            alpha: self.alpha * alpha,
+            rgb: self.rgb,
+        }
+    }
+}
+
+/// The style data for the backend drawing API
+pub trait BackendStyle {
+    /// Get the color of current style
+    fn color(&self) -> BackendColor;
+
+    /// Get the stroke width of current style
+    fn stroke_width(&self) -> u32 {
+        1
+    }
+}
+
+impl BackendStyle for BackendColor {
+    fn color(&self) -> BackendColor {
+        *self
+    }
+}
diff --git a/src/text.rs b/src/text.rs
new file mode 100644
index 0000000..58cc9f2
--- /dev/null
+++ b/src/text.rs
@@ -0,0 +1,244 @@
+use super::{BackendColor, BackendCoord};
+use std::error::Error;
+
+/// Describes font family.
+/// This can be either a specific font family name, such as "arial",
+/// or a general font family class, such as "serif" and "sans-serif"
+#[derive(Clone, Copy)]
+pub enum FontFamily<'a> {
+    /// The system default serif font family
+    Serif,
+    /// The system default sans-serif font family
+    SansSerif,
+    /// The system default monospace font
+    Monospace,
+    /// A specific font family name
+    Name(&'a str),
+}
+
+impl<'a> FontFamily<'a> {
+    /// Make a CSS compatible string for the font family name.
+    /// This can be used as the value of `font-family` attribute in SVG.
+    pub fn as_str(&self) -> &str {
+        match self {
+            FontFamily::Serif => "serif",
+            FontFamily::SansSerif => "sans-serif",
+            FontFamily::Monospace => "monospace",
+            FontFamily::Name(face) => face,
+        }
+    }
+}
+
+impl<'a> From<&'a str> for FontFamily<'a> {
+    fn from(from: &'a str) -> FontFamily<'a> {
+        match from.to_lowercase().as_str() {
+            "serif" => FontFamily::Serif,
+            "sans-serif" => FontFamily::SansSerif,
+            "monospace" => FontFamily::Monospace,
+            _ => FontFamily::Name(from),
+        }
+    }
+}
+
+/// Text anchor attributes are used to properly position the text.
+///
+/// # Examples
+///
+/// In the example below, the text anchor (X) position is `Pos::new(HPos::Right, VPos::Center)`.
+/// ```text
+///    ***** X
+/// ```
+/// The position is always relative to the text regardless of its rotation.
+/// In the example below, the text has style
+/// `style.transform(FontTransform::Rotate90).pos(Pos::new(HPos::Center, VPos::Top))`.
+/// ```text
+///        *
+///        *
+///        * X
+///        *
+///        *
+/// ```
+pub mod text_anchor {
+    /// The horizontal position of the anchor point relative to the text.
+    #[derive(Clone, Copy)]
+    pub enum HPos {
+        /// Anchor point is on the left side of the text
+        Left,
+        /// Anchor point is on the right side of the text
+        Right,
+        /// Anchor point is in the horizontal center of the text
+        Center,
+    }
+
+    /// The vertical position of the anchor point relative to the text.
+    #[derive(Clone, Copy)]
+    pub enum VPos {
+        /// Anchor point is on the top of the text
+        Top,
+        /// Anchor point is in the vertical center of the text
+        Center,
+        /// Anchor point is on the bottom of the text
+        Bottom,
+    }
+
+    /// The text anchor position.
+    #[derive(Clone, Copy)]
+    pub struct Pos {
+        /// The horizontal position of the anchor point
+        pub h_pos: HPos,
+        /// The vertical position of the anchor point
+        pub v_pos: VPos,
+    }
+
+    impl Pos {
+        /// Create a new text anchor position.
+        ///
+        /// - `h_pos`: The horizontal position of the anchor point
+        /// - `v_pos`: The vertical position of the anchor point
+        /// - **returns** The newly created text anchor position
+        ///
+        /// ```rust
+        /// use plotters_backend::text_anchor::{Pos, HPos, VPos};
+        ///
+        /// let pos = Pos::new(HPos::Left, VPos::Top);
+        /// ```
+        pub fn new(h_pos: HPos, v_pos: VPos) -> Self {
+            Pos { h_pos, v_pos }
+        }
+
+        /// Create a default text anchor position (top left).
+        ///
+        /// - **returns** The default text anchor position
+        ///
+        /// ```rust
+        /// use plotters_backend::text_anchor::{Pos, HPos, VPos};
+        ///
+        /// let pos = Pos::default();
+        /// ```
+        pub fn default() -> Self {
+            Pos {
+                h_pos: HPos::Left,
+                v_pos: VPos::Top,
+            }
+        }
+    }
+}
+
+/// Specifying text transformations
+#[derive(Clone)]
+pub enum FontTransform {
+    /// Nothing to transform
+    None,
+    /// Rotating the text 90 degree clockwise
+    Rotate90,
+    /// Rotating the text 180 degree clockwise
+    Rotate180,
+    /// Rotating the text 270 degree clockwise
+    Rotate270,
+}
+
+impl FontTransform {
+    /// Transform the coordinate to perform the rotation
+    ///
+    /// - `x`: The x coordinate in pixels before transform
+    /// - `y`: The y coordinate in pixels before transform
+    /// - **returns**: The coordinate after transform
+    pub fn transform(&self, x: i32, y: i32) -> (i32, i32) {
+        match self {
+            FontTransform::None => (x, y),
+            FontTransform::Rotate90 => (-y, x),
+            FontTransform::Rotate180 => (-x, -y),
+            FontTransform::Rotate270 => (y, -x),
+        }
+    }
+}
+
+/// Describes the font style. Such as Italic, Oblique, etc.
+#[derive(Clone, Copy)]
+pub enum FontStyle {
+    /// The normal style
+    Normal,
+    /// The oblique style
+    Oblique,
+    /// The italic style
+    Italic,
+    /// The bold style
+    Bold,
+}
+
+impl FontStyle {
+    /// Convert the font style into a CSS compatible string which can be used in `font-style` attribute.
+    pub fn as_str(&self) -> &str {
+        match self {
+            FontStyle::Normal => "normal",
+            FontStyle::Italic => "italic",
+            FontStyle::Oblique => "oblique",
+            FontStyle::Bold => "bold",
+        }
+    }
+}
+
+impl<'a> From<&'a str> for FontStyle {
+    fn from(from: &'a str) -> FontStyle {
+        match from.to_lowercase().as_str() {
+            "normal" => FontStyle::Normal,
+            "italic" => FontStyle::Italic,
+            "oblique" => FontStyle::Oblique,
+            "bold" => FontStyle::Bold,
+            _ => FontStyle::Normal,
+        }
+    }
+}
+
+/// The trait that abstracts a style of a text.
+///
+/// This is used because the the backend crate have no knowledge about how
+/// the text handling is implemented in plotters.
+///
+/// But the backend still wants to know some information about the font, for
+/// the backend doesn't handles text drawing, may want to call the `draw` method which
+/// is implemented by the plotters main crate. While for the backend that handles the
+/// text drawing, those font information provides instructions about how the text should be
+/// rendered: color, size, slant, anchor, font, etc.
+///
+/// This trait decouples the detailed implementaiton about the font and the backend code which
+/// wants to perfome some operation on the font.
+///
+pub trait BackendTextStyle {
+    /// The error type of this text style implementation
+    type FontError: Error + Sync + Send + 'static;
+
+    fn color(&self) -> BackendColor {
+        BackendColor {
+            alpha: 1.0,
+            rgb: (0, 0, 0),
+        }
+    }
+
+    fn size(&self) -> f64 {
+        1.0
+    }
+
+    fn transform(&self) -> FontTransform {
+        FontTransform::None
+    }
+
+    fn style(&self) -> FontStyle {
+        FontStyle::Normal
+    }
+
+    fn anchor(&self) -> text_anchor::Pos {
+        text_anchor::Pos::default()
+    }
+
+    fn family(&self) -> FontFamily;
+
+    fn layout_box(&self, text: &str) -> Result<((i32, i32), (i32, i32)), Self::FontError>;
+
+    fn draw<E, DrawFunc: FnMut(i32, i32, BackendColor) -> Result<(), E>>(
+        &self,
+        text: &str,
+        pos: BackendCoord,
+        draw: DrawFunc,
+    ) -> Result<Result<(), E>, Self::FontError>;
+}