Code Monkey home page Code Monkey logo

embedded-graphics's People

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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

embedded-graphics's Issues

Check for font overdraw

When running

cargo run -p simulator --example fonts

A black square is seen at the end of the Inverse 6x8 example. This probably shouldn't be there:

image

Investigate if it's common to all fonts, or just the 6x8 font, and rectify if it's a bug.

Drawable Trait

The documentation of the Drawable trait states:

/// Marks an object as "drawable". Must be implemented for all graphics objects
pub trait Drawable {}

Is this still true? The current code doesn't seem to use this trait and the only references (other than empty implementations) are comments referring to a non existent draw() method.

Why is translate always making a new object?

Hi,

    fn translate(&self, by: Coord) -> Self {
        Self {
            offset: (self.offset.0 + by.0, self.offset.1 + by.1),
            ..*self
        }
    }

While looking into the project i got a bit confused by the part above.
Why does translate always make a modified "clone" of the object instead of modifying itself?
I would have expected sth like the following, where you need to explicitly clone the object if you still need it:

    fn translate(&mut self, by: Coord) {
        self.offset = (self.offset.0 + by.0, self.offset.1 + by.1)
    }

Strange Behaviour with 0.4.2 from crates.io

After testing my crate for a few hours I realised that the new crates.io 0.4.2 is not the same as the github master 0.4.2 release.
Somehow the patch hasn't arrived on crates.io even though there was the new release.

Easy way to test it:
Go to the simulator and use the embedded-graphics version from crates.io instead of the local one and then run cargo run --example fonts

Display simulator/plotter

As demonstrated by #4 and #11, it would be great to have a display simulator to render things out into. Extending it to do snapshotting as part of the CI process would be super useful.

[unsorted] Enchancements

Continue of rust-embedded/wg#22 (comment).

This is assorted thought, to discuss general library improvements, prior to create separate issues. At first, i'd like to say, that i don't invent something new. Everything described below were already implemented in other languages, and i only point to missed things. I strongly recommend to investigate u8g2 sources and wiki as source of ideas. That doesn't mean it's ideal, but it has a lot of useful solutions like font formats.

Basic things (to be honest, what i need fisrt to migrate from C to Rust :)

  • The most demanded, more font sizes (up to 24-30px), with tools to extract required char subsets. +more compact font store format.
  • (probably) More compact framebuffer format for monochrome display (1 byte per 8 pixels, in your ssd1306)
  • (probably) Async inteface support

new

  • (probably) Consider what is needed to be a good base api layer for window manager (library to create interactive menus and other things). I did not investigated this area yet. Just suppose, that some menu system is required in many devices with LCD.

This does not include all supported u8g2 features. Need time to collect more details and analyze other libs.


Answers to your questions in rust-embedded/wg#22 (comment):

The fonts are stored as 1 byte per 8 pixels, so I'm not sure how much more compact they could get without using some sort of runtime decoding which I'd like to steer away from.

See https://github.com/olikraus/u8g2/wiki/u8g2fontformat

  • At first, you do not support partial lists & lists with holes. For example:
    • One may wish to have english and russian languages. But still work with "normal" strings when writing code. User should be able to extract only required chars, and font should be able to store those.
    • Mad case: one may wish to write "hello wold" only. Then all english letters are not required.
    • Real case: I need very big font (60px), but used to display digits only. Then i need only 0..9 and . chars to save space.
  • u8g2 seems to support some data compression, but i did not investigated how effective is it (for example, it does not use bytes to encode space).

May be, using u8g2 fonts format can be convenient, because you will be able to use existing tools until native ready.

Probably, fonts & tools could be in separate crate to avoid licences mixture.

I'm not sure what you mean for embedded-graphics as it doesn't use a framebuffer at all. Can you elaborate?

embedded-graphics itself does not use framebuffre, but ssd1306 has it https://github.com/jamwaffles/ssd1306/blob/master/src/mode/graphics.rs#L46.

Also, it may be useful to optimize display bulk writes and to stack async API calls effectively:

eg
  .draw_line(...)
  .draw_text(...)
  .draw_anything(...)
  .flush() // <- future

That's only a semantic example, convenient async api is a separate topic to discuss. Also result can affect decision, if embedded-graphics should have direct access to framebuffer or not.

I don't know your plans on this library. To be honest, i have some pressure from existing projects support, and would like to avoid direct participation in code development. But i could help to analyze existing solutions & suggest possible end-user api/tools designs, because have some experience with such things.

Let me know what do you think.

Ability to return chained iterators from functions

Code like this fails to compile:

