Draw vs Fill

G’day Mates.

If you create a Shape, say a Rectangle, and fill and then to get an outline, draw it, you’ll get the drawn rectangle to be one pixel larger than the filled one. This is as stated in the docs, and I understand this, and why. Though this is creating quite some problem for me since I’m creating an API that excepts shapes and the paint to fill and outline them (among other things) and are supposed to procuce an image of the result.

The problem is that if you want the shape to be outlined with a translucent color, it looks really bad since generally the top left pixels touches the shape but the bottom right don’t (they are painted outside the shape).

I’ve tried the following:

  1. Setting stroke-hint to PURE. Works, but since it creates two pixel outlines (as it should) it’s a no-go.

  2. Auto transformation of shapes for draw/fill to scale down i pixel for draw. Works sometimes but due to rounding in the Sun API when a custom transform is used, creates inconsistent results. The outline jumps on/off the edges of the filled shape.

  3. Trying different BasicStroke()s. Doesn’t work.

Some of the above DO work in certain circumstances, but then there’s the problem with turning anti aliasing on/off, which usually foils some work arounds.

My API has no control over anti-aliasing, Stroke or graphics transform, all that is parameterized. I just want to outline shapes in a good looking, pixel correct way.

Now, is there a simple (or complicated for that matter) way to get a Stoke, transform, rendering hint, or whatever, that always creates equally sized shapes dring fill/draw?

If not (which I’m almost sure of), is this how it works on other platforms (non Java) as well? For instance .NET.

ps. I noticed sketsa (SVG editor) has the same problem. As do every other Java apps i’ve seen.

ps2. Also drawing/filling cirlces don’t even paint the same pixels, sometimes there are “unpainted” pixels between the drawn circle and the filled one.

Cheers,
Mikael

Wouldn’t you need to paint the outline one pixel left and above of the or shape, and make it 2 pixels wider and higher?

like

gfx.fillrect(x,y,width,height);

gfx.drawrect(x-1,y-1,width+2,height+2);

Yep, I could do that but I’m making an API and I don’t know what Shapes are sent in to my drawing/filling methods.
I just get a generic shape (which may be a circle, round rect or whatever) and some paint to fill and outline it.

That’s why I need a generic solution.

Cheers,
Mikael

Let me add something more to your post.

stroking text with small fonts using basicstroke always gives ugly results on win:

draw text, then draw text outline

draw text outline, then draw text

my very own bitmap-outline implementation seems to give better results (!)

Mik

I’m guessing that problem is a yet unfixed bug. Check out
http://developer.java.sun.com/developer/bugParade/bugs/4151279.html and the other bugs related to it.

I’ve always expected that to draw an outline using draw(Shape) will simply draw the pixels exactly at the borders of the Shape (not pixels at borders + 1 or whatever, if you were using the default BasicStroke). Can you point out the docs that say otherwise?

[quote] stroking text with small fonts using basicstroke always gives ugly results on win:
[/quote]
This is definitely related to the bug above. Problem is supposedly scan-conversion inaccuracies after bezier approximations when trying to draw curves. The inaccuracies are especially apparent on small curves

Funny enough this bug doesn’t seem to appear on MacOS X. Maybe this is due to the redirection of java2d rasterizer to the Quartz libs.