Forum > macOS / Mac OS X

THtmlViewer work-around for TCanvas.TextOut/bgcolor bug (M1 > x86_64)

(1/1)

Manlio:
I discovered that when compiling for macOS on Apple Silicon machines (M1, M2, etc) and targeting x86_64, there is a compiler bug that causes Canvas.TextOut to ignore the Brush.color, even if Brush.style is NOT bsClear.

In other words, if you set a Brush.Color, and then set Brush.Style := bsSolid, and then call TextOut, the background color will NOT be applied. The result will be as if Brush.Style = bsClear.

I wrote a dedicated message about that, just before this one.

Here I want to share how I made a work-around for this problem affecting the THtmlViewer controls.

This bug affects THtmlViewer, for example when rendering this:

--- Code: ---<span style="background-color:yellow;" >Highlighted text</span>

--- End code ---
The background will not be applied, due to the above bug.

So I have made my own crude work-around like this:

1. I Declare a global variable: var BuggyCanvas: TCanvas = nil;

2. In procedure DrawTheText (unit HTMLSubs), right under the line Canvas.Brush.Style := bsSolid; I add this new line:  BuggyCanvas := Canvas; 

5. When the time comes to actually write the text, in unit HtmlMisc, function ExtTextOutW(...), just before calling ExtTextOut, I do this:


--- Code: ---{$IFDEF DARWIN}
{$IFDEF CPUX86_64}
if BuggyCanvas <> nil then begin
  BuggyCanvas.FillRect(X, Y, X + BuggyCanvas.TextWidth(s), Y + BuggyCanvas.TextHeight(s));
  BuggyCanvas := nil;
end;
{$ENDIF}
{$ENDIF}
// next line is the original code
Result := ExtTextOut(DC, X, Y, etc...

--- End code ---

Explanation:

1. Whenever the situation arises in which text must be written with a non-transparent background color (point 2 above), then I save the canvas to the variable BuggyCanvas.

2. Just before writing text with TextOut/ExtTextOut, I check if BuggyCanvas is not nil, and in that case, knowing that TextOut will not do the job, I paint myself a rectangle of the correct size (TextWidth and TextHeight) at the correct position (X, Y) where the text is about to be painted. This work-around works perfectly for me.

3. Set BuggyCanvas to nil afterwards, to make sure this is only done when necessary, and on existing Canvas objects.

4. The two conditional defines ensure that the bug work-around is only applied on the architectures that need it.

Again, this only happens when compiling on an Apple Silicon machine, targeting x86_64 i.e. Intel Apple machines.

Figuring this whole thing out took me a lot of time and effort, and so I hope that if you come across the same problem and are searching for a solution, this will help.

Navigation

[0] Message Index

Go to full version