Кто-нить ковырял базовый класс редактора кода?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Кто-нить ковырял базовый класс редактора кода?

Сообщение Cheb » 13.07.2018 16:56:04

Народ, никто не ковырял базовый класс редактора кода? До самого дна, где происходит рендеринг текста?

Похоже, этот гипервелосипед построен на основе чего-то *совсем* не подходящего:
1. тормозной шо ппц. На пк ещё терпимо, на Raspberry Pi 3 - боль. Слайд-шоу при прокрутке.
2. не умеет использовать *не* моноширинные шрифты, честно рендерит всю строку как шрифт надиктовал - и всё развозит.

Так вот, хотелось бы добраться до этого говнища и заменить на что-то вменяемое, типа использования битмапного шрифта, или просто кеширорвания глифов, чтобы текст собирался по буковкам, забивая на реальную ширину глифов в шрифте, а не тормозным рендером слов.
И получить на выходе сборку лазаря с не тормозящим редактором кода и гораздо более широким выбором шрифтов.

Кто докапывался?
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 639
Зарегистрирован: 06.06.2005 15:54:34

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение Mirage » 14.07.2018 00:26:28

Не смотрел, но что там может быть, кроме FreeType, даже чисто теоретически?
Mirage
энтузиаст
 
Сообщения: 813
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение Cheb » 14.07.2018 10:23:03

Вопрос не что, а *как*. Courier в линуксАх использовать тупо невозможно из-за неотключаемого вырвиглазного сглаживания.

..копаю...

..вы таки будете смеяться, но это 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;
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 639
Зарегистрирован: 06.06.2005 15:54:34

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение Pavia » 14.07.2018 12:27:16

Все эти текстовые редакторы сплошное недоразумение. Поэтому даже задумался, а не написать статью про то как надо делать.

Конечно с выводом есть трудности. Но все решаемы.
1)
Растеризация глифов букв долгая операция.
Растеризация это перевод из векторной формы объекта в растровую в виде точек. Перевод в точки требует задействовать сложную математику, либо пристрелку с повышенной точностью для получения эффекта антилясинга. А ещё шрифты содержат скрипты для препроцессинга и постпроцессинга букв.
Решение закешировать глифы букв картинками. В виндоусе отдельный сервис который неплохо с этим справляется.
2) Буквы залезают одна под другую.
Если шрифт не моноширный, то буквы к примеру «од». Обособленно это заметно на курсиве «ол» и еще сильнее при переходи с прямых на косые буквы «оло» В виндоусе очень большой скос по умолчанию 4 пикселя. В браузере всего 2 пикселя.
Тут 2 или даже 3 подпроблемы.
2.1) Что-бы совместить буквы даже прямые надо использовать блендеринг.
Мы не можем сделать все пиксели абсолютно прозрачными и не прозрачными. Так как из-за цветного фона появятся артифакты, тежи ступеньки.
Решение использовать блендинг. Блендинг довольно медленная операция. И тут лучше кэшировать не отдельные буквы, а слова целиком.
2.2) При смешивание прямых и косых очень сильно залезают друг под друга.
Решение делать отступы.
2.3) При редактирование каретка остаётся прямой.
Если в браузере это не заметно, то в редакторе это раздражает. Если отступы не делать то есть места где каретка стоит на середине буквы!
Решение делать отступы и рассчитывать при каждом перемещении. Про уменьшение величины скоса уже сказал,
3) Частичный скролинг делать через копирование известной части и дорисовки нового.
Из самого нижнего положения при переходе на одну линию вниз нужно сместить всё что нарисовано вверх и вывести новую линию. Что-бы не тратить память на кэширование обычно напрямую используют видео память. Тем более такая операция копирования может быть аппаратно оптимизирована.
4) Что делать если мы скролимся целиком к примеру по страницам клавишей pageDown? Выхода нет перерисовывать всё. Так как человек существо медленное пока он второй раз успеет нажать пройдёт четверть секунды. А вот глаз реагирует быстрее на порядок так вот что-бы это не разрежало и перерисовка была плавной используют предсказание. Просчёт идет на перёд в буфер и потом вывод.
5) Плавный скролинг. Если идёт скролинг мышкой то хочется что-бы он был плавным и тут уже на что только не идут разработчики. Используют оверлеи что-бы аппаратно ускорить копирование картинки из базовой ОЗУ в видео память. Сжимают картинку, а потом аппаратно разжимают из-за этого она становится размытой.
Аватара пользователя
Pavia
постоялец
 
Сообщения: 213
Зарегистрирован: 07.01.2011 12:46:51

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение Cheb » 15.07.2018 04:52:37

Да даже просто убить это ***** неотключаемое сглаживание - уже великое дело было бы, даже без кеширования.
И скорости даже малине хватило бы, безо всяких изысков и оптимизаций.

Дятелы из майкрософт, наконец-то догадались, что не всем нужно их сраное сглаживание - и стало возможно его отключить в виндовс 10, начиная с какого-то обновления. Теперь я могу ей пользоваться, более не приходится вынужденно сидеть на виндовс 7, и Courier New выглядит нормально, не вырвиглазно.

Но в линуксе такой роскоши нет, сглаживание прибито гвоздями.
Приходится в лазарусе какими-то левыми громадными шрифтами пользоваться, чтобы получить буквы, а не обмылки. А Courier под любым линуксом - выглядит, как сраное говно.

