Giter Club home page Giter Club logo

embedded-text's Introduction

Embedded graphics logo

Build Status Crates.io Docs.rs embedded-graphics on Matrix

Embedded graphics

Embedded-graphics is a 2D graphics library that is focused on memory constrained embedded devices.

A core goal of embedded-graphics is to draw graphics without using any buffers; the crate is no_std compatible and works without a dynamic memory allocator, and without pre-allocating large chunks of memory. To achieve this, it takes an Iterator based approach, where pixel colors and positions are calculated on the fly, with the minimum of saved state. This allows the consuming application to use far less RAM at little to no performance penalty.

It contains built in items that make it easy to draw 2D graphics primitives:

Additional functions provided by external crates

Embedded-graphics is designed to be extended by the application or other crates. Examples of this are adding support for different image formats or implementing custom fonts.

Note that some of these crates may not support the latest version of embedded-graphics.

If you know of a crate that is not in this list, please open an issue to add it.

Display drivers

To support many different kinds of display, embedded-graphics doesn't include any drivers directly but provides the DrawTarget API in embedded-graphics-core that can be implemented by external crates. In addition to the drivers for real displays, the simulator can be used to test code during development.

Photographs showing embedded-graphics running on physical display hardware.

These are just some of the displays the community has added embedded-graphics support to. This list is taken from the dependent crates list on crates.io so might be missing some unpublished entries. Please open an issue if there's a display driver that should be added to this list.

Note that some drivers may not support the latest version of embedded-graphics.

  • embedded-graphics-web-simulator: Simulated display in your browser via Webassembly
  • epd-waveshare Driver for various ePaper displays (EPD) from Waveshare
  • hub75: A rust driver for hub75 rgb matrix displays
  • ili9341: A platform agnostic driver to interface with the ILI9341 (and ILI9340C) TFT LCD display
  • ls010b7dh01: A platform agnostic driver for the LS010B7DH01 memory LCD display
  • push2_display: Ableton Push2 embedded-graphics display driver
  • retro-display: Display drivers for retro-computers incl. Commodore 64
  • sh1106: I2C driver for the SH1106 OLED display
  • sh1108: I2C/SPI driver for the SH1108 OLED display
  • smart-leds-matrix: Driver for smart LED (like ws2812) based LED matrixes.
  • ssd1306: I2C and SPI (4 wire) driver for the SSD1306 OLED display
  • ssd1309: I2C/SPI driver for the SSD1309 OLED display written in 100% Rust.
  • ssd1322: Pure Rust driver for the SSD1322 OLED display chip
  • ssd1331: SPI (4 wire) driver for the SSD1331 OLED display
  • ssd1351: SSD1351 driver
  • ssd1675: Rust driver for the Solomon Systech SSD1675 e-Paper display (EPD) controller
  • st7565: SPI driver for ST7565 based displays
  • st7735-lcd: Rust library for displays using the ST7735 driver
  • st7789: A Rust driver library for ST7789 displays
  • st7920: ST7920 LCD driver in Rust
  • gc9a01-rs: SPI 4-wire driver for the Gc9a01 display driver

Simulator

Embedded graphics comes with a simulator! The simulator can be used to test and debug embedded graphics code, or produce examples and interactive demos to show off embedded graphics features.

A screenshot of embedded-graphics running in its simulator.

Take a look at the examples repository to see what embedded-graphics can do, and how it might look on a display. You can run the examples like this:

git clone https://github.com/embedded-graphics/examples.git
cd examples/eg-0.7

cargo run --example hello-world

Crate features

Additional features can be enabled by adding the following features to your Cargo.toml.

  • nalgebra_support - use the Nalgebra crate with no_std support to enable conversions from nalgebra::Vector2 to Point and Size.

  • fixed_point - use fixed point arithmetic instead of floating point for all trigonometric calculation.

  • defmt - provide implementations of defmt::Format for all types where possible. defmt is a library for logging that moves as much work as possible over to a separate logging machine, making it especially suited to low-resource MCUs. Note that defmt might not work with older versions of rustc that are otherwise supported by embedded-graphics.

Migrating from older versions

Implementing embedded_graphics support for a display driver

