Coder Social home page Coder Social logo

framebuffer size. about truetype_arduino HOT 27 CLOSED

k-omura avatar k-omura commented on May 30, 2024
framebuffer size.

from truetype_arduino.

Comments (27)

Yardie- avatar Yardie- commented on May 30, 2024 1

I have added a branch to my repo called minor mods.
It contains minor changes that I think are worth adding I will try and keep it close to your code.
With simple suggestions of working code.
I know I changed a lot over the last day or two.
Each commit will have a simple reason.

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024 1

Compound glyphs would be very very cool.

I actually think you were heading in an interesting direction with the first string width idea.
I have re-implemented your struct with a couple of variations.
I will get something going in the next few days and put it up on the yardie thread.

the glyph information read from the TTF
I understand now
these values are read from the ttf itself not the buffer or the window.
the this-> confused me.

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024 1

That is fine.
I now have fully functional code and will modify my "alternate" branch so that when you have holidays again next year you can come back and have a look.
Thank you K.

Enjoy.
:) Greg
ps.
the results so far
clock
an e-paper clock that looks like a post it note

from truetype_arduino.

k-omura avatar k-omura commented on May 30, 2024

Indeed, given future improvements such as rotation and error checking, the class needs to know the size of the framebuffer.
This requires changing the API arguments, so I think it's better to change the API alone first for future improvement.

In addition, I will add an argument in the direction of the bit arrangement of the frame buffer to expand the support for the frame buffer format.

In my opinion, the changes below are appropriate, but what about?

void truetypeClass::setFramebuffer(uint16_t _framebufferWidth, uint16_t _framebuffer_bit, uint8_t *_framebuffer)
↓
void truetypeClass::setFramebuffer(uint16_t _framebufferWidth, uint16_t _framebufferHeight, uint16_t _framebuffer_bit, uint8_t _framebufferDirection, uint8_t *_framebuffer)

I'm sorry to bother you to change the API, but I think this is necessary.
Or if you have any other solutions, please let me know.

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

No I totally agree.
I thought about this and looked at my old code.
and that is basically how I have ended up doing it

It doesn't worry me that you make any changes especially when they will make the whole project so much better.

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

here's something I just made to explain it.

rotations

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

The calls I make are

struct Image_Canvas canvas;
  uint8_t image[EPD_BYTES];
  canvas_make(&canvas, image, EPD_BYTES, EPD_WIDTH, EPD_HEIGHT, 0, 0xff);
  canvas.font_scale = 0.3;
  canvas_rotation_set(&canvas,0);
  canvas_draw_paragraph(&canvas, string, start_x , start_y, vertical_padding,  0x00, DRAW_STYLE_CENTRED); 

so it's pretty much the same as you are creating.
Mine will run on an ATtiny3216
But yours does TTF and that's the clincher.

from truetype_arduino.

k-omura avatar k-omura commented on May 30, 2024

Wow, that's a great rotation.
The feeling of proceeding with the implementation has increased!

As a confirmation, the coordinate transformation of rotation is based on your code below, isn't it?
#6 (comment)

Looking at your rotation, I noticed that I need to change the arguments and thinking of the setStringWidth method.
Need to set the upper side of the y coordinate as an argument.
Also, now the concept of start and end will change to the concept of range.
I will proceed with the implementation together with these!

Thanks Greg :)

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

My pleasure.
The code in #6 produced the above image it is the real output of that. It is s screen grab of the output of print_buffer.
I think the image is a good way to explain rotation.
By the way I prefer rotation as it's more like turning a page rather than turning yourself.
You are more than welcome to use it for explanation.

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

While you are working out the API why not put rotation as a variable in the string method
like void string(uint16_t _x, uint16_t _y, const String _string, uint8_t rotation=5);
Then in the string method
if(rotation==5) use the default rotation.
Otherwise use that rotation but don't change the default.
then
setRotation changes the default

to my mind that is the clearest way to implement it and also explain what is happening.
The constructor of the class doesn't need to set it. I would start at zero. Then if it is set by set

