Sim Daltonism’s purple bug

Back in 2016, I converted the filter algorithm in Sim Daltonism 1.x to OpenGL shader code so it’d run on the GPU and have better performance. This also made it possible to bring it to iOS as a real-time filter for the camera. A bug slipped through however.

On a filtered color wheel we can observe that a region of deeply saturated blue becomes purple. This makes no visual sense: purple light is blue light + red light, and this purple area showed up even for protanopia (no red cones). This also wasn’t happening with version 1, and it wasn’t happening on the Color Laboratory on which Sim Daltonism’s filter algorithm is based.

I dug up the code for version 1 and tried to find differences. I did not have much success at finding accidental algorithmic differences. So I finally tried to clamp some values within the 0…1 range they were supposed to be in; theoretically the result of the calculation shouldn’t be out of this range but that doesn’t account for rounding errors in floating point calculations. GPUs are quite fast, but they sometimes sacrifice precision to achieve that speed. And that did the trick.

So now there’s a new version of Sim Daltonism with a corrected filter on both Mac and iOS. And I want to thank Lisa Charlotte Rost for signaling this bug after comparing with other color blindness simulation tools.

More Hot Keys in Black Light Pro

Some people find their display too bright, and some displays are actually too bright. You can dim the backlight of your display, but what if the lowest setting is still too bright? Then you can use Black Light or Black Light Pro to dim the display more… problem solved? Not entirely it seems.

I occasionally get requests for ways to dim the display using global keyboard shortcuts, often known as “hot keys”. In Black Light Pro you can have many effects configured with various dim levels, and you can assign a hot key to each. But wouldn’t it be better to have two keys for increasing or decreasing the brightness? The new version of Black Light Pro is making this possible, and more.

With version 1.2 of Black Light Pro you can now set hot keys to increase and decrease brightness, change the tinting vividness and hue, toggle the invert effect, etc. Those changes will be saved to the current active effect.

If you have more than one monitor, you can apply the same effect on all of them or apply a different effect to each. In the former case hot keys will control the effect for all the screens at the same time. In the later case hot keys will let you to control each screen independently, with one hot key to cycle between them.

Black Light Pro comes with a 30-day trial so you can experience it yourself.

Font substitution and missing text

I recently found a bug in my work-in-progress-next-major-version of Counterparts Lite where text in certain languages was not showing up in the text editor. The problem ended up being related to font substitution. If characters from certain languages aren’t showing up in your Cocoa text views, here’s something to check…

The first thing to understand is that no font contains all the characters defined in Unicode. When the text system encounters characters that aren’t representable in the current font, it chooses another font that has the correct glyphs to display those characters.

Every time you change some part of a NSTextStorage object in Cocoa, its processEditing method is called to optimize attribute ranges and fix things that could be incoherent (such as a paragraph style spanning only part of a paragraph). This is also where font substitution happens.

You can observe what processEditing is doing easily by setting a delegate on the text storage implementing the willProcessEditing and didProcessEditing methods. After changing the text, printing the text storage’s content in willProcessEditing will result in this single text section with uniform attributes:

Hello 漢字{
    NSColor = "Catalog color: System textColor";
    NSFont = "\"Helvetica 12.00 pt. P [] (0x7f85d9f60070)
        fobj=0x7f85d9f4c320, spc=3.33\"";

And then in didProcessEditing you will see it was split in two text sections with different font attributes:

Hello {
    NSColor = "Catalog color: System textColor";
    NSFont = "\"Helvetica 12.00 pt. P [] (0x7fbdc15a25c0)
        fobj=0x7fbdbec6a0d0, spc=3.33\"";
    NSColor = "Catalog color: System textColor";
    NSFont = "\"HiraginoSans-W3 12.00 pt. P [] (0x7fbdc15b2330)
        fobj=0x7fbdc15adbe0, spc=4.00\"";

The font was changed for the characters not representable in Helvetica to ensure they can still be shown. Font substitution at work!

Perhaps however our app wants to control the font in the text view in order to replace whatever style could come from the user pasting some text. Those delegate methods sure seem like a good place to do that, and they are.

It is important to know however that there’s a crucial difference between changing the font in willProcessEdting and in didProcessEditing:

  • willProcessEditing is called before font substitution. Any font you set while in willProcessEditing will get substituted with an appropriate font for characters not available in the font you choose.

  • didProcessEditing is called after font substitution. If you change the font while in didProcessEditing there will be no further font substitution, and thus you should make sure the font you set can display all the characters.

In summary, if you have to change the font after the text storage was edited, do it in willProcessEditing and it’ll do the right thing. Don’t do it in didProcessEditing.

It’s also important to note that you can change the font in the text storage without manipulating the text storage directly (such as in textView.font = myFont). The same rule apply: do it in willProcessEditing because if you do it from didProcessEditing no font substitution will occur and you can end up with characters not showing up.

macOS Catalina: Authorize Screen Recording

macOS Catalina brings tighter security in various ways. One change is about preventing apps from seeing what’s on your screen. Apps that want to do that now require a special authorization from the user. This includes two of my apps: Sim Daltonism and Red Stripe.

The first time you open the app, macOS will tell you it wants to record the screen and will offer to open System Preferences. Until authorized in System Preferences, all the app can see is your desktop picture.

You can open System Preferences from the alert shown by macOS when you first open the app, which will bring you exactly at the right place. Otherwise, you can go there by choosing System Preferences from the Apple menu: from there, open the Security & Privacy pane, choose the Privacy tab, and select the the Screen Recording category.

You will see a list of apps that requested the ability to record the screen. Check the ones you want to authorize. You might be prompted to quit the app so the setting takes effect; this is unnecessary in the case of Sim Daltonism and Red Stripe but might be needed for other apps.

  • © 2003–2020 Michel Fortin.