To add support for embedded-graphics to a display driver, DrawTarget from embedded-graphics-core must be implemented. This allows all embedded-graphics items to be rendered by the display. See the DrawTarget documentation for implementation details.

Examples

Drawing examples

A grid of screenshots showing primitives, text and other items that can be drawn using embedded-graphics.

Example usage of drawing primitives, text and images with embedded-graphics can be found here.

Shapes and text

The following example draws some shapes and text to a FrameBuffer in place of target hardware. The simulator can also be used for debugging, development or if hardware is not available.

use embedded_graphics::{
    framebuffer::{buffer_size, Framebuffer},
    mono_font::{ascii::FONT_6X10, MonoTextStyle},
    pixelcolor::{raw::LittleEndian, BinaryColor},
    prelude::*,
    primitives::{
        Circle, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle, StrokeAlignment, Triangle,
    },
    text::{Alignment, Text},
    mock_display::MockDisplay,
};

fn main() -> Result<(), std::convert::Infallible> {
    // Create a new framebuffer
    let mut display = Framebuffer::<
       BinaryColor,
       _,
       LittleEndian,
       320,
       240,
       { buffer_size::<BinaryColor>(320, 240) },
  >::new();

    // Create styles used by the drawing operations.
    let thin_stroke = PrimitiveStyle::with_stroke(BinaryColor::On, 1);
    let thick_stroke = PrimitiveStyle::with_stroke(BinaryColor::On, 3);
    let border_stroke = PrimitiveStyleBuilder::new()
        .stroke_color(BinaryColor::On)
        .stroke_width(3)
        .stroke_alignment(StrokeAlignment::Inside)
        .build();
    let fill = PrimitiveStyle::with_fill(BinaryColor::On);
    let character_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);

    let yoffset = 10;

    // Draw a 3px wide outline around the display.
    display
        .bounding_box()
        .into_styled(border_stroke)
        .draw(&mut display)?;

    // Draw a triangle.
    Triangle::new(
        Point::new(16, 16 + yoffset),
        Point::new(16 + 16, 16 + yoffset),
        Point::new(16 + 8, yoffset),
    )
    .into_styled(thin_stroke)
    .draw(&mut display)?;

    // Draw a filled square
    Rectangle::new(Point::new(52, yoffset), Size::new(16, 16))
        .into_styled(fill)
        .draw(&mut display)?;

    // Draw a circle with a 3px wide stroke.
    Circle::new(Point::new(88, yoffset), 17)
        .into_styled(thick_stroke)
        .draw(&mut display)?;

    // Draw centered text.
    let text = "embedded-graphics";
    Text::with_alignment(
        text,
        display.bounding_box().center() + Point::new(0, 15),
        character_style,
        Alignment::Center,
    )
    .draw(&mut display)?;

    Ok(())
}

This example is also included in the examples repository and can be run using cargo run --example hello-world. It produces this output:

Embedded Graphics Simulator example screenshot

Additional examples can be found in the examples repository.

Minimum supported Rust version

The minimum supported Rust version for embedded-graphics is 1.71.1 or greater. Ensure you have the correct version of Rust installed, preferably through https://rustup.rs.

Development setup

Please see the development setup guide.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

embedded-text's People

Contributors

broderickcarlin avatar bugadani avatar derfetzer avatar rfuest avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

embedded-text's Issues

Vertical alignment

When using a fully specified bounding box, e-t could handle vertical alignment. May also be interesting for indeterminate height cases as well.

In the meantime, at least in theory, embedded-layout can be used to position textboxes vertically.

Improve whitespace behaviour

Currently, whitespace characters are transformed into single spaces and are handled inconsistently between alignments. Rework this based on some standard solution.

Maybe make behaviour configurable.

Flow text between text boxes

Latest embedded-graphics changes allow embedded-text to return residual text that was not rendered. This allows embedded-text users to allow implementing for example multiple text columns.

Tests

  • Set up render tests (compare against image in repo)
  • Cover more code with unit tests

Release

Some work is still necessary before releasing to crates.io:

  • Tests (test rendered output of examples?)
  • Clean up duplicated code
  • Documentation

SHY support

Allow placing soft hyphens in the source text that are only rendered if a word is wrapped

Allow partially drawn lines

Currently, the last line is always rendered even if it draws skipped if any of it is outside of the bounding box.