fn multi() -> impl Iterator<Item = Pixel<PixelColorU8>> {
    let line = Line::new(Coord::new(0, 1), Coord::new(2, 3))
        .with_stroke(Some(1u8.into()))
        .into_iter();

    let circle = Circle::new(Coord::new(5, 5), 3)
        .with_stroke(Some(1u8.into()))
        .into_iter();

    line.chain(circle)
}

With the following error:

error[E0515]: cannot return value referencing temporary value
  --> src/main.rs:46:5
   |
38 |       let line = Line::new(Coord::new(0, 1), Coord::new(2, 3))
   |  ________________-
39 | |         .with_stroke(Some(1u8.into()))
   | |______________________________________- temporary value created here
...
46 |       line.chain(circle)
   |       ^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function

error: aborting due to previous error

It should work! Composing iterators (and caching the result if desired) is a key ergonomic feature of e-g. It currently doesn't work with a function call.

Make tinytga and tinybmp optional dependencies

It makes no sense to pull in tinytga and tinybmp by default. These should be optional features of embedded graphics.

TODO

  • Ensure that they are documented as such in the docs
    • ImageBMP page
    • ImageTGA page
    • README if any
    • Landing page feature list
  • Add some examples to the simulator to show usage

Closes #91

Docs

Add the no_missing_docs guard and write some "MVP" docs.

Better chaining/grouping

It's currently possible to chain drawable objects together like this:

let chained = Rect::new((0, 0), (1, 1), 1)
    .into_iter()
    .chain(Circle::new((2, 2), 1, 1).into_iter());

disp.draw(chained);

however it's not very ergonomic. It also makes doing transforms on the group as a whole quite difficult. To solve this, there should be a DrawableBuilder (or other named...) struct with an API that allows the following:

let chained = DrawableBuilder::new()
    .append(Rect::new((0, 0), (1, 1), 1))
    .append(Circle::new((2, 2), 1, 1));

disp.draw(chained.into_iter());

It should also implement the Transform trait so that the following is possible:

let chained = DrawableBuilder::new()
    .append(Rect::new((0, 0), (1, 1), 1))
    .append(Circle::new((2, 2), 1, 1))
    .translate((10, 10))
    .finish();

disp.draw(chained.into_iter());

Infinite font iterator when negative translation happens to be the font height

I've run into an issue where the fontbuilder iterator will loop indefinitely under certain translation conditions.

Here's a minimal example:

display.draw(Font6x12::render_str("Testing string")
            .with_stroke(Some(0xF1FA_u16.into()))
            .translate(Coord::new(0, -12))
            .into_iter());
display.flush();

if a negative y translation happens to be equal to the height of the font, it will loop indefinitely in here: https://github.com/jamwaffles/embedded-graphics/blob/master/embedded-graphics/src/fonts/font_builder.rs#L193

Add RGB565 pixel type

This is a more valid use of the PixelColorU* pattern - a pixel value that wraps a single u16 to provide an R5G6B5 colour type (and some util functions) commonly found in embedded/low bit depth display applications.

[sandbox] New font format & tools

That's a sandbox to discuss requirements for new font format, tools and related things.

Fonts:

  • Both monospace and proportional fonts should be supported
  • Should be extendable with kerning info in future (at binary format level)
  • What strings encoding should be used?
    • utf8 is preferable, but how difficult is it?
    • hieroglyphs?
    • ligatures? (probably - not in this life :)
  • Should we support marcos for recoding to write strings in convenient way? Example - if someone wish to use koi-8 encoding. Probably - no, because utf8 is preferable.
  • What source format is preferable for generated data? I'd prefer text .rs files (they should define complex data structures). Also, text format will allow to embed comments with source/copyrigth/license info
  • What optimizations needed for fast processing, to avoid bulk scans (and so we need such opts)? (sorting by glyph codes, etc)

Tools / data sources:

  • Small fonts should be pixel-perfect - take from BDF (X11 and other)
  • Big fonts should be taken from TTF (via ttf2bdf utility)
  • Allow strip char subsets to save space
  • Allow merge fonts (text + icons)
  • Remap charcodes (if font has koi-8 encoding, or if we merge icons)
  • Generate fonts demo page

Feedback needed. Add missed things.

Prelude

There should be a prelude that makes using the crate easier.

Tracking issue: BMP support

Use nom in no_std mode to parse BMP images. It should produce an iterator to stay true to the minimal-alloc philosophy of embedded_graphics.

Nalgebra support

Nalgebra now supports no_std. It should therefore be pretty easy to include in embedded-graphics behind a nalgebra feature. At minimum, it should redefine the Coord type to use a Nalgebra Vector2.

Rename Transform::translate to Transform::position