...короче, если смогу выделить время - сделаю хак для SynEdit, чтобы хотя бы тупо битмапный шрифт использовал вместо TextOut виджета. Но дело это - не простое, и не быстрое.
Эх, мечты - мечты.

З.Ы. Если шрифт - не моноширинный, то выбрать ширину буквы "О". Те, что уже - ставить по центру. Те, что шире - плющить.

З.З.Ы. Курсив/наклонный - это извращение, которому нечего делать в редакторе кода.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 639
Зарегистрирован: 06.06.2005 15:54:34

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение Mirage » 15.07.2018 23:06:21

Ступил конечно, причем тут FreeType, оно же не ownerdraw. Логично, что ОС в конечном итоге рисуют текст.

Cheb писал(а):Courier в линуксАх использовать тупо невозможно из-за неотключаемого вырвиглазного сглаживания.


Именно для курьера сглаживание? Само сглаживание шрифтов вроде отключается. По крайней мере в Убунте.

Cheb писал(а):З.З.Ы. Курсив/наклонный - это извращение, которому нечего делать в редакторе кода.


Спорно - хорошо помечать так например статические члены класса. Или интерфейсы.
Mirage
энтузиаст
 
Сообщения: 813
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение Cheb » 17.07.2018 10:37:44

Именно для курьера сглаживание?

Для всего, принудительное и неотключаемое.
И даже больше: меня грызёт сомнение. что это - ляп лазаревского виджета, а не системы.

Как пример, как надо, приведу Notepad++, коим пользуюсь по работе уже много лет. Он быстрый, Лазарь в сравнении - ржавый тормоз. И он вообще не позволяет выбирать шрифт - используется какой-то курьер, только размер можно менять по Ctrl + колесо мыши.

Вот скажите, *зачем* редактору кода что-то, кроме нормального Courier?
В лазаре это больше на отладочную фичу похоже, для хакания вокруг кривых ОС и кривых установок шрифтов.

хорошо помечать так например статические члены класса. Или интерфейсы.

Просто с правильными пиксельными шрифтами курсив не работает. Пока ни разу не видел, чтобы курсив без сглаживания не выглядел, как говно. А ведь и сам в своё время пробовал шрифты рисовать.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 639
Зарегистрирован: 06.06.2005 15:54:34

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение zoltanleo » 17.07.2018 10:50:54

Cheb писал(а):Как пример, как надо, приведу Notepad++

а почему бы не поднять обсуждение проблемы тут? ИМХО, шансов на какие-то подвижки было бы больше. И даже, если допилишь сабж до нужной кондиции в виде плагина-компонента к IDE, народ тебе только рукоплескать будет.
Аватара пользователя
zoltanleo
постоялец
 
Сообщения: 151
Зарегистрирован: 17.10.2013 10:55:01

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение Cheb » 17.07.2018 11:23:33

Ээээ, мил человек, у меня столько проектов в стеке висит, что даже не смешно, а грустно.

Насчёт зазаровского синедита, навскидку:
Доработать чтобы вместо TextOut использовалась прокладка, назовём её CodeEditorTextOut, где:
- все буквы кодом ниже 127 (базовая латиница) - из встроенного битмапного шрифта (набора оных на разные размеры), и выводятся каким-нибудь растровым методом виджета (не изучал пока).
- всё, что содержит буквы выше этого - а это будут *только* строковые константы! - выводится по старинке через TextOut, и только на них влияет выбор шрифта в редакторе. При этом ещё проверяется ширина текста и размер подгоняется на лету, чтобы влезало в рамки, диктуемые шириной встроенного шрифта.

Вот тогда будут и волки сыты, и овцы целы.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 639
Зарегистрирован: 06.06.2005 15:54:34

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение zoltanleo » 17.07.2018 11:56:25

Cheb писал(а):Ээээ, мил человек, у меня столько проектов в стеке висит, что даже не смешно, а грустно.

вот я и говорю: напиши фикс в виде компонента, навроде того же профайлера. Его просто включат в стандартный набор OPM, что позволит ставить на свежую сборку Лазаря одним кликом. И никого просить не надо. Только написать :)
Аватара пользователя
zoltanleo
постоялец
 
Сообщения: 151
Зарегистрирован: 17.10.2013 10:55:01

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение Mirage » 17.07.2018 23:34:28

Cheb писал(а):Вот скажите, *зачем* редактору кода что-то, кроме нормального Courier?


Мне, к примеру, больше нравится шрифт Consolas, а еще больше DejaVu Sans Mono, который в данный момент и используется.

Cheb писал(а):И даже больше: меня грызёт сомнение. что это - ляп лазаревского виджета, а не системы.


Система становится несглаженой при активации соотв. режима отрисовки шрифтов. Так что в системе принудительного нет. LCL по идее должен использовать системные средства вывода. Возможно, захардкожен какой-то параметр, приводящий к сглаженному выводу шрифтов независимо от системных настроек.
Mirage
энтузиаст
 
Сообщения: 813
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Кто-нить ковырял базовый класс редактора кода?

Сообщение mig-31 » 19.07.2018 19:24:41

Но в линуксе такой роскоши нет, сглаживание прибито гвоздями.

В KDE и GNOME во все времена можно было выключить сглаживание.
mig-31
постоялец
 
Сообщения: 180
Зарегистрирован: 14.07.2011 13:46:48


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot], Yandex [Bot] и гости: 7

Рейтинг@Mail.ru
cron