From ba63b2151bd91681b43d0f13f2c3092fd32e315a Mon Sep 17 00:00:00 2001 From: James Waples Date: Mon, 13 Jan 2020 13:36:30 +0000 Subject: [PATCH] Embedded graphics 0.6.0-alpha.3 (#2) * Upgrade lib to e-g 0.6.0-alpha.3 * Fix examples * Fix doc examples, test them in CI * Format doc example * Migrate to CircleCI * Add/update badges * Add changelog entry * Remove empty values from cache checksum * Clean docs more thoroughly * Fix(?) docs.rs build * Fix graphics example styles --- .circleci/config.yml | 107 +++++++++++++++++++++++++++++++++++++++++++ .travis.yml | 65 -------------------------- CHANGELOG.md | 7 ++- Cargo.toml | 10 ++-- README.md | 4 +- build.sh | 8 ++-- examples/bmp.rs | 2 +- examples/graphics.rs | 52 ++++++++++++--------- examples/image.rs | 2 +- examples/rotation.rs | 6 ++- examples/text.rs | 47 +++++++++++-------- src/display.rs | 104 ++++++++++++++++++++++------------------- src/lib.rs | 2 +- 13 files changed, 247 insertions(+), 169 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 .travis.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..4028621 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,107 @@ +target_steps: &target_steps + docker: + - image: circleci/rust:1.40.0 + steps: + - checkout + - restore_cache: + key: v1-ssd1331-{{ .Environment.CIRCLE_JOB }}-{{ checksum "Cargo.toml" }} + - run: sudo apt install -qq libsdl2-dev python-pip + - run: sudo pip install linkchecker + - run: rustup default ${RUST_VERSION:-stable} + - run: rustup component add rustfmt + - run: | + SYSROOT=$(rustc --print sysroot) + + if [[ ! "$SYSROOT" =~ "$TARGET" ]]; then + rustup target add $TARGET + else + echo "Target $TARGET is already installed" + fi + - run: ./build.sh + - save_cache: + key: v1-ssd1331-{{ .Environment.CIRCLE_JOB }}-{{ checksum "Cargo.toml" }} + paths: + - ./target + - /home/ubuntu/.cargo + +version: 2 +jobs: + target-arm-unknown-linux-eabi: + environment: + - TARGET: "arm-unknown-linux-gnueabi" + - DISABLE_EXAMPLES: 1 + <<: *target_steps + + target-armv7-unknown-linux-gnueabihf: + environment: + - TARGET: "armv7-unknown-linux-gnueabihf" + - DISABLE_EXAMPLES: 1 + <<: *target_steps + + target-x86_64-unknown-linux-gnu: + environment: + - TARGET: "x86_64-unknown-linux-gnu" + - DISABLE_EXAMPLES: 1 + <<: *target_steps + + target-x86_64-unknown-linux-musl: + environment: + - TARGET: "x86_64-unknown-linux-musl" + - DISABLE_EXAMPLES: 1 + <<: *target_steps + + target-thumbv6m-none-eabi: + environment: + - TARGET: "thumbv6m-none-eabi" + # Disable example builds as they target thumbv7 and up + - DISABLE_EXAMPLES: 1 + <<: *target_steps + + target-thumbv7em-none-eabi: + environment: + - TARGET: "thumbv7em-none-eabi" + <<: *target_steps + + target-thumbv7em-none-eabihf: + environment: + - TARGET: "thumbv7em-none-eabihf" + <<: *target_steps + + target-thumbv7m-none-eabi: + environment: + - TARGET: "thumbv7m-none-eabi" + <<: *target_steps + +build_jobs: &build_jobs + jobs: + # Raspberry Pi 1 + - target-arm-unknown-linux-eabi + + # Raspberry Pi 2, 3, etc + - target-armv7-unknown-linux-gnueabihf + + # Linux + - target-x86_64-unknown-linux-gnu + - target-x86_64-unknown-linux-musl + + # Bare metal + - target-thumbv6m-none-eabi + - target-thumbv7em-none-eabi + - target-thumbv7em-none-eabihf + - target-thumbv7m-none-eabi + +workflows: + version: 2 + build_all: + <<: *build_jobs + + # Build every day + nightly: + <<: *build_jobs + triggers: + - schedule: + cron: "0 0 * * *" + filters: + branches: + only: + - master diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 030fa77..0000000 --- a/.travis.yml +++ /dev/null @@ -1,65 +0,0 @@ -# Based on the "trust" template v0.1.2 -# https://github.com/japaric/trust/tree/v0.1.2 - -dist: trusty -language: rust -rust: - - stable - - beta - - nightly -sudo: required - -matrix: - include: - # Raspberry Pi 1 - - env: TARGET=arm-unknown-linux-gnueabi DISABLE_EXAMPLES=1 - - # Raspberry Pi 2, 3, etc - - env: TARGET=armv7-unknown-linux-gnueabihf DISABLE_EXAMPLES=1 - - env: TARGET=x86_64-unknown-linux-gnu DISABLE_EXAMPLES=1 - - env: TARGET=x86_64-unknown-linux-musl DISABLE_EXAMPLES=1 - - # Bare metal - - env: TARGET=thumbv6m-none-eabi DISABLE_EXAMPLES=1 - - env: TARGET=thumbv7em-none-eabi - - env: TARGET=thumbv7em-none-eabihf - - env: TARGET=thumbv7m-none-eabi - - - rust: nightly - env: TARGET=thumbv7m-none-eabi - - - rust: beta - env: TARGET=thumbv7m-none-eabi - - # Always supply a target - exclude: - - rust: stable - - rust: beta - - rust: nightly - -install: - - pip install linkchecker --user - - rustup component add rust-src - - rustup component add rustfmt - - rustup target add thumbv7m-none-eabi - - | - SYSROOT=$(rustc --print sysroot) - - if [[ ! "$SYSROOT" =~ "$TARGET" ]]; then - rustup target add $TARGET - else - echo "Target $TARGET is already installed" - fi - - source ~/.cargo/env || true - -script: - - ./build.sh - -cache: cargo -before_cache: - # Travis can't cache files that are not readable by "others" - - chmod -R a+r $HOME/.cargo - -notifications: - email: - on_success: never diff --git a/CHANGELOG.md b/CHANGELOG.md index cbf54c8..04b2378 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,19 +5,18 @@ ## Unreleased -- None - ### Added - None ### Changed -- None +- **(breaking)** Upgraded to embedded-graphics 0.6.0-alpha.3 +- Migrated from Travis to CircleCI for repo builds ### Fixed -- None +- Tell docs.rs to build against `x86_64-unknown-linux-gnu` so doc builds work again ### Security diff --git a/Cargo.toml b/Cargo.toml index e1d8a06..995a677 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,16 +11,18 @@ readme = "README.md" repository = "https://github.com/jamwaffles/ssd1331" version = "0.2.0-alpha.1" edition = "2018" -[badges.travis-ci] -branch = "master" -repository = "jamwaffles/ssd1331" +[badges] +circle-ci = { repository = "jamwaffles/ssd1331", branch = "master" } + +[package.metadata.docs.rs] +default-target = "x86_64-unknown-linux-gnu" [dependencies] embedded-hal = "0.2.3" [dependencies.embedded-graphics] optional = true -version = "0.6.0-alpha.2" +version = "0.6.0-alpha.3" [dev-dependencies] cortex-m = "0.6.1" diff --git a/README.md b/README.md index 379816d..ebc935f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # SSD1331 driver -[![Build Status](https://travis-ci.org/jamwaffles/ssd1331.svg?branch=master)](https://travis-ci.org/jamwaffles/ssd1331) +[![Build Status](https://circleci.com/gh/jamwaffles/ssd1331/tree/master.svg?style=shield)](https://circleci.com/gh/jamwaffles/ssd1331/tree/master) +[![Crates.io](https://img.shields.io/crates/v/ssd1331.svg)](https://crates.io/crates/ssd1331) +[![Docs.rs](https://docs.rs/ssd1331/badge.svg)](https://docs.rs/ssd1331) [![SSD1331 display showing Ferris](readme_banner.jpg?raw=true)](examples/image.rs) diff --git a/build.sh b/build.sh index 517061f..5710494 100755 --- a/build.sh +++ b/build.sh @@ -17,14 +17,16 @@ cargo fmt --all -- --check cargo build --target $TARGET --all-features --release cargo test --lib --target x86_64-unknown-linux-gnu - -# Always test docs against thumbv7m target as the complete readme example needs to compile against it -cargo test --doc --target thumbv7m-none-eabi +cargo test --doc --target x86_64-unknown-linux-gnu if [ -z $DISABLE_EXAMPLES ]; then cargo build --target $TARGET --all-features --examples fi +# Remove stale docs - the linkchecker might miss links to old files if they're not removed +cargo clean --doc +cargo clean --doc --target $TARGET + cargo doc --all-features --target $TARGET linkchecker target/$TARGET/doc/ssd1331/index.html diff --git a/examples/bmp.rs b/examples/bmp.rs index eb500b7..1da8ffe 100644 --- a/examples/bmp.rs +++ b/examples/bmp.rs @@ -87,7 +87,7 @@ fn main() -> ! { (h as u32 - im.height()) as i32 / 2, )); - disp.draw(moved.into_iter()); + moved.draw(&mut disp); disp.flush().unwrap(); diff --git a/examples/graphics.rs b/examples/graphics.rs index 72e6bf4..57cc7dd 100644 --- a/examples/graphics.rs +++ b/examples/graphics.rs @@ -25,7 +25,8 @@ use embedded_graphics::{ geometry::Point, pixelcolor::Rgb565, prelude::*, - primitives::{Circle, Line, Rectangle, Triangle}, + primitives::{Circle, Rectangle, Triangle}, + style::PrimitiveStyleBuilder, }; use panic_semihosting as _; use ssd1331::{DisplayRotation::Rotate0, Ssd1331}; @@ -80,27 +81,36 @@ fn main() -> ! { disp.init().unwrap(); disp.flush().unwrap(); - disp.draw( - Triangle::new( - Point::new(8, 16 + 16), - Point::new(8 + 16, 16 + 16), - Point::new(8 + 8, 16), + Triangle::new( + Point::new(8, 16 + 16), + Point::new(8 + 16, 16 + 16), + Point::new(8 + 8, 16), + ) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Rgb565::RED) + .stroke_width(1) + .build(), + ) + .draw(&mut disp); + + Rectangle::new(Point::new(36, 16), Point::new(36 + 16, 16 + 16)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Rgb565::GREEN) + .stroke_width(1) + .build(), ) - .stroke(Some(Rgb565::RED)) - .into_iter(), - ); - - disp.draw( - Rectangle::new(Point::new(36, 16), Point::new(36 + 16, 16 + 16)) - .stroke(Some(Rgb565::GREEN)) - .into_iter(), - ); - - disp.draw( - Circle::new(Point::new(72, 16 + 8), 8) - .stroke(Some(Rgb565::BLUE)) - .into_iter(), - ); + .draw(&mut disp); + + Circle::new(Point::new(72, 16 + 8), 8) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Rgb565::BLUE) + .stroke_width(1) + .build(), + ) + .draw(&mut disp); disp.flush().unwrap(); diff --git a/examples/image.rs b/examples/image.rs index c2d382f..6d27284 100644 --- a/examples/image.rs +++ b/examples/image.rs @@ -85,7 +85,7 @@ fn main() -> ! { let im = ImageLE::new(include_bytes!("./ferris.raw"), 86, 64) .translate(Point::new((96 - 86) / 2, 0)); - disp.draw(im.into_iter()); + im.draw(&mut disp); disp.flush().unwrap(); diff --git a/examples/rotation.rs b/examples/rotation.rs index c4921e3..fd0bbd4 100644 --- a/examples/rotation.rs +++ b/examples/rotation.rs @@ -26,7 +26,7 @@ #![no_main] use cortex_m_rt::{entry, exception, ExceptionFrame}; -use embedded_graphics::{pixelcolor::BinaryColor, prelude::*}; +use embedded_graphics::{image::ImageLE, pixelcolor::BinaryColor, prelude::*}; use panic_semihosting as _; use ssd1331::{DisplayRotation, Ssd1331}; use stm32f1xx_hal::{ @@ -89,7 +89,9 @@ fn main() -> ! { let im = ImageLE::::new(include_bytes!("./rust.raw"), 64, 64); // Map on/off image colours to Rgb565::BLACK/Rgb565::WHITE - disp.draw(im.into_iter().map(|p| Pixel(p.0, p.1.into()))); + im.into_iter() + .map(|p| Pixel(p.0, p.1.into())) + .draw(&mut disp); disp.flush().unwrap(); diff --git a/examples/text.rs b/examples/text.rs index a367c6b..170f3e6 100644 --- a/examples/text.rs +++ b/examples/text.rs @@ -22,7 +22,13 @@ use cortex_m_rt::{entry, exception, ExceptionFrame}; use embedded_graphics::{ - fonts::Font6x8, geometry::Point, pixelcolor::Rgb565, prelude::*, text_6x8, + egtext, + fonts::{Font6x8, Text}, + geometry::Point, + pixelcolor::Rgb565, + prelude::*, + style::TextStyleBuilder, + text_style, }; use panic_semihosting as _; use ssd1331::{DisplayRotation::Rotate0, Ssd1331}; @@ -80,27 +86,30 @@ fn main() -> ! { // Red with a small amount of green creates a deep orange colour let rust = Rgb565::new(0xff, 0x07, 0x00); - disp.draw( - Font6x8::render_str("Hello world!") - .stroke(Some(Rgb565::WHITE)) - .into_iter(), - ); - disp.draw( - Font6x8::render_str("Hello Rust!") - .stroke(Some(rust)) - .translate(Point::new(0, 16)) - .into_iter(), - ); + Text::new("Hello world!", Point::zero()) + .into_styled( + TextStyleBuilder::new(Font6x8) + .text_color(Rgb565::WHITE) + .build(), + ) + .draw(&mut disp); + + Text::new("Hello Rust!", Point::new(0, 16)) + .into_styled(TextStyleBuilder::new(Font6x8).text_color(rust).build()) + .draw(&mut disp); // Macros can also be used - disp.draw( - text_6x8!( - "Hello macros!", - stroke = Some(Rgb565::RED), - fill = Some(Rgb565::GREEN) + egtext!( + text = "Hello macros!", + top_left = (0, 0), + style = text_style!( + font = Font6x8, + text_color = Rgb565::RED, + background_color = Rgb565::GREEN ) - .translate(Point::new(0, 24)), - ); + ) + .translate(Point::new(0, 24)) + .draw(&mut disp); disp.flush().unwrap(); diff --git a/src/display.rs b/src/display.rs index e612ed1..9391fa1 100644 --- a/src/display.rs +++ b/src/display.rs @@ -20,13 +20,13 @@ const BUF_SIZE: usize = 96 * 64 * 2; /// /// ```rust /// use embedded_graphics::{ -/// fonts::Font6x8, +/// fonts::{Font6x8, Text}, /// geometry::Point, /// image::ImageLE, /// pixelcolor::Rgb565, /// prelude::*, /// primitives::{Circle, Line, Rectangle}, -/// Drawing, +/// style::{PrimitiveStyleBuilder, TextStyleBuilder}, /// }; /// use ssd1331::{DisplayRotation::Rotate0, Ssd1331}; /// # use ssd1331::test_helpers::{Pin, Spi}; @@ -42,31 +42,42 @@ const BUF_SIZE: usize = 96 * 64 * 2; /// display.init().unwrap(); /// display.flush().unwrap(); /// -/// display.draw( -/// Line::new(Point::new(0, 0), Point::new(16, 16)) -/// .stroke(Some(Rgb565::RED)) -/// .stroke_width(1) -/// .into_iter(), -/// ); -/// display.draw( -/// Rectangle::new(Point::new(24, 0), Point::new(40, 16)) -/// .stroke(Some(Rgb565::new(255, 127, 0))) -/// .stroke_width(1) -/// .into_iter(), -/// ); -/// display.draw( -/// Circle::new(Point::new(64, 8), 8) -/// .stroke(Some(Rgb565::GREEN)) -/// .stroke_width(1) -/// .into_iter(), -/// ); -/// display.draw(&image); -/// display.draw( -/// Font6x8::render_str("Hello Rust!") -/// .translate(Point::new(24, 24)) -/// .style(Style::stroke(Rgb565::RED)) -/// .into_iter(), -/// ); +/// Line::new(Point::new(0, 0), Point::new(16, 16)) +/// .into_styled( +/// PrimitiveStyleBuilder::new() +/// .stroke_color(Rgb565::RED) +/// .stroke_width(1) +/// .build(), +/// ) +/// .draw(&mut display); +/// +/// Rectangle::new(Point::new(24, 0), Point::new(40, 16)) +/// .into_styled( +/// PrimitiveStyleBuilder::new() +/// .stroke_color(Rgb565::new(255, 127, 0)) +/// .stroke_width(1) +/// .build(), +/// ) +/// .draw(&mut display); +/// +/// Circle::new(Point::new(64, 8), 8) +/// .into_styled( +/// PrimitiveStyleBuilder::new() +/// .stroke_color(Rgb565::GREEN) +/// .stroke_width(1) +/// .build(), +/// ) +/// .draw(&mut display); +/// +/// image.draw(&mut display); +/// +/// Text::new("Hello Rust!", Point::new(24, 24)) +/// .into_styled( +/// TextStyleBuilder::new(Font6x8) +/// .text_color(Rgb565::RED) +/// .build(), +/// ) +/// .draw(&mut display); /// /// // Render graphics objects to the screen /// display.flush().unwrap(); @@ -339,39 +350,38 @@ where } } +#[cfg(feature = "graphics")] +use core::convert::TryInto; #[cfg(feature = "graphics")] use embedded_graphics::{ drawable, + geometry::Size, pixelcolor::{ raw::{RawData, RawU16}, Rgb565, }, - Drawing, + DrawTarget, }; #[cfg(feature = "graphics")] -impl Drawing for Ssd1331 +impl DrawTarget for Ssd1331 where SPI: hal::blocking::spi::Write, DC: OutputPin, { - fn draw(&mut self, item_pixels: T) - where - T: IntoIterator>, - { - // Filter out pixels that are off the top left of the screen - let on_screen_pixels = item_pixels - .into_iter() - .filter(|drawable::Pixel(point, _)| point.x >= 0 && point.y >= 0); - - for drawable::Pixel(point, color) in on_screen_pixels { - // NOTE: The filter above means the coordinate conversions from `i32` to `u32` should - // never error. - self.set_pixel( - point.x as u32, - point.y as u32, - RawU16::from(color).into_inner(), - ); - } + fn draw_pixel(&mut self, pixel: drawable::Pixel) { + let drawable::Pixel(pos, color) = pixel; + + self.set_pixel( + (pos.x).try_into().unwrap(), + (pos.y).try_into().unwrap(), + RawU16::from(color).into_inner(), + ); + } + + fn size(&self) -> Size { + let (w, h) = self.dimensions(); + + Size::new(w as u32, h as u32) } } diff --git a/src/lib.rs b/src/lib.rs index 5bccf8f..9c0856b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,7 +61,7 @@ //! // Center the image on the display //! let moved = im.translate(Point::new((96 - im.width() as i32) / 2, 0)); //! -//! display.draw(moved.into_iter()); +//! moved.draw(&mut display); //! //! display.flush().unwrap(); //! ```