also changing the name of string to something like stringDraw might make it clearer.

I don't think you need to change
setStringWidth(
as it really only needs a length for what it does.
Actually
It could just be
setStringWidth( uint16_t characters_per_line=0xFFFF, bool line_break_on_word=false )
then running off the page is dealt with in addPixel

or simply add those two variables to string then it doesn't need to be implemented at all.
after all it is only relevant to that particular string not the buffer.

for line_break_on word have a simple routine that checks does a look back and look ahead
line_break_on_word is really a wish list thing and though and could easily be implemented later

The cool thing about using the rotation in addPixel
ALL the other code doesn't need to deal with.

All other code just references the top left corner of the character/word/sentence/paragraph
relative to the current rotation. Not the actual co-ordinates on the frame buffer. addPixel does that.

I hope that helps. It took me a long time to get my head around this in a real way.

By implementing my ideas in your code it means that all the work I have done on my code is not wasted.
I have been working to a point where I can help you.
I just didn't know it at the time.
The end result is I actually get what I wanted in the first place.
multiple scalable variable width TTF fonts on an epaper with a minimal library.

Now that! is so cool.

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

I just re-read your README
implementation of
Align text to the right.
Do you mean writing right to left for Japanese Arabic Chinese
siht ekil
I think that could be implemented with the same API as would be required by centring.
just a flag.
So you could mix fonts and r-l l-r sentences onto the same buffer.

When you go back to work I will start working on my fork and you can see where I get.
But for now have fun.
It will always be your code and your project.

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

After thinking about the right to left I think direction is actually better than rotation.
Thus there are 16 possibilities with centring as the 3rd bit
this can be delt with like int with the high bit as the direction flag
then the first two as rotation

0 left to right = 0b00000000
0 right to left = 0b10000000
90 left to right = 0b000000001
90 right to left = 0b10000001
180 left to right = 0b00000010
180 right to left = 0b10000010
270 left to right = 0b00000011
270 right to left = 0b10000011
or
direction & 0b00000000 == 0 rotation
direction & 0b00000010 == 90 degrees rotation
direction & 0b00000001 == 180 degrees rotation
direction & 0b00000011 == 270 degrees rotation
direction & 0b00000100 == centred
direction & 0b10000000 == right to left

that is really clean

string advances or reduces x on the basis of direction & 0b10000000

addPixel rotates on the basis of
direction & 0b00000000 == 0 rotation
direction & 0b00000010 == 90 degrees rotation
direction & 0b00000001 == 180 degrees rotation
direction & 0b00000011 == 270 degrees rotation

rotateText (new_rotation)
mask = direction & 0b11111100;
new_rotation &= 0b00000011;
direction = mask | new_rotation

haven't tested that but it should work

on further reflection an API change I would prefer is

string becomes textDraw
setStringWidth becomes textWidthMaximum or textWidthMax
setStringColor becomes setTextColor

also add
add
#define setTextColour setTextColor // color is american spelling only
setTextDirection
setTextLineSpacing
// this is an int to allow negatives and defines the amount the carriage return moves down each new line
// the character height is included then this is added/subtracted from this

this would be even clearer in the use of the class

text can be either a character a sentence or paragraph
and it is actually what we are dealing with here
string is really a programmers concept so people new to coding may have trouble with it.
https://en.wiktionary.org/wiki/text

Sorry for changing my advise but I think this will lead to a cleaner and clearer robust code base.
Easier adoption and less support problems.
As with all libraries change is inevitable.
I don't think anyone else is using this at the moment so now is the time.
Anyone who returns should be able to adapt your old code base to this fairly easily.

If we get it clean now you wont be bothered by confused users in the future and it can stay a fun project for both of us.
Simple clean API = 0 support requirements

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

here is the complete working code for my c file function
( I can send the whole code if you like but this is the relevant part )
the scaling and rotation are handled here
I think it is fairly self explanatory.

enum _Rotations
{
   Rotate_0 = 0,
   Rotate_90,
   Rotate_180,
   Rotate_270,
};

struct Image_Canvas
{
  uint8_t * image;
  uint16_t  width_in_pixels;
  uint16_t  height_in_pixels;
  uint32_t  bytes;    // max image size
  uint16_t  rotation;
  uint8_t   bit_type;
  double   font_scale;
  uint8_t   bg_colour;
};

bool canvas_pixel_set( struct Image_Canvas * canvas, int16_t page_x, int16_t page_y, bool colour_code)
{
  // translate x and y
  page_x = int16_t((double) page_x * canvas->font_scale);
  page_y = int16_t((double) page_y * canvas->font_scale);
  
  int16_t temp = page_x;
  int16_t canvas_x, canvas_y;
  if( canvas->rotation == Rotate_90 )
  {
    canvas_x = canvas->width_in_pixels -1 - page_y ;
    canvas_y =  temp;
  }
  else if( canvas->rotation == Rotate_180 )
  {
    canvas_x = canvas->width_in_pixels -1 - page_x;
    canvas_y = canvas->height_in_pixels -1 - page_y;
  }
  else if( canvas->rotation == Rotate_270 )
  {
    canvas_x = page_y ;
    canvas_y = canvas->height_in_pixels -1 - temp ;
  }
  else
  {
    canvas_y = page_y;
    canvas_x = page_x;
  }
  // now all is rotated test out of bounds
  // force to range to bit wise 0-7 or 0 to boundary number - 1 
  if (canvas_x < 0 || (uint16_t)canvas_x >= canvas->width_in_pixels || canvas_y < 0 || (uint16_t) canvas_y >= canvas->height_in_pixels)
    return false;  
 // the code below is for 1 bit per pixel this is the only part that needs to change for the other resolutions 4 and 8
 // as I now have a lillygo and an inkscape6 and it will help the ttf lib I will work on that in the next few days
  uint32_t byte_to_change = (canvas_x + canvas_y * canvas->width_in_pixels) / 8;
  uint16_t col = canvas_x / 8;
  uint8_t bit_mask = 1 << (7 - (canvas_x % 8)); // draw pixel left to right 
  
  if(colour_code)
  canvas->image[byte_to_change] &= ~bit_mask;//0x00;//unset the bit
  else
  canvas->image[byte_to_change] |= bit_mask ;// = 0xFF;//&= ~ bit_mask;
  return true;
}

from truetype_arduino.

k-omura avatar k-omura commented on May 30, 2024

Thank you for a lot of information!
I haven't caught up with everything yet, but it looks very useful.

I just re-read your README
implementation of
Align text to the right.
Do you mean writing right to left for Japanese Arabic Chinese
siht ekil

Regarding text alignment, I did not intend to arrange the characters from the right, but I intended to align them to the right.
(In Japanese, it is rare to write from the right in modern times)
The source of the idea comes from CSS.
https://www.w3schools.com/cssref/pr_text_text-align.ASP

Arranging letters from the right (typically Arabic) isn't a high priority for me, but if it's easy to see your idea, you might try implementing it!

Thank you as always!

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

Yes it is clear I need to find my cpp hat and start coding cpp.
If you spend the rest of your holiday coding the parts you enjoy.
Then when you have to go back to work I will pick up the ball.
I am semi retired and have a fair bit of available time to code.
Also I have some specific requirements for my real project which this will become a part of.
I finally have a better understanding of git and so I will keep my git up to date.
I have had some major variation ideas.
I would like to make this compatible in esp-idf and pi so no String references.
also I have a small simple graphics lib circles squares buttons I would like to hook in to the framework
I have had a very oop idea which I will attempt to implement.
ie
cpp template uint8_t_image
which frame_buffer implements
ttfClass extends frame_buffer
then
either
ttfClasArduino extends ttfClass adding String related code functions
or
ttfClass has #ifdef Arduino guards so the code will only be available in Arduino

the second option is probably the easier and less confusing way to go

simple_images extends frame_buffer
etc.
then
output_des simply includes the ttfClass and or simple_image

the API will basically stay the same but each part deals specifically with it's own individual issues only
easier to debug

I will play with the right to left when I finally get my head around the core.

Have fun
Greg

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

I have added rotation to my repo and modified setTextWidth to setTextBoundary
I haven't had a chance to test it yet but it compiles.
It's late now so I'm going to bed.

from truetype_arduino.

k-omura avatar k-omura commented on May 30, 2024

I ported your rotation code and tried it.
It worked perfectly and was impressed.
I also understood the idea of the coordinate system when rotating.
I could clearly understand why I didn't have to add arguments to setTextBoundary.

Only one thing to share,
You commented out the if statement for this->framebufferDirection inside setFramebuffer and addPixel, but here it was intended to set the framebuffer format type. (Readme framebuffer format section)
It does not deny your ideas about text rotation, alignment, and direction.
It's just my intended use of variables.
It's confusing because there are several directions of meaning.

good night!

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

Yes it is surprisingly simple.
Once you get your head around what is actually happening.

I'm glad you like it and it still works.
I still haven't had a chance to test it.
I generated a pull request which you can ignore or implement. That's up to you.
I tried to stay within your coding style.

The reason I just commented them out was to show that they are not required for this functionality.
Basically leaving the setTextBoundary as it is means that right until the addPixel we are thinking in one direction. It simplfies the code and concepts.
The next step was to use the textBoundaries as a sort of window for you text in the same rotation as the text. Centring and word wrap then work within that window.

Here's an image to show what I mean.
The blue line (boundary of "0") is the same boundary as the green one (boundary of "90").
the textDraw then uses that window to describe it's world.
if the text goes outside the window it returns to the start of the window
right or left depending on the textDirecton
Maintaining your idea of a window rather than just a length means that the draw text draw is also vertically restricted with in that window.
This would allow scrolling if someone wanted to go that far.
The code could simply truncate the string that was printed and the user could compare what was sent to what came back. and send that part later like the token in strtok

ALL the rest of the code can pretty much ignore rotation as they reference off 0x and 0y which is then translated in the rotation section
In the image rotation 0x and 0y are moved to the appropriate corner.
This part took me a long time to get my head around. I kept talking myself out of the obvious answer. It can't be that easy. That is where the serial print version of the code really helped.
rotations2

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

Hi K
If you have a moment could you please answer a question.

in the lines below

  result.advanceWidth = (result.advanceWidth * this->characterSize) / (this->yMax - this->yMin);
  result.leftSideBearing  = (result.leftSideBearing * this->characterSize) / (this->yMax - this->yMin);

what is the point of the / (this->yMax - this->yMin)
I am clearly miss understanding something here.

I have been working on getStringWidth
with a model that should make it easy to break on word or break on \n or \r
This would not change the api but may allow an additional method
paragraphDraw(String str, bool breakOnWord)
where you feed a string and it does carriage returns when appropriate without affecting your code or API.
I realise that this is not a priority for you and as such I thought it would be a good job for me as it is something I would like. without affecting your code.

Thanks Greg

from truetype_arduino.

k-omura avatar k-omura commented on May 30, 2024

When drawing the glyph information read from the TTF in the frame buffer, it means scaling to match the size of the character specified by the user.
Scaling is the following equation.
this->charactersize / (this->ymax - this->ymin)
scale

In the calculation, in many cases (this->characterSize) <(this->yMax - this->yMin), it will be caused by 0(int operation) to result.advanceWidth or result.leftSideBearing, Explicitly, the denominer will increase result.advanceWidth, result.leftSideBearing and this->characterSize ahead.

Anyway, this calculation means scaling from the TTF to the character size specified by the user.

I am very grateful to work on improving GetStringWidth.
Certainly, now this is not so high priority for me, and I'm thinking of working on 'Compound Glyphs'.

Speaking of which, it is very interesting to be called by one alphabet.
It seems to appear in 007 :) It is not a genius like Q

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