translate implies that a relative translation is being performed, however this is not the case. Instead, an absolute position for the top-left corner of an object is given. For example, thing.translate(-1, -1) positions thing at (-1, -1). This change opens up the API to a proper translate() where something like thing.position(10, 10).translate(5, 5) would result in thing being at position (15, 15).

Primitives are missing pixels?

Maybe it's just me but the triangle and the rectangle from the graphics example in the SSD1306 crate seem to be missing a pixel each in the lower right corner.

Fill in gaps for conversion to `PixelColorUN`

This is to reduce the number of errors due to expected but non-existent behaviour when using plain integers with embedded graphics.

Missing impls:

  • impl From<u16> for PixelColorU32 { /* ... */ }

Tracking issue: Macros for primitives

It should be possible to create a primitive using a terser, macro-based syntax. The exact syntax is as yet undefined, but it should be possible to define the primitive's dimensions (start/end coords, radius, etc) as well as styles in an extensible way.

Unfilled polygon support

It should be possible to create an open and closed line loop. Filled polygons can be added in a separate issue.

Fix Image16BPP byte ordering

The current implementation is incorrect; two bytes [ 0xcc, 0x00 ] that represent a single 16 bit pixel value are currently interpreted as 0x00cc_u16 which is incorrect; it should be 0xcc00.

Failing test case:

let image: Image16BPP<PixelColorU16> = Image16BPP::new(
    &[
        0xff, 0x00, 0x00, 0x00, 0xbb, 0x00, //
        0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, //
        0xee, 0x00, 0x00, 0x00, 0xaa, 0x00,
    ],
    3,
    3,
)
.translate(Coord::new(-1, -1));
let mut it = image.into_iter();

assert_eq!(
    it.next(),
    Some(Pixel(UnsignedCoord::new(0, 0), 0xcc00_u16.into()))
);
assert_eq!(
    it.next(),
    Some(Pixel(UnsignedCoord::new(1, 0), 0x0000_u16.into()))
);
assert_eq!(
    it.next(),
    Some(Pixel(UnsignedCoord::new(0, 1), 0x0000_u16.into()))
);
assert_eq!(
    it.next(),
    Some(Pixel(UnsignedCoord::new(1, 1), 0xaa00_u16.into()))
);

Documentation audit

As noticed in #62 (comment), there are missing docs on at least the image pages. The description for Image16BPP also describes it as an 8 bit image, which is obviously wrong.

ssd1306 broken by latest changes?

