Итак, год спустя описываю решение проблемы. Исследования проводил в Берлине, но думаю рецепт подойдет и для младших версий.
1. Ошибка существует в файле FMX.TextLayout.GPU, поэтому копируем его в проект.
2. Убираем мусор при отрисовке кропнутого символа.
Ищем в файле следующий фрагмент:
ColoredGlyph := TFontGlyphStyle.ColorGlyph in Rec.Glyph.Style;
if ColoredGlyph then
TCustomCanvasGpu(ACanvas).ModulateColor := $FFFFFFFF;
ACanvas.DrawBitmap(Rec.Bitmap, SrcR, R, Opacity);
if ColoredGlyph then
TCustomCanvasGpu(ACanvas).ModulateColor := LRun.Color;
и заменяем его на
if not R.IsEmpty then begin
// Disable draw empty rect
ColoredGlyph := TFontGlyphStyle.ColorGlyph in Rec.Glyph.Style;
if ColoredGlyph then
TCustomCanvasGpu(ACanvas).ModulateColor := $FFFFFFFF;
ACanvas.DrawBitmap(Rec.Bitmap, SrcR, R, Opacity);
if ColoredGlyph then
TCustomCanvasGpu(ACanvas).ModulateColor := LRun.Color;
end;
Пояснение: при расчете области отрисовки R символа, мы можем получить "отрицательный размер", где Bottom будет меньше чем Top. Соответсвенно такой же неправильной становиться область источника SrcR и на экран вылазит мусор.
3. От мусора избавились, но если присмотреться к нижней границе текста, то можно увидеть, что отрезка не ровная, одни символы отрезаны больше, другие меньше. Для этого нужно исправить алгоритм расчета области отсечения.
Для этого ищем комментарий //Checking for lines lower than bottom border - с него начинается ветка, в которую нужно внести изменения.
Чуть далее ищем код
Rec := AddOrGetChar(nil, Run.Chars[K], ChDic, Run.Font);
X := MaxSize.Y - FFrame.Last.TopLeft.Y - Rec.Glyph.VerticalAdvance * FScaleFactor;
и меняем его на
Rec := AddOrGetChar(LayoutCanvas, Run.Chars[K], ChDic, Run.Font);
X := MaxSize.Y - FFrame.Last.TopLeft.Y - ((Rec.SrcRect.Height + Rec.Glyph.Origin.Y) * FScaleFactor);
Здесь пояснения дать сложнее, скажу только, что разработчики проигнорировали тот момент, что символы имеют разные размеры (например . и Ж) и считают отсечение не по размеру глифа символа а по экранному размеру символа, т.е. он будет одинаковый для всей строки, что неправильно, так как в дальнейшем данное отсечение применяется к глифу символа.
P.S. А куда переехал CodeCentral, не нашел его в Берлине?