Hi K
Here is what I am working towards

void truetypeClass::paragraphDraw(int16_t _x, int16_t _y, int16_t _v_padding, uint8_t _justification, bool _break_on_nl, const wchar_t _character[]){
  /* concept  
   * this takes a string and finds how many words fit in the boundary 
   * it then justifies that line according to _justification
     * 0: left
     * 1: centre
     * 2: right
   * and writes that to the buffer.
   * it moves down the font height + v_padding ( which can be negative )
   * and repeats the process until either the end of the string 
   * or the bottom of the boundary is reached.
   * 
   * if the string is incomplete it returns the position in the string 
   * where the last character drawn occurred. So your code could 
   * show the rest of the text when you send it again from that point.
   * This opens many possibilities.  
   * 
   * Line breaks.
   * if _break_on_nl is true. 
     * The line will break and increment.
   * The escape characters \v or \f are treated as paragraph breaks 
   * and as such will always break the line and move down.
   * These are historic characters that are rarely used but still valid  
   * and as such are available to format your text easily. 
   * Simply insert them at the appropriate points in your text.
   *  
   */
}

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

Speaking of which, it is very interesting to be called by one alphabet.
It seems to appear in 007 :) It is not a genius like Q

Or like K in the movie "Men in Black"
Maybe you haven't seen it.

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

