289 views
in GUI Development by

I want to make a "pixelated" border of a button with rounded corners. Easy, right? Unfortunately not.

My current version of EmWi is 10.00

Setting a path, add lines and arcs in the init method.

Path.SetMaxNoOfSubPaths( 1 );
Path.InitSubPath( 0, 8 + 4*3 );
Path.GetNoOfEdges( 0 );
Path.Begin( 0, 7, 0 );
Path.AddLine( 0, 32, 0 );
Path.AddArc( 0, 32, 7, 7, 7, -90.0, 0.0, 3 );
Path.AddLine( 0, 39, 32 );
Path.AddArc( 0, 32, 32, 7, 7, 0.0, 90.0, 3 );
Path.AddLine( 0, 7, 39 );
Path.AddArc( 0, 7, 32, 7, 7, 90.0, 180.0, 3 );
Path.AddLine( 0, 0, 7 );
Path.AddArc( 0, 7, 7, 7, 7, 180.0, 270.0, 3 );
Path.Close( 0 );

Add a StrokePath, set the created path and set Quality to false (=pixelated). Width of the StrokePath set to 1 (=Default, and intended).

Increasing the number of edges will lead to the arcs getting "missing pixels", which is not acceptable as well.

 

Now even if I ditch the rounded corners and just add lines, it will render vertical lines invisible.

Path.SetMaxNoOfSubPaths( 1 );
Path.InitSubPath( 0, 8 );
Path.GetNoOfEdges( 0 );
Path.Begin( 0, 0, 0 );
Path.AddLine( 0, 39, 0 );
Path.AddLine( 0, 39, 39 );
Path.AddLine( 0, 0, 39 );
Path.AddLine( 0, 0, 0 );
Path.Close( 0 );

The vertical lines are not visible on the prototyper neither on the device screen.

What am I doing wrong?

1 Answer

0 votes
by
 
Best answer

Hello Treeview,

very interesting question, which in fact is not that simple. In your example, all coordinates are integers. These values address exact the edges between two pixels. Trying to display 1-pixel thick line affects thus two pixels. The left half of such 1-pixel thick line occupies 50% of the left pixel and the right half occupies 50% of the right pixel. This effect can be seen when you enable the Quality mode again. The lines appear 2-pixel thick and semitransparent:

To stroke a line with exact 1 pixel width, it is necessary to specify as coordinate the center of a pixel. In other words to add 0.5 to the coordinates. To demonstrate the effect I have added an invocation of Translate( 0.5, 0.5 ) to your example:

Path.SetMaxNoOfSubPaths( 1 );

// Move the origin of the coordinate system to the center of a pixel
Path.Translate( 0.5, 0.5 );

Path.InitSubPath( 0, 8 );
Path.GetNoOfEdges( 0 );
Path.Begin( 0, 0, 0 );
Path.AddLine( 0, 39, 0 );
Path.AddLine( 0, 39, 39 );
Path.AddLine( 0, 0, 39 );
Path.AddLine( 0, 0, 0 );
Path.Close( 0 );

This results in correct displayed shape, regardless of the used Quality mode:

Adding Translate( 0.5, 0.5 ) to the code with rounded rectangle, produces following results. The results are better with this trick:

That the vertical 1-pixel line disappears with Quality=false, however, is not correct. The actual implementation of the raster algorithm fills a pixel with color only, when the drawn shape does occupy more than 50% of the pixel. In case of the 1-pixel thick vertical line, the line occupies exactly 50% of the left and 50% of the right pixel. Consequently, none of the both was filled. The line disappeared. We will modify this algorithm to handle this special case in a better manner. This modification will be added in the next version.

For the moment, if you want to display 1-pixel thick lines with Quality=false, use coordinates which address the center of a pixel (add 0.5 to the coordinates). Or you use the Translate( 0.5, 0.5 ) method. Also helpful is to specify the thickness of the stroked path to be greater than 1.0 pixel. For example, specify in the property Width 1.2 pixel.

Does it help you further?

Another hint: to display rounded rectangles, Embedded Wizard provides also the so-called Bitmap Frame view. Here, you design the rectangle with the rounded corners by using a graphic editor. Embedded Wizard composes from this image a scalable frame according to 9-slice approach. If the image is in ALPHA8 format, you can even colorize it at the runtime. The disadvantage of this approach: the radius of the corners is predetermined in the image. The advantage: the drawing operations can be accelerated by graphics HW (if such is available). Possibly, the usage of this view is sufficient for your application case? 

Best regards

Paul Banach

by
Dear Paul Banach

Thank you for this insight. The Idea to make it with Bitmap Frame occured to me right AFTER sending this question although I should have known. And you are right, that would normally be the better solution.

I would like to try the StrokePath anyways, since I have implemented a way to vary the radius of the rounded corners. Just like you described (Can you read my mind?). But if the Stroke Path attempt does not meet my customers needs, I will revert back to this approach.

Have a nice weekend.
by

Due to convenience and despite my first comment, I decided to stick with the Bitmap Frame solution. It is just so much simpler.

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...