Make it configurable, perhaps through the textbox style.

Improve examples

The examples need a bit of care. The most immediate issue is that some examples contain invisible characters and most of them are poorly explained.

Vertical alignment and line background position.

Currently, when line_height > 0, the characters are rendered aligned to the top of the line. This should probably depend on the vertical alignment option, i.e. bottom aligned text should align to the bottom of the line.

Tabulature positions

TabSize will not be the best name when this lands...

Add a new variant to the tab configuration: TabSize::Positions(&'static [u32])

Refine what a word is

Currently, everything that is not a whitespace is parsed as a word, which works most of the time but for example recognizing hyphens could result in nicer word wrapping.

Configurable horizontal overflow

Currently instead of overflowing, e-t breaks words that are too long. There should be a configuration option to hide or overflow instead of breaking.

Configurable leading (and trailing) space rendering

In left (and maybe justified) aligned text, leading space can be:

  • ignored (first printed character is printed at line 1, column 1)
  • measured (first printed character is printed at line 1, column N, nothing drawn until then)
  • rendered (probably obvious)
  • These options should probably be part of TextBoxStyle
  • Also, pass ignored whitespace sequences to plugins somehow.

interactive example hangs on switching to right alignment

When I start the interactive.rs example and cycle through the alignment modes the example hangs when I switch from CenterAligned to RightAligned. I seems to happen independent of the bounding box and can be reproduced with the default bounds.

Text editor plugin

Display a blinking cursor at the given offset. Implement hit-testing the text to retrieve a cursor offset.

Add TextBox background

Currently e-t doesn't support a background color setting for the entire text box. Having this feature would be useful if you want to dynamically update the content of a text box. Otherwise you need to clear the text box region before redrawing the text box to make sure none of the previous content remains. This can lead to a flickering display, if it is updated directly and doesn't use a framebuffer with explicit flushing.

Vertical Overdraw: End of text

When implementing a "console" like scenario using this, it would be simpler if we have an option to show the last characters rather than the first few when drawing.
For example, if the string is "1 2 3 4 5 ..... 100", today it would produce "1 2 3 4 .. 50" if the space is not enough. We might also want to show "51 52 53... 100" as on option so that we can keep on having a tail like command.

As an alternative, it would suffice that the struct return a "number of characters that would fit in the view" so that the user can remove the prefix (1 2 .. 50 in above example) as needed.

Feature flags

The fancy features in e-t have a performance cost here and there. Since the crate is aimed for embedded applications, maybe those features should be behind compile-time flags. How granular should this be?

  • special characters as a single feature + single feature flag for each special character?
  • feature flags for underline/crossed-out text styles?

These flags should be on by default, with clear documentation as to what disabling them means.

On the other hand, e-t currently uses several type-level configuration options. Maybe some of the extra features could be turned into such configuration options. Would this be a good idea?

Rectangle in prelude

Are you sure it's a good idea to include an external type in the prelude? I would agree that it's a good idea, if a program would only need to depend on e-t and not e-g. But all programs need to import types from e-g anyway, so that also including Rectangle isn't much more effort.

Support external font renderers

A possible idea of doing this is to create an interface that should be implemented by various fonts and font renderers. In this case, embedded-text should provide implementations for everything supported by embedded-graphics and probably for the most popular third party renderers, within reason.

External renderers may or may not support more fancy text decoration, so the interface should abstract over these somehow.

Line and paragraph spacing

cc @rfuest (because of this comment)

The current idea would be to provide 2(+1) functions:

  • line_height
  • line_spacing
  • (later a paragraph_spacing similar to line_spacing but it's far off)

Both of these functions would set the distance between baselines, but line_height would use pixels, while line_spacing would use a multiplicative factor (probably f32 simply because I find fixed point unwieldy) value. The latter would somewhat align to what word processors are doing, while the former doesn't require f32 support.

Internally, line_spacing could be something like a multiply-and-round implementation calling line_height.

Do you have any better idea for line spacing? One drawback is that it would lock paragraph_spacing into using an f32 value without a line_height analogue that would set spacing in pixels (thinking about it some more, a pixel-based paragraph spacing would also be confusing if it had the same meaning as line_height - I can imagine what a surprise it would be if a paragraph_spacing of 12 pixels would result in 4px of space...).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.