How can a circle be drawn exactly in the center of a watchface with Alloy?

I did the Alloy tutorial and tried the code for an analog watchface here. The center dot drawn with

render.drawCircle(black, cx, cy, 4, 0, 360);

isn’t exactly in the center. The diameter is 9 pixels instead of the expected 8 (with a radius of 4) which means it cannot be drawn in the center of a 260x260 pixels display like Gabbro. Is there any function that can do this? I searched the documentation but didn’t find anything so far.

1 Like

Good question! Let me check with the Moddable folks. In meantime, these are some other good drawing examples for Alloy pebble-examples/piu/watchfaces at main · Moddable-OpenSource/pebble-examples · GitHub

2 Likes

Here’s the answer - ‘Our circle drawing is your circle drawing – here’s the code. We call graphics_fill_circle with the coordinates provided by the caller. Note that the PebbleOS coordinates are integers, so they cannot express a fractional pixel.’

2 Likes

Thanks for the quick reply!

That’s interesting - Moddable uses

graphics_fill_circle(ctx, center, radius);

if a full circle is drawn (like in my example above), otherwise

graphics_fill_radial(ctx, r, GOvalScaleModeFillCircle, inset_thickness, from, to);

is used.

I noticed years ago (when programming a watchface in C) the same problem with graphics_fill_circle(). The workaround was to use graphics_fill_radial() instead which made it possible to center a circle on the watchface.

So with Moddable a workaround would be to do something like

render.drawCircle(black, cx, cy, 4, 0, 180);
render.drawCircle(black, cx, cy, 4, 180, 360);

or

render.drawCircle(black, cx, cy, 4, -180, 180);

In these cases Moddable uses graphics_fill_radial() to draw a full circle, and the circle has a diameter of 8 pixels, centered on the watchface.

But now I wonder why Moddable doesn’t always use graphics_fill_radial(), but does things differently for a full circle drawn from 0° to 360°?

1 Like

Thinking a bit more about it …

  • render.drawCircle() draws a circle with an odd number of pixels as diameter when a full circle is drawn from 0° to 360°.
  • render.drawCircle() draws parts of a circle (e.g. from 0° to 270°) with an even number of pixels as diameter.
  • The C function graphics_fill_circle() draws a circle with an odd number of pixels as diameter.
  • With the C function graphics_fill_radial() you can have both: an even or an odd number of pixels as diameter, depending on the size of the rect parameter.

Ideally as a watchface developer I’d like to have a Moddable function with the same functionality as graphics_fill_radial() which allows more fine-tuning than the C function graphics_fill_circle() or the Moddable function render.drawCircle() as it is now. Wishful thinking …

1 Like

That’s a great point. We’re going to fix the underlying Alloy API call to use the correct C api (graphics_fill_radial).

Really appreciate you bringing this up. Please create new topics here if you detect any other weirdness or have questions!

2 Likes

also it’s crazy that the C function has been wrong for all these years. We should probably fix that :slight_smile:

2 Likes