09-12-2025, 05:08 PM
Hey @bplus, this ended up being an interesting example to research. Here is a version that will work in both QB64 and QBJS:
The only difference here is that rather than comparing each pixel to the black pixel as in your original, I'm checking to see if the _Red component is over a certain threshold. This is necessary because QBJS uses the native HTML 2D canvas methods for drawing text and these methods apply anti-aliasing by default.
Here's another example that illustrates this. Using a slightly modified version of your zoom logic, you can see that we detected gray pixels around the edges of the text:
This is where compatibility questions can get a bit tricky. The anti-aliasing is a pretty nice feature that we get by default in QBJS. It makes text and drawing elements like lines and circles appear nice and smooth. Perhaps, the answer is to create some sort of strict graphics compatibility mode. (Unfortunately, that would mean needing to re-implement all of the low-level drawing methods as there is not a way to turn this off in the out-of-the-box canvas methods.)
As you can see in the example above, I'm also breaking some screen mode rules by allowing either indexed colors or RGB color definitions regardless of screen type which I find pretty handy. I'm always trying to find the balance between compatibility and enhanced functionality and performance. Screen modes aren't really necessary anymore except for backwards compatibility.
You may be asking, ok, well why didn't the original implementation work comparing against a sampled black pixel? Well, in short, this is a case where I was focusing on performance vs compatibility. Essentially, in QBJS colors are represented as an object with red, green, blue and alpha components. Methods that use colors can convert to and from unsigned long representations of the color. In an effort to reduce the amount of conversions that would be necessary, the Point method (and other methods that return color data return the underlying color object). This prevents having to parse the color data from the numeric representation when that color is passed to a drawing method. If you try to print the color it will convert it on the fly to its numeric representation. So, you could change the comparison in your original code to the following:
I'll look at this further and see about having Point return the expected numeric representation. I think this may be a case where any potential performance issues might be negligible compared to the improved compatibility.
I appreciate you and @Pete making me aware of examples like this. Unless someone reports it, I'm not aware of what challenges people might be running into.
The only difference here is that rather than comparing each pixel to the black pixel as in your original, I'm checking to see if the _Red component is over a certain threshold. This is necessary because QBJS uses the native HTML 2D canvas methods for drawing text and these methods apply anti-aliasing by default.
Here's another example that illustrates this. Using a slightly modified version of your zoom logic, you can see that we detected gray pixels around the edges of the text:
This is where compatibility questions can get a bit tricky. The anti-aliasing is a pretty nice feature that we get by default in QBJS. It makes text and drawing elements like lines and circles appear nice and smooth. Perhaps, the answer is to create some sort of strict graphics compatibility mode. (Unfortunately, that would mean needing to re-implement all of the low-level drawing methods as there is not a way to turn this off in the out-of-the-box canvas methods.)
As you can see in the example above, I'm also breaking some screen mode rules by allowing either indexed colors or RGB color definitions regardless of screen type which I find pretty handy. I'm always trying to find the balance between compatibility and enhanced functionality and performance. Screen modes aren't really necessary anymore except for backwards compatibility.
You may be asking, ok, well why didn't the original implementation work comparing against a sampled black pixel? Well, in short, this is a case where I was focusing on performance vs compatibility. Essentially, in QBJS colors are represented as an object with red, green, blue and alpha components. Methods that use colors can convert to and from unsigned long representations of the color. In an effort to reduce the amount of conversions that would be necessary, the Point method (and other methods that return color data return the underlying color object). This prevents having to parse the color data from the numeric representation when that color is passed to a drawing method. If you try to print the color it will convert it on the fly to its numeric representation. So, you could change the comparison in your original code to the following:
Code: (Select All)
If Str$(Point(x, y)) <> Str$(black~&) Then
This would work... however, because of the antialiasing it would detect all of the gray pixels as well and the output would lose definition. Plus, it looks weird and is not intuitive.I'll look at this further and see about having Point return the expected numeric representation. I think this may be a case where any potential performance issues might be negligible compared to the improved compatibility.
I appreciate you and @Pete making me aware of examples like this. Unless someone reports it, I'm not aware of what challenges people might be running into.