also a modification to

typedef struct {
uint16_t width; // width of string up to break point
uint16_t lastCharPoint; // last string position on break allows break string on width overrun and carriage return
uint16_t lastSpacePoint; // last string position on space character allows break string on word boundary
} ttStringWidth_t ;

ttStringWidth_t truetypeClass::getStringWidth(const wchar_t _character[], int16_t _current_x, bool _break_on_return=false, bool _break_on_word=false ){

the paragraph stuff could be simply in an example rather than the core
to keep the core tight.

But it is something I want and so as long as the core handles it I am happy.

from truetype_arduino.

k-omura avatar k-omura commented on May 30, 2024

I think it's good.
I thought about some of the structures of the structure, but couldn't think of a good one.
With this, it seems that you can measure the width of the string without doing complicated processing!
thanks!

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

Ok after quite a bit of testing I have realised that lastCharPoint and lastSpacePoint are problematic as the type of string we are dealing with varies. So these issues like centering and right justification are actually outside the scope of the class.
I will revert back to your version where getStringWidth returns a uint16_t equal to the width in pixels the string would use, and that is all it does.
I will write an example of how to centre or right justify the output.
It will keep your code tighter and simpler to maintain.

We simply need to have two regions.
framebufferBoundary width_in_pixels or bytes, height_in_pixels and bits_per_byte
---- This is relative to the array
and
textBoundary start_x start_y width_in_pixels and height_in_pixels
----- This is relative to the current rotation.

if draw accepts negatives and a start_x start_y as it now does true centering is possible.

if addPixel only draws anything inside the framebufferBoundary and textBoundary it stays clean and doesn't break.

This keeps it simple and flexible.

from truetype_arduino.

Yardie- avatar Yardie- commented on May 30, 2024

Hi K
At your leisure have a look at my "altenate" branch.
I have made a few changes without really changing your code a lot.
Hopefully it will be more esp-idf and pi compatible but I haven't tested that yet.
The input strings should be more compatible and robust.
I have added one public variable breakLine.
Which defaults to work as you have planned however allows printing text on one line without line breaks.
It relies on the addPixel just not drawing the out of bounds characters.
Over the next few weeks I will work on that branch.
I have added an example of justify.
Centre or right align the text simply using only the class.
Also I will test it in esp-idf and add an example for that.
I now have something I can work with and can move on with my stuff.
Also you can get back to casually improving the core.

Thanks heaps for your help.

from truetype_arduino.

k-omura avatar k-omura commented on May 30, 2024

Hi Greg

The challenge of the width of the string is very difficult.
I have not had a definitive idea yet.

When I think in implementing various ideas, what I think is not dependent on the framebuffer format as much as possible.
In other words, it is the simplest way that the frame buffer operation is integrated only in the addPixel

Unfortunately, my holiday ended. I have fewer time I can touch this code.
I am grateful for your various activities and I am confirmed as much as possible.

Thank you.

from truetype_arduino.

Related Issues (12)

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.