Перейти к содержанию
Fire Monkey от А до Я
  • 0

Вертикальное смещение юникодных шрифтов


Вадим Смоленский

Вопрос

В своем проекте (это японско-русский словарь) мне приходится выводить на TImage.Bitmap.Canvas хранящиеся в юникоде иероглифы, причем шрифт пользователь может выбрать сам. Столкнулся с неприятным явлением: разные шрифты располагают выводимый символ на разной высоте, в результате чего иероглиф часто не вписывается в предназначенную для него область. По умолчанию принят шрифт Tahoma, с ним всё хорошо:

JI_tahoma.png.756f1d23bc94c79ad622f20e25f44271.png

Но вот шрифт Yu Mincho:

JI_Yu_Mincho.png.f63e2b85d50bf8ae202b587c7b30f652.png

А вот, еще хлеще, Kozuka Gothic:

JI_Kozuka_Gothic.png.1856d8711b3cd526b42c278ddf699957.png

Вопрос: что за параметр регулирует вертикальное смещение, можно ли его вынуть и с ним работать?

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
48 минут назад, dnekrasov сказал:

Попробуйте сместить вверх на TTextMetric.tmExternalLeading

Компилятору не нравится, говорит: method identifier expected.

Ссылка на комментарий
  • 0
5 минут назад, Вадим Смоленский сказал:

Компилятору не нравится, говорит: method identifier expected

А как Вы его используете? TextMetric надо предварительно загрузить для выбранного шрифта API-шными функциями (посмотрите FMX.FontGlyphs.Win.TWinFontGlyphManager.LoadResource)

Изменено пользователем dnekrasov
Ссылка на комментарий
  • 0
4 минуты назад, dnekrasov сказал:

посмотрите FMX.FontGlyphs.Win.TWinFontGlyphManager.LoadResource

Простите мне мое невежество: это где нужно смотреть? В хелпах? На сайте Embarcadero? Где-нибудь еще?

Ссылка на комментарий
  • 0
2 минуты назад, Вадим Смоленский сказал:

это где нужно смотреть

Это использование WinAPI. В частности функция GetTextMetrics. Смотреть лучше всего в MSDN

В модуле FMX.FontGlyphs.Win в методе TWinFontGlyphManager.LoadResource просто хорошо видно как с ней работать.

Ссылка на комментарий
  • 0
2 часа назад, dnekrasov сказал:

В модуле FMX.FontGlyphs.Win в методе TWinFontGlyphManager.LoadResource просто хорошо видно как с ней работать.

Изучив упомянутый метод в указанном модуле, сделал вывод, что код должен выглядеть примерно так:

function FontVertShift (F: TFont): Single;
var Metrics: TTextMetric;
    DC: HDC;
    HF: HFont;
begin
  HF:=SelectObject(DC, F.Handle);
  SelectObject(DC, HF);
  GetTextMetrics(DC, Metrics);
  result := Metrics.tmExternalLeading
end;

Затык в том, что FireMonkey не предоставляет Handle для шрифта. Как же передать сюда шрифт?

Ссылка на комментарий
  • 0
1 час назад, Вадим Смоленский сказал:

Как же передать сюда шрифт?

Как-то так:

function FontVertShift (F: TFont): Single;
var
  Metrics: TTextMetric;
  DC: HDC;
  HF: HFont;
begin
  DC := CreateCompatibleDC(0);
  try
    HF := CreateFont(-Round(F.Size * GetDCScale(DC)), 0, 0, 0, FontWeightToWinapi(F.StyleExt.Weight),
      Cardinal(not F.StyleExt.Slant.IsRegular),
      0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
      CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
      DEFAULT_PITCH or FF_DONTCARE, PChar(F.Family));
    if HF = 0 then
      Exit(0);

    try
      SelectObject(DC, HF);
      GetTextMetrics(DC, Metrics);
    finally
      DeleteObject(HF);
    end;

    Result := Metrics.tmExternalLeading
  finally
    DeleteDC(DC);
  end;
end;

 

Изменено пользователем dnekrasov
Ссылка на комментарий
  • 0

Вот, кстати, tmInternalLeading больше похоже на то, что я ищу. Он недостаточно смещает, но пропорционально. Попробую подобрать коэффициент...

Ссылка на комментарий
  • 0

Код самый простой:

with MyImage.Bitmap.Canvas do
begin
 BeginScene;
 Font.Family := 'Tahoma';
 Font.Style := [];
 Font.Size := 60;
 FillText (RectF (0, 0-FontVertShift(Font), Width-1, Height-1), '字' , False , 1 , [] , TTextAlign.Leading, TTextAlign.Leading);
 EndScene;
