Кто-нить ковырял базовый класс редактора кода?
Модератор: Модераторы
Кто-нить ковырял базовый класс редактора кода?
Народ, никто не ковырял базовый класс редактора кода? До самого дна, где происходит рендеринг текста?
Похоже, этот гипервелосипед построен на основе чего-то *совсем* не подходящего:
1. тормозной шо ппц. На пк ещё терпимо, на Raspberry Pi 3 - боль. Слайд-шоу при прокрутке.
2. не умеет использовать *не* моноширинные шрифты, честно рендерит всю строку как шрифт надиктовал - и всё развозит.
Так вот, хотелось бы добраться до этого говнища и заменить на что-то вменяемое, типа использования битмапного шрифта, или просто кеширорвания глифов, чтобы текст собирался по буковкам, забивая на реальную ширину глифов в шрифте, а не тормозным рендером слов.
И получить на выходе сборку лазаря с не тормозящим редактором кода и гораздо более широким выбором шрифтов.
Кто докапывался?
Похоже, этот гипервелосипед построен на основе чего-то *совсем* не подходящего:
1. тормозной шо ппц. На пк ещё терпимо, на Raspberry Pi 3 - боль. Слайд-шоу при прокрутке.
2. не умеет использовать *не* моноширинные шрифты, честно рендерит всю строку как шрифт надиктовал - и всё развозит.
Так вот, хотелось бы добраться до этого говнища и заменить на что-то вменяемое, типа использования битмапного шрифта, или просто кеширорвания глифов, чтобы текст собирался по буковкам, забивая на реальную ширину глифов в шрифте, а не тормозным рендером слов.
И получить на выходе сборку лазаря с не тормозящим редактором кода и гораздо более широким выбором шрифтов.
Кто докапывался?
Вопрос не что, а *как*. Courier в линуксАх использовать тупо невозможно из-за неотключаемого вырвиглазного сглаживания.
..копаю...
..вы таки будете смеяться, но это TextOutW()
..а под линуксАми - как всегда, эмуляция ВинАПИ:
..копаю...
..вы таки будете смеяться, но это TextOutW()
Код: Выделить всё
{------------------------------------------------------------------------------
Method: TextOut
Params: DC - handle of device context
X - x-coordinate of starting position
Y - y-coordinate of starting position
Str - string
Count - number of characters in string
Returns: If the function succeeds
Writes a character string at the specified location, using the currently
selected font.
------------------------------------------------------------------------------}
function TWin32WidgetSet.TextOut(DC: HDC; X, Y: Integer; Str: PChar; Count: Integer): Boolean;
{$ifdef WindowsUnicodeSupport}
var
ws: widestring;
{$endif}
begin
{$ifdef WindowsUnicodeSupport}
ws := UTF8ToUTF16(copy(str,1,Count));
Result := Boolean(Windows.TextOutW(DC, X, Y, PWideChar(ws), length(ws)));
{$else}
Result := Boolean(Windows.TextOut(DC, X, Y, Str, Count));
{$endif}
end;..а под линуксАми - как всегда, эмуляция ВинАПИ:
Код: Выделить всё
function TGtk3WidgetSet.TextOut(DC: HDC; X, Y: Integer; Str: Pchar;
Count: Integer): Boolean;
var
S: String;
begin
// Result:=inherited TextOut(DC, X, Y, Str, Count);
{$IFDEF VerboseGtk3DeviceContext}
DebugLn('TGtk3WidgetSet.TextOut x=',dbgs(x),' y=',dbgs(y),' Text ',dbgs(Str),' count ',dbgs(Count));
{$ENDIF}
Result := False;
if IsValidDC(DC) then
begin
Result := True;
S := StrPas(Str);
if Count > 0 then
S := UTF8Copy(S, 1, Count);
TGtk3DeviceContext(DC).drawText(X, Y , S);
end;
end;
Код: Выделить всё
function TGtk2WidgetSet.TextOut(DC: HDC; X, Y: Integer; Str: Pchar;
Count: Integer) : Boolean;
var
DevCtx: TGtkDeviceContext absolute DC;
DCOrigin: TPoint;
yOffset: integer;
BackGroundColor: PGdkColor;
begin
Result := IsValidDC(DC);
if not Result then Exit;
if Count <= 0 then Exit;
if DevCtx.HasTransf then
DevCtx.TransfPoint(X, Y);
UpdateDCTextMetric(DevCtx);
DCOrigin := DevCtx.Offset;
with DevCtx.DCTextMetric.TextMetric do
yOffset := tmHeight-tmDescent-tmAscent;
if yOffset < 0 then
yOffset := 0;
DevCtx.SelectedColors := dcscCustom;
EnsureGCColor(DC, dccCurrentTextColor, True, False);
BackGroundColor := nil;
if Assigned(DevCtx.GDIObjects[gdiBrush]) and (DevCtx.BkMode = OPAQUE) and
Assigned(DevCtx.CurrentBackColor.Colormap) then
begin
EnsureGCColor(DC, dccCurrentBackColor, DevCtx.GDIObjects[gdiBrush]^.GDIBrushFill = GDK_SOLID, True);
//do not set BackGroundColor if CurrentBrush.Color = CurrentBackColor.
//issue #22719
if TGDKColorToTColor(DevCtx.CurrentBackColor.Color) <>
TGDKColorToTColor(DevCtx.GetBrush^.GDIBrushColor.Color) then
BackGroundColor := @DevCtx.CurrentBackColor.Color;
end;
DevCtx.DrawTextWithColors(Str, Count,
X + DCOrigin.X, Y + DCOrigin.Y + yOffset,
nil, BackGroundColor);
end;Все эти текстовые редакторы сплошное недоразумение. Поэтому даже задумался, а не написать статью про то как надо делать.
Конечно с выводом есть трудности. Но все решаемы.
1)
Растеризация глифов букв долгая операция.
Растеризация это перевод из векторной формы объекта в растровую в виде точек. Перевод в точки требует задействовать сложную математику, либо пристрелку с повышенной точностью для получения эффекта антилясинга. А ещё шрифты содержат скрипты для препроцессинга и постпроцессинга букв.
Решение закешировать глифы букв картинками. В виндоусе отдельный сервис который неплохо с этим справляется.
2) Буквы залезают одна под другую.
Если шрифт не моноширный, то буквы к примеру «од». Обособленно это заметно на курсиве «ол» и еще сильнее при переходи с прямых на косые буквы «оло» В виндоусе очень большой скос по умолчанию 4 пикселя. В браузере всего 2 пикселя.
Тут 2 или даже 3 подпроблемы.
2.1) Что-бы совместить буквы даже прямые надо использовать блендеринг.
Мы не можем сделать все пиксели абсолютно прозрачными и не прозрачными. Так как из-за цветного фона появятся артифакты, тежи ступеньки.
Решение использовать блендинг. Блендинг довольно медленная операция. И тут лучше кэшировать не отдельные буквы, а слова целиком.
2.2) При смешивание прямых и косых очень сильно залезают друг под друга.
Решение делать отступы.
2.3) При редактирование каретка остаётся прямой.
Если в браузере это не заметно, то в редакторе это раздражает. Если отступы не делать то есть места где каретка стоит на середине буквы!
Решение делать отступы и рассчитывать при каждом перемещении. Про уменьшение величины скоса уже сказал,
3) Частичный скролинг делать через копирование известной части и дорисовки нового.
Из самого нижнего положения при переходе на одну линию вниз нужно сместить всё что нарисовано вверх и вывести новую линию. Что-бы не тратить память на кэширование обычно напрямую используют видео память. Тем более такая операция копирования может быть аппаратно оптимизирована.
4) Что делать если мы скролимся целиком к примеру по страницам клавишей pageDown? Выхода нет перерисовывать всё. Так как человек существо медленное пока он второй раз успеет нажать пройдёт четверть секунды. А вот глаз реагирует быстрее на порядок так вот что-бы это не разрежало и перерисовка была плавной используют предсказание. Просчёт идет на перёд в буфер и потом вывод.
5) Плавный скролинг. Если идёт скролинг мышкой то хочется что-бы он был плавным и тут уже на что только не идут разработчики. Используют оверлеи что-бы аппаратно ускорить копирование картинки из базовой ОЗУ в видео память. Сжимают картинку, а потом аппаратно разжимают из-за этого она становится размытой.
Конечно с выводом есть трудности. Но все решаемы.
1)
Растеризация глифов букв долгая операция.
Растеризация это перевод из векторной формы объекта в растровую в виде точек. Перевод в точки требует задействовать сложную математику, либо пристрелку с повышенной точностью для получения эффекта антилясинга. А ещё шрифты содержат скрипты для препроцессинга и постпроцессинга букв.
Решение закешировать глифы букв картинками. В виндоусе отдельный сервис который неплохо с этим справляется.
2) Буквы залезают одна под другую.
Если шрифт не моноширный, то буквы к примеру «од». Обособленно это заметно на курсиве «ол» и еще сильнее при переходи с прямых на косые буквы «оло» В виндоусе очень большой скос по умолчанию 4 пикселя. В браузере всего 2 пикселя.
Тут 2 или даже 3 подпроблемы.
2.1) Что-бы совместить буквы даже прямые надо использовать блендеринг.
Мы не можем сделать все пиксели абсолютно прозрачными и не прозрачными. Так как из-за цветного фона появятся артифакты, тежи ступеньки.
Решение использовать блендинг. Блендинг довольно медленная операция. И тут лучше кэшировать не отдельные буквы, а слова целиком.
2.2) При смешивание прямых и косых очень сильно залезают друг под друга.
Решение делать отступы.
2.3) При редактирование каретка остаётся прямой.
Если в браузере это не заметно, то в редакторе это раздражает. Если отступы не делать то есть места где каретка стоит на середине буквы!
Решение делать отступы и рассчитывать при каждом перемещении. Про уменьшение величины скоса уже сказал,
3) Частичный скролинг делать через копирование известной части и дорисовки нового.
Из самого нижнего положения при переходе на одну линию вниз нужно сместить всё что нарисовано вверх и вывести новую линию. Что-бы не тратить память на кэширование обычно напрямую используют видео память. Тем более такая операция копирования может быть аппаратно оптимизирована.
4) Что делать если мы скролимся целиком к примеру по страницам клавишей pageDown? Выхода нет перерисовывать всё. Так как человек существо медленное пока он второй раз успеет нажать пройдёт четверть секунды. А вот глаз реагирует быстрее на порядок так вот что-бы это не разрежало и перерисовка была плавной используют предсказание. Просчёт идет на перёд в буфер и потом вывод.
5) Плавный скролинг. Если идёт скролинг мышкой то хочется что-бы он был плавным и тут уже на что только не идут разработчики. Используют оверлеи что-бы аппаратно ускорить копирование картинки из базовой ОЗУ в видео память. Сжимают картинку, а потом аппаратно разжимают из-за этого она становится размытой.
Да даже просто убить это ***** неотключаемое сглаживание - уже великое дело было бы, даже без кеширования.
И скорости даже малине хватило бы, безо всяких изысков и оптимизаций.
Дятелы из майкрософт, наконец-то догадались, что не всем нужно их сраное сглаживание - и стало возможно его отключить в виндовс 10, начиная с какого-то обновления. Теперь я могу ей пользоваться, более не приходится вынужденно сидеть на виндовс 7, и Courier New выглядит нормально, не вырвиглазно.
Но в линуксе такой роскоши нет, сглаживание прибито гвоздями.
Приходится в лазарусе какими-то левыми громадными шрифтами пользоваться, чтобы получить буквы, а не обмылки. А Courier под любым линуксом - выглядит, как сраное говно.
...короче, если смогу выделить время - сделаю хак для SynEdit, чтобы хотя бы тупо битмапный шрифт использовал вместо TextOut виджета. Но дело это - не простое, и не быстрое.
Эх, мечты - мечты.
З.Ы. Если шрифт - не моноширинный, то выбрать ширину буквы "О". Те, что уже - ставить по центру. Те, что шире - плющить.
З.З.Ы. Курсив/наклонный - это извращение, которому нечего делать в редакторе кода.
И скорости даже малине хватило бы, безо всяких изысков и оптимизаций.
Дятелы из майкрософт, наконец-то догадались, что не всем нужно их сраное сглаживание - и стало возможно его отключить в виндовс 10, начиная с какого-то обновления. Теперь я могу ей пользоваться, более не приходится вынужденно сидеть на виндовс 7, и Courier New выглядит нормально, не вырвиглазно.
Но в линуксе такой роскоши нет, сглаживание прибито гвоздями.
Приходится в лазарусе какими-то левыми громадными шрифтами пользоваться, чтобы получить буквы, а не обмылки. А Courier под любым линуксом - выглядит, как сраное говно.
...короче, если смогу выделить время - сделаю хак для SynEdit, чтобы хотя бы тупо битмапный шрифт использовал вместо TextOut виджета. Но дело это - не простое, и не быстрое.
Эх, мечты - мечты.
З.Ы. Если шрифт - не моноширинный, то выбрать ширину буквы "О". Те, что уже - ставить по центру. Те, что шире - плющить.
З.З.Ы. Курсив/наклонный - это извращение, которому нечего делать в редакторе кода.
-
Mirage
- энтузиаст
- Сообщения: 881
- Зарегистрирован: 06.05.2005 20:29:07
- Откуда: Russia
- Контактная информация:
Ступил конечно, причем тут FreeType, оно же не ownerdraw. Логично, что ОС в конечном итоге рисуют текст.
Именно для курьера сглаживание? Само сглаживание шрифтов вроде отключается. По крайней мере в Убунте.
Спорно - хорошо помечать так например статические члены класса. Или интерфейсы.
Cheb писал(а):Courier в линуксАх использовать тупо невозможно из-за неотключаемого вырвиглазного сглаживания.
Именно для курьера сглаживание? Само сглаживание шрифтов вроде отключается. По крайней мере в Убунте.
Cheb писал(а):З.З.Ы. Курсив/наклонный - это извращение, которому нечего делать в редакторе кода.
Спорно - хорошо помечать так например статические члены класса. Или интерфейсы.
Именно для курьера сглаживание?
Для всего, принудительное и неотключаемое.
И даже больше: меня грызёт сомнение. что это - ляп лазаревского виджета, а не системы.
Как пример, как надо, приведу Notepad++, коим пользуюсь по работе уже много лет. Он быстрый, Лазарь в сравнении - ржавый тормоз. И он вообще не позволяет выбирать шрифт - используется какой-то курьер, только размер можно менять по Ctrl + колесо мыши.
Вот скажите, *зачем* редактору кода что-то, кроме нормального Courier?
В лазаре это больше на отладочную фичу похоже, для хакания вокруг кривых ОС и кривых установок шрифтов.
хорошо помечать так например статические члены класса. Или интерфейсы.
Просто с правильными пиксельными шрифтами курсив не работает. Пока ни разу не видел, чтобы курсив без сглаживания не выглядел, как говно. А ведь и сам в своё время пробовал шрифты рисовать.
Cheb писал(а):Как пример, как надо, приведу Notepad++
а почему бы не поднять обсуждение проблемы тут? ИМХО, шансов на какие-то подвижки было бы больше. И даже, если допилишь сабж до нужной кондиции в виде плагина-компонента к IDE, народ тебе только рукоплескать будет.
Ээээ, мил человек, у меня столько проектов в стеке висит, что даже не смешно, а грустно.
Насчёт зазаровского синедита, навскидку:
Доработать чтобы вместо TextOut использовалась прокладка, назовём её CodeEditorTextOut, где:
- все буквы кодом ниже 127 (базовая латиница) - из встроенного битмапного шрифта (набора оных на разные размеры), и выводятся каким-нибудь растровым методом виджета (не изучал пока).
- всё, что содержит буквы выше этого - а это будут *только* строковые константы! - выводится по старинке через TextOut, и только на них влияет выбор шрифта в редакторе. При этом ещё проверяется ширина текста и размер подгоняется на лету, чтобы влезало в рамки, диктуемые шириной встроенного шрифта.
Вот тогда будут и волки сыты, и овцы целы.
Насчёт зазаровского синедита, навскидку:
Доработать чтобы вместо TextOut использовалась прокладка, назовём её CodeEditorTextOut, где:
- все буквы кодом ниже 127 (базовая латиница) - из встроенного битмапного шрифта (набора оных на разные размеры), и выводятся каким-нибудь растровым методом виджета (не изучал пока).
- всё, что содержит буквы выше этого - а это будут *только* строковые константы! - выводится по старинке через TextOut, и только на них влияет выбор шрифта в редакторе. При этом ещё проверяется ширина текста и размер подгоняется на лету, чтобы влезало в рамки, диктуемые шириной встроенного шрифта.
Вот тогда будут и волки сыты, и овцы целы.
Cheb писал(а):Ээээ, мил человек, у меня столько проектов в стеке висит, что даже не смешно, а грустно.
вот я и говорю: напиши фикс в виде компонента, навроде того же профайлера. Его просто включат в стандартный набор OPM, что позволит ставить на свежую сборку Лазаря одним кликом. И никого просить не надо. Только написать
-
Mirage
- энтузиаст
- Сообщения: 881
- Зарегистрирован: 06.05.2005 20:29:07
- Откуда: Russia
- Контактная информация:
Cheb писал(а):Вот скажите, *зачем* редактору кода что-то, кроме нормального Courier?
Мне, к примеру, больше нравится шрифт Consolas, а еще больше DejaVu Sans Mono, который в данный момент и используется.
Cheb писал(а):И даже больше: меня грызёт сомнение. что это - ляп лазаревского виджета, а не системы.
Система становится несглаженой при активации соотв. режима отрисовки шрифтов. Так что в системе принудительного нет. LCL по идее должен использовать системные средства вывода. Возможно, захардкожен какой-то параметр, приводящий к сглаженному выводу шрифтов независимо от системных настроек.
Но в линуксе такой роскоши нет, сглаживание прибито гвоздями.
В KDE и GNOME во все времена можно было выключить сглаживание.
