fix(macos): S-метр, линейка и зумбар больше не мылятся на Retina

Cocoa рисует канву в физических пикселях, TBitmap всегда 1x, поэтому кадр,
собранный в offscreen-битмап логического размера, растягивался вдвое.

PlatformUtils.GetScreenScale возвращает 2 на Retina и 1 на остальных
платформах. Масштаб — обычная переменная, а не условная компиляция: на
Windows/Linux умножение на 1 даёт прежние числа, а на канву кадр кладётся
через Draw, как и раньше (StretchDraw только при масштабе > 1).

В SMeterView, RulerView и PanZoomBar битмап растёт в S раз, пиксельные
константы, размеры шрифтов и толщина пера умножаются на S. Перо важно
отдельно: иначе на Retina все риски стали бы вдвое тоньше.

RulerView кэширует битмап, поэтому смена масштаба сбрасывает кэш.
PanZoomBar.ThumbGeom получил параметр AScale: отрисовка зовёт его с
физической шириной, хит-тест мыши — с логической, код мыши не менялся.

Objective-C изолирован в MacScale.pas: {$MODESWITCH OBJECTIVEC1} несовместим
с {$MODE Delphi}, а DWARF-3 (-gw3, Debug-режим lazbuild) роняет FPC 3.2.4 с
internal error 200609171 на любых Objective-C типах — отсюда {$DEBUGINFO OFF}.

Замер после правки: 37.5% CPU против 38% базовых, отрисовка этих трёх
элементов ниже уровня шума в профиле.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 19:09:53 +03:00
co-authored by Claude Opus 4.8
parent 406f32b52c
commit fd8769898a
5 changed files with 232 additions and 112 deletions
+42
View File
@@ -0,0 +1,42 @@
unit MacScale;
{
MacScale.pas — единственное место, где проекту нужен Objective-C.
Вынесен из PlatformUtils, потому что {$MODESWITCH OBJECTIVEC1} несовместим
с {$MODE Delphi} (компилятор падает с internal error 200609171). Здесь свой
режим ObjFPC; наружу торчит одна обычная функция.
Модуль имеет смысл только на macOS с GUI: под HEADLESS и на других
платформах он не компилируется и не подключается.
}
{$MODE ObjFPC}{$H+}
{$MODESWITCH OBJECTIVEC1}
// FPC 3.2.4 падает с internal error 200609171, когда генерирует DWARF-3
// (-gw3, режим Debug у lazbuild) для Objective-C типов. Отладочная информация
// для этих сорока строк не нужна.
{$DEBUGINFO OFF}
interface
// Целочисленный масштаб основного экрана: 2 на Retina, 1 иначе.
function MacBackingScale: Integer;
implementation
uses
CocoaAll;
function MacBackingScale: Integer;
var
Sc: NSScreen;
begin
Result := 1;
Sc := NSScreen.mainScreen;
if Sc = nil then Exit;
Result := Round(Sc.backingScaleFactor);
if Result < 1 then Result := 1;
end;
end.