end;

Код функции брал ваш, только tmExternalLeading заменил на  tmInternalLeading.

Шрифты пробовал такие (после названия - сначала значение tmInternalLeading, затем tmExternalLeading):

MS Mincho:  0, 0  (проблемы нет)
MS Gothic:  0, 0  (проблемы нет)
Tahoma:  12, 0  (в самый раз)
Yu Gothic:  17, 19  (недостаточно)
Kozuka Gothic Pr6N B:  50,0  (недостаточно)
Meiryo:  30, 0  (чересчур)

За ссылку спасибо, заглянул - но там, как я понял, материал для разработчиков шрифтов. Мои амбиции так далеко не простираются.

Ссылка на комментарий
  • 0

Почти для всех вышеперечисленных шрифтов по этой формуле получается как раз значение tmInternalLeading. Единственное исключение - Yu Gothic, для него получилось 36, против прежнего 17. Было недостаточно, стало чересчур. Подход по-прежнему работает только для шрифта Tahoma.

Ссылка на комментарий
  • 0

@Вадим Смоленский, попробуйте для шрифта Yu Gothic рассчитывать смещение как Font.Size * 0.408576 а для Kozuka Gothic Pr6N B - Font.Size * 1.0033 (мне просто интересно - правильно ли я рассчитал коэффиценты)

Ссылка на комментарий
  • 0
7 часов назад, Вадим Смоленский сказал:

Да, с этими коэффициентами на этих шрифтах выходит отлично!

Во как! Значит GetTextMetrics неправильно рассчитывает tmExternalLeading  и tmInternalLeading.

7 часов назад, Вадим Смоленский сказал:

Что же тут за калькуляция?

Сам расчет описан здесь

Ссылка на комментарий
  • 0
1 час назад, dnekrasov сказал:

@Вадим Смоленский, а можно как-то увидеть Ваш проект - а то дочка японский учит - сказала, что хороший словарик всегда пригодится :)

Да, конечно. Это ЯРКСИ (японско-русский компьютерный словарь иероглифов). Если ваша дочка про него еще не слышала, то вот он где:

http://www.susi.ru/yarxi

Там есть версии для мобильных платформ тоже. Версия 7.7 для Windows, которая вывешена, разрабатывалась еще в Delphi 6, которой я продолжал пользоваться до 2016 года. Сейчас перешел наконец в современную программную среду и целый год потратил на переделку интерфейса. Идет бета-тестирование; надеюсь через неделю-другую вывесить версию 8.0, которая будет несравнимо лучше. Так что есть смысл со скачиванием немножко подождать.

Документацию изучаю, но пока не смог понять, как именно нужно действовать...

Ссылка на комментарий
  • 0
18 минут назад, Вадим Смоленский сказал:

Если ваша дочка про него еще не слышала

Говорит, что слышала - однокурсники нахваливают, а преподаватели советуют.

 

20 минут назад, Вадим Смоленский сказал:

Документацию изучаю, но пока не смог понять, как именно нужно действовать

Посмотрите раздел "Baseline to Baseline Distances". Метрики шрифта я вытягивал с помощью редактора FontForge - как это сделать программно - не знаю, надо досконально разбираться в формате.

Ссылка на комментарий
  • 0
35 минут назад, dnekrasov сказал:

Посмотрите раздел "Baseline to Baseline Distances".

Мало что можно понять из этого раздела. Вот, дают формулу для external leading:

MAX( 0, LineGap - ((usWinAscent + usWinDescent) - (Ascender - Descender)))

Что такое LineGap? Какая разница между usWinAscent и Ascender? Как они оба соотносятся с нашим Metrics.tmAscent?

Трудно поверить, что я один во всем интернете столкнулся с этой проблемой. Где-то все-таки должен быть готовый алгоритм.

Ссылка на комментарий
  • 0
33 минуты назад, Вадим Смоленский сказал:

Что такое LineGap? Какая разница между usWinAscent и Ascender?

Про это можно почитать здесь

42 минуты назад, Вадим Смоленский сказал:

Как они оба соотносятся с нашим Metrics.tmAscent

Как я понял:

Metrics.tmAscent = unitsPerEm / Font.Size * uWinAscend

 

Ссылка на комментарий
  • 0
17 минут назад, dnekrasov сказал:

Про это можно почитать здесь

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

Да, если у вашей дочки есть телефон с андроидом, то буду рад выписать ей бесплатную лицензию на полную андроидную версию ЯРКСИ. Все-таки вы мне помогли, в какой-то мере прояснили вопрос. Пишите на vsСОБАКАsusi.ru

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...