It seems something broke in the SSD1306 driver in the last few hours:

   Compiling ssd1306 v0.1.0 (file:///Users/egger/OSS/ssd1306)
error[E0061]: this function takes 3 parameters but 4 parameters were supplied
  --> examples/image_i2c.rs:56:14
   |
56 |     let im = Image1BPP::new(include_bytes!("./rust.raw"), 64, 64, (32, 0));
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters

error[E0061]: this function takes 1 parameter but 2 parameters were supplied
  --> examples/text_i2c.rs:51:15
   |
51 |     disp.draw(Font6x8::render_str("Hello world!", (0, 0)).into_iter());
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter

error[E0061]: this function takes 3 parameters but 4 parameters were supplied
  --> examples/rotation_i2c.rs:67:14
   |
67 |       let im = Image1BPP::new(
   |  ______________^
68 | |         include_bytes!("./rust.raw"),
69 | |         64,
70 | |         64,
71 | |         (w as u32 / 2 - 64 / 2, h as u32 / 2 - 64 / 2),
72 | |     );
   | |_____^ expected 3 parameters

error[E0061]: this function takes 1 parameter but 2 parameters were supplied
  --> examples/text_i2c.rs:52:15
   |
52 |     disp.draw(Font6x8::render_str("Hello Rust!", (0, 16)).into_iter());
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter

Make drawable objects stylable

For example, instead of just setting the border colour on a rect with Rect::new((0, 0), (10, 10), 1), it would be useful to be able to style all primitives::* objects.

There should be a Stylable trait that provides a with_style() method.

As a first step, styling should be able to set:

  • Border colour (1/0)
  • Fill colour (Some(1), Some(0), None)
  • Border width

with a Style struct. This struct should be applicable to any embedded-graphics drawable object. Unused styles should be ignored. For example, setting the fill colour of a Font makes no sense, so would be ignored. Likewise, setting the text colour for a Rect would also be ignored.

It should also have a Default so that only properties to change have to be supplied. This also allows easier future expansion. Struct property names should loosely follow the CSS spec, but this is not required if it doesn't make sense.

Example usage:

// Unfilled rect with solid border
let filledSquare = Rect::new((0, 0), (10, 10))
    .with_style(Style { border_color: 1 });

// Filled rect with clear, thicker border
let filledSquare = Rect::new((0, 0), (10, 10))
    .with_style(Style { border_color: 0, border_width: 2, background_color: Some(1) });

Line thickness support

#45 adds stroke width support to all primitives except lines. This is unexpected for the user and bad from a feature perspective so should be fixed.

Add partial draw support

It should be possible to get hold of an iterator to only generate pixels for part of the screen, as well as the top left and bottom right coordinates of that bounding box. Primitives like lines that don't update their entire bounding box should probably just return their default iterator which gives the same behaviour. The method to get the bounding box should still return the correct values though.

Cc yuri91/ili9341-rs#3 (comment)

First row of font background is off by one

As surfaced in #51, there's a strange artifact when using a background for a font:

image

The black rectangle (black font on black background) to the middle left has its first row shifted by one which obviously shouldn't happen.

Tracking issue: TGA support

Use nom in no_std mode to parse both uncompressed and RLE (Run Length Encoding) compressed TGA images. It should produce an iterator to stay true to the minimal-alloc philosophy of embedded_graphics.

Some work has been started here.

Use fonts from u8g2

U8g2 has a pretty big collection of fonts. It would be great to have support for them in embedded-graphics. This issue is a tracking issue of sorts to define what should be done as a minimum first step towards u8g2 font support.

Any code that aims to close this issue should:

  • Reuse as much u8g2 tooling as possible
  • Treat the u8g2 repository as the source of truth for fonts (no mirrors, etc)
  • Create embedded-graphics compatible font maps like the .raw files here.

The first implementation will be non-ideal, but will show where things can be fixed or improved with more optimisations and tooling in the future.

CC also #28 for some desired future features.

Expose a SizedDrawing trait for sized objects

A sized object in this context is an object (line, image, etc) where its size and offset in pixels is known. This will be everything currently included in embedded_graphics, but should be exposed as a separate SizedDrawing trait accompanying Drawing so that either graphics objects or displays that don't support setting a draw area don't have to implement it. Many displays support a partial screen draw to a given area which is much more efficient than updating the entire screen. It also makes using screens without a huge display buffer easier. A SizedDrawing object should also implement Drawing for compatibility reasons. - actually, no. This will make it a hard requirement which, for example, tiny devices with no framebuffer might not be able to fulfill.

Ensure a link is added to the doc landing page next to the "bla bla all you need to do is impl Drawing bla bla" section.

Moar fonts

From #22

Add more bitmap fonts:

  • A 24-30px font Can't find a pixel bitmap. Something to add in the future with a better font story
  • 6x12
  • 8x16
  • Number-only versions of the above fonts!

PixelColor types

The PixelColor trait is implemented for both PixelColorUx and ux (with x = 8, 16, 32). Why are the PixelColorUx types used instead of the unwrapped variants?

The PixelColorUx types don't seem to add any additional semantic information. Maybe it would be beneficial to add predefined types for commonly used pixel formats, like a newtype for RGB565 or an enum for 1 bpp displays.

Change iteration order

For epaper displays you can set the draw order to X ascending than Y ascending or Y than X for a region, but if you iterate over a rendered string from this library it gives X to Y for each character, then resets the Y range for the next character. If it went Y to X you could iterate directly to the device without a buffer. So basically going left to right rather than top to bottom for each character. I'm trying to use a chip with 20Kb of SRAM, so not enough for a framebuffer.

Colour support

Hi all,

I've been working on a SSD1351 driver crate based on the work done with the ssd1306. I am at the point where I want to start integrating embedded_graphics traits for more advanced graphic work. The SSD1351 being a 16bit colour display driver the current u8 for colour is not going to work, and in the future this crate should probably be able to support even higher colour depths.

Just wanted to kick off some discussion on the matter :)

RLE-encode font bitmaps

From #22, a first step towards more efficient/better fonts is to compress their binary representations in flash. RLE seems easy enough to do. Now that some more font processing needs to happen (PNG -> 8BPP -> RLE), this work should create a tool to help out. It will replace convert_1bpp.sh with a Rust program.

  • Create tool to convert PNG font bitmaps into 8BPP, RLE raw files. This should be a separate project using the Cargo workspaces feature
  • Add tool link/quick docs to readme
  • Convert raw font files and font iterators to use new RLE format.

Drawing integers and floats?

Hello,

std is of course unavailable in embedded so I can't use the normal number to string conversion, what is the best practice for drawing integers and floats? EG, I have an f32 that I want to display to 4 significant figures. If this doesn't exist I'd be more than happy to write it.

Thanks :)

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.