Post by MangyDog on Feb 9, 2018 6:31:06 GMT -8
A gift to the community for listening to me moan and whine all the time.
Also a huge thank you to James as his help lately has been utterly amazing...
For a project I'm working on I've been needing the ability to rotate text blocks.
Now there is already a function in the library as James pointed out in a previous topic of mine.
Sadly the cost of using this function is GRAM. As each text block is captured and internally converted to a bitmap asset.
For the most part this wouldn't normally be an issue, however if like my project you're really at the limits of your gram resources it simply wouldn't work.
So I created this function that builds rotated text blocks. Of course there are pros and cons here too, where before you sacrificed GRAM, here you sacrifice computational time.
This can really make the little Arduino cry... So if you plan a project with tons of rotated text blocks, consider a higher end MCU.
Now be aware, this is my current 100% working version of the function, but its not the final version. I may make updates later.
I'm also sure some smart alec could improve the maths and make it better...
I'm also happy for James to incorporate a this or a version of this into the main library...
A quick description of how it works.
This treats each character of the char array individually, using the bitmap matrix commands it then rotates and offsets the vertex render point so it lines up correctly to the adjacent character.
Currently this only has centred justification. No left or right.
I also added bunch and scale arguments, so you can shrink or expand the width of the text block. You can also use the scale x and y in conjunction to get some finer font sizes.
But this very limited. While scaling down is easy and doesn't really appear to have much of a limit outside of some pixels of a bitmap being lost as it reaches the pixel level scale, scaling up seems to be very limited and you'll struggle to reach 2 x original size.
For this function to work the bitmap size has to expand the frame size of each bitmap. When you have loads of overlapping bitmap frames this seems to cause render errors within the EVE chip. I don't think this is a software issue.
The errors can be seen a few different ways. The errors I've noticed so far are;
Strips or lines of other bitmap elements or vertex drawn objects disappearing randomly.
Gaps or lines appearing randomly down the screen.
The whole display image being stretched way beyond the screen size.
If you get any errors like this reduce the number you entered into either the bmp_width, bmp_height, scaleX, scaleY , arguments.
I've tried to avoid floating maths to limit the computational impact. So the scale is in terms of % 100 being full normal size 50% half size.
To use the function within your programme;
rotateTEXT("Some Text Here",6,PIXELS(X),PIXELS(Y),DEGREES(ANGLE),12,17,100,100,100);
Call the function, enter your text, this can be in the form of a char array, enter the bitmap handle of your font, set the position of the x and y. To help keep conformity to other built in functions the X and Y are in 16 bit, The function reduces them to per pixel placment. You can use the built in PIXEL() function to provide the 16bit placement. Angle is also 16bit for the same reason. Currently you have to manually enter the BMP width and height, once I know how to dynamically work out font handle sizes by just their bitmap handles these two arguments be removed. Bunch space affects the scale of the character placement but not bitmap size. So you can have your text block with text characters closer together or further apart. 100% normal. You can then enter the X and Y scales.
While for some this might be a simple function, i spent a good couple of weeks constantly editing and testing this thing to get it working how I think it should. Its been a lot of work. I'm not a mathematical genius by any stretch, much of this is from trial and error.
Feel free to use this function, I hope its useful...
if you like this send a thanks my way... Even better if you want to hire me... Get in touch. I need the work
Also a huge thank you to James as his help lately has been utterly amazing...
For a project I'm working on I've been needing the ability to rotate text blocks.
Now there is already a function in the library as James pointed out in a previous topic of mine.
Sadly the cost of using this function is GRAM. As each text block is captured and internally converted to a bitmap asset.
For the most part this wouldn't normally be an issue, however if like my project you're really at the limits of your gram resources it simply wouldn't work.
So I created this function that builds rotated text blocks. Of course there are pros and cons here too, where before you sacrificed GRAM, here you sacrifice computational time.
This can really make the little Arduino cry... So if you plan a project with tons of rotated text blocks, consider a higher end MCU.
Now be aware, this is my current 100% working version of the function, but its not the final version. I may make updates later.
I'm also sure some smart alec could improve the maths and make it better...
I'm also happy for James to incorporate a this or a version of this into the main library...
A quick description of how it works.
This treats each character of the char array individually, using the bitmap matrix commands it then rotates and offsets the vertex render point so it lines up correctly to the adjacent character.
Currently this only has centred justification. No left or right.
I also added bunch and scale arguments, so you can shrink or expand the width of the text block. You can also use the scale x and y in conjunction to get some finer font sizes.
But this very limited. While scaling down is easy and doesn't really appear to have much of a limit outside of some pixels of a bitmap being lost as it reaches the pixel level scale, scaling up seems to be very limited and you'll struggle to reach 2 x original size.
For this function to work the bitmap size has to expand the frame size of each bitmap. When you have loads of overlapping bitmap frames this seems to cause render errors within the EVE chip. I don't think this is a software issue.
The errors can be seen a few different ways. The errors I've noticed so far are;
Strips or lines of other bitmap elements or vertex drawn objects disappearing randomly.
Gaps or lines appearing randomly down the screen.
The whole display image being stretched way beyond the screen size.
If you get any errors like this reduce the number you entered into either the bmp_width, bmp_height, scaleX, scaleY , arguments.
I've tried to avoid floating maths to limit the computational impact. So the scale is in terms of % 100 being full normal size 50% half size.
To use the function within your programme;
rotateTEXT("Some Text Here",6,PIXELS(X),PIXELS(Y),DEGREES(ANGLE),12,17,100,100,100);
Function | The text you want | BMP Handle of Font | X Position | Y Position | ANGLE | Font BMP Width | Font BMP Height | Bunch Space Scale | ScaleX | ScaleY |
rotateTEXT | "Some Text Here" | 6, | PIXELS(X), | PIXELS(Y), | DEGREES(ANGLE), | 12, | 17, | 100, | 100, | 100); |
Call the function, enter your text, this can be in the form of a char array, enter the bitmap handle of your font, set the position of the x and y. To help keep conformity to other built in functions the X and Y are in 16 bit, The function reduces them to per pixel placment. You can use the built in PIXEL() function to provide the 16bit placement. Angle is also 16bit for the same reason. Currently you have to manually enter the BMP width and height, once I know how to dynamically work out font handle sizes by just their bitmap handles these two arguments be removed. Bunch space affects the scale of the character placement but not bitmap size. So you can have your text block with text characters closer together or further apart. 100% normal. You can then enter the X and Y scales.
While for some this might be a simple function, i spent a good couple of weeks constantly editing and testing this thing to get it working how I think it should. Its been a lot of work. I'm not a mathematical genius by any stretch, much of this is from trial and error.
Feel free to use this function, I hope its useful...
if you like this send a thanks my way... Even better if you want to hire me... Get in touch. I need the work
void rotateTEXT(const char* text, uint8_t font_handle, uint16_t x, uint16_t y, int16_t angle, uint8_t bmp_width, uint8_t bmp_height, uint8_t space,
uint8_t scaleX, uint8_t scaleY)
{
/*
* Bmp_width/height hopefully would be automated in time. But currently manually inputed.
*
* space is the space between characters, how close they bunch up.
*
* 100 = 100% normal spacing 50 = 50% spacing bringing characters closer by half
*
* 0 would place all characters at the same point.
*
* scaleX scales the text in X reducing or enlarging its width, y does it in y.
* When scaling X the whole text block is scaled together.
*
* If scaling X and Y together you can get finer font sizes between set fonts, at the cost of text bitmap image quality when enlarging.
* Useful for minor font size changes.
*
*/
uint16_t frame_width = space * (scaleX * bmp_width / 100) / 100;
uint16_t frame_height = space * (scaleY * bmp_height / 100) / 100;
int frame_size = (frame_width > frame_height ? frame_width : frame_height);
x = x / 16;
y = y / 16;
x = x - frame_size / 2 - (15 * frame_size / 100); // - (frame_size / 12); //(bmp_width*0.3);
y = y - frame_size / 2 - (15 * frame_size / 100); // - (frame_size / 17); //(bmp_height*0.3);
int size = strlen(text);
GD.SaveContext();
GD.Begin(BITMAPS);
for (uint8_t i = 0; i < size; i++)
{
GD.cmd_loadidentity();
GD.cmd_translate((frame_size * 65536) / 2 + (15 * frame_size / 100 * 65536), (frame_size * 65536) / 2 + (15 * frame_size / 100 * 65536));
GD.cmd_rotate(angle);
GD.cmd_translate(-(frame_size * 65536) / 2 + (15 * frame_size / 100 * 65536), -(frame_size * 65536) / 2 + (15 * frame_size / 100 * 65536));
if (scaleX != 100 || scaleY != 100)
{
GD.cmd_translate((frame_size * 65536) / 2, (frame_size * 65536) / 2);
GD.cmd_scale(65536 / 100 * scaleX, 65536 / 100 * scaleY);
GD.cmd_translate(-(frame_size * 65536) / 2, -(frame_size * 65536) / 2);
}
GD.cmd_setmatrix();
GD.BitmapHandle(font_handle);
GD.BitmapSize(BILINEAR, BORDER, BORDER, (frame_size * 1.5), (frame_size * 1.5));
GD.Cell(static_cast<int>(text[i]));
uint16_t radius = 0;
if (size % 2 == 0)
{
radius = -(frame_width * (size / 2)) + (frame_width * (i + .5));
}
else
{
radius = -(frame_width * (size / 2)) + (frame_width * (i));
}
uint16_t ax = 16 * x + GD.rcos(16 * radius, angle);
uint16_t ay = 16 * y + GD.rsin(16 * radius, angle);
GD.Vertex2f(ax, ay);
}
GD.RestoreContext();
GD.End();
}