OberonCore https://forum.oberoncore.ru/ |
|
недочёт в TextViews — "несимметричное" кэширование https://forum.oberoncore.ru/viewtopic.php?f=134&t=6936 |
Страница 1 из 1 |
Автор: | arisu [ Среда, 10 Май, 2023 11:28 ] |
Заголовок сообщения: | недочёт в TextViews — "несимметричное" кэширование |
нашёл некоторый… скажем так, недочёт в TextViews. как мы знаем, оригинальный виндовый BBCB в принципе забивает большой и толстый на кернинг. лин-версия использует панго (или, в случае LC, свою рисовалку на основе FreeType), и кернинг уважает. это почти работает, за одним интересным исключением. штука такая, что TextSetters.Reader разбивает текст не только по кусочкам с разными атрибутами, но и на некоторых специальных символах типа переноса и минуса. он это делает для реализации wrapping. также максимальный размер возвращаемого кусочка — 64. и вот тут возникает противоречие между `TextViews.DrawLine()` и `TextViews.GetThisLocation()`. `DrawLine()` кэширует строки кусками по 128, и вдобавок не разбивает их по границам спецсимволов. а `GetThisLocation()` такого не делает. из-за этого в некоторых случаях вычисленая позиция каретки может не соответствовать реальной позиции глифа на экране. то есть: `GetThisLocation()` двигается ровно по кусочкам, возвращённым Reader, через `StringWidth()`. а теперь представим такой случай: знак минуса имеет ненулевой кернинг с некоторыми буквами (так, например, в вердане: "A-" — тут минус смещают немного влево. `DrawLine()` накопит строку "A-" и нарисует минус с правильным кернингом. а `GetThisLocation()` вычислит сумму длин строк "A" и "-" отдельно, и каретка уедет немного дальше вправо, чем надо. такая штука очень малозаметна, но тем не менее она существует. если в строке накопится много минусов с кернингом — каретка довольно заметно визуально сместится. вариантов решения я тут вижу два: или учить `GetThisLocation()` кэшировать текст точно так же, как делает `DrawLine()`, или выкинуть из `DrawLine()` кэширование совсем. второй вариант мне кажется более правильным: просто отключить кэширование в `DrawLine()`. техника сейчас достаточно быстрая, чтобы не имело смысла собирать там кусочки (тем более что частично кусочки уже собирает Reader). Код: PROCEDURE CacheString (x, y: INTEGER; c: INTEGER; IN s: ARRAY OF CHAR; f: Fonts.Font); VAR i, j, len: INTEGER; BEGIN len := LEN(s$); IF FALSE THEN (* old code, unused *) IF (cache.len + len >= cacheLen) OR (cache.y # y) OR (cache.color # c) OR (cache.font # f) THEN FlushCaches END; ASSERT(cache.len + len < cacheLen, 100); IF cache.len = 0 THEN cache.x := x; cache.y := y; cache.color := c; cache.font := f END; i := 0; j := cache.len; WHILE i < len DO cache.buf[j] := s[i]; INC(i); INC(j) END; cache.len := j ELSE FlushCaches; ASSERT(cache.len = 0); cache.x := x; cache.y := y; cache.color := c; cache.font := f; cache.buf := s$; cache.len := len END END CacheString; старый код не удаляем — пусть будет, мало ли. просто вместо этого не склеиваем строки, даже если возможно. это не ломает никакой логики, и решает все потенциальные проблемы с кернингом. в LC я просто удалил всю логику кэширования из `DrawLine()`. реально она почти ничего не ускоряет, только зря усложняет код. |
Автор: | Иван Денисов [ Среда, 10 Май, 2023 11:48 ] | ||
Заголовок сообщения: | Re: BlackBox 2.0 | ||
Что-то не получается пока воспроизвести проблему с А-
|
Автор: | arisu [ Среда, 10 Май, 2023 13:00 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
это сильно зависит от конкретных шрифтов и шрифтового движка. pango, например, делает кернинг несколько не так, как FreeType (там реально для одного и того же шрифта по какой-то причине отличаются то ли значения кернинга, то ли кернинговые пары). я и налетел на это, когда перешёл с панги на фритайп, и долго искал ошибку в своей реализации HostFonts, хех. тут сложно конкретно показать воспроизводимость бага, но он есть. я потому и привёл такое длинное описание, чтобы можно было вывести существование бага чисто логическим путём. в большинстве случаев бага не будет, я тоже его замечал только на конкретных кернинговых парах же. а вот когда я стал писать регулярки типа `[A-F]` — оно полезло. p.s.: панго, кстати, похоже, не делает кернинг минуса с 'A'. там вообще внизу harfbuzz, а он почти все метрики шрифта обрабатывает сам, минуя фритайп. но где-то кернинг будет — и ой. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |