![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
canvas.textWidth для разных стилей
novichek © (2010-01-18 22:31:00)Устанавливаю стиль в fsItalic.
canvas.textWidth возвращает то же самое что и при отсутствии стиля.
В результате конец текста обрезан немного.
Подскажите пожалуйста, с чем связано, что для одного шрифта результат вроде бы правильный, для другого нет..
в процессе мучения, из-за выхода текста за размеры, набросал для теста:
procedure TForm1.Button1Click(Sender: TObject);
const
// test = 'Проверка связи ры ры ры рычаг';
test = 'test test test test';
var
bmp: TBitmap;
x1, x2, x3, x4: Integer;
procedure drawbmp(offset: Integer);
begin
bmp.Canvas.FillRect(bmp.Canvas.ClipRect);
bmp.Canvas.TextOut(0, 0, test);
form1.Canvas.Draw(0, offset, bmp);
end;
begin
bmp:= TBitmap.Create;
bmp.Canvas.Brush.Color:= clBlack;
bmp.Canvas.Font.Color:= clWhite;
bmp.Canvas.Font.Name:= 'Comic Sans MS';
bmp.Canvas.Font.Size:= 40;
bmp.Height:= bmp.Canvas.TextHeight('Py');
bmp.Canvas.Font.Style:=[];
x1:= bmp.Canvas.TextWidth(test);
bmp.Width:= x1;
drawbmp(0);
bmp.Canvas.Font.Style:=[fsItalic];
x2:= bmp.Canvas.TextWidth(test);
bmp.Width:= x2;
drawbmp(bmp.Height + 10);
bmp.Canvas.Font.Style:=[fsBold];
x3:= bmp.Canvas.TextWidth(test);
bmp.Width:= x3;
drawbmp(bmp.Height*2 + 10*2);
bmp.Canvas.Font.Style:=[fsBold, fsItalic];
x4:= bmp.Canvas.TextWidth(test);
bmp.Width:= x4;
drawbmp(bmp.Height*3 + 10*3);
bmp.Free;
ShowMessage('[] - '+IntToStr(x1)+', [fsItalic] - '+IntToStr(x2)+', [fsBold] - '+IntToStr(x3)+', [fsBold, fsItalic] - '+IntToStr(x4));
end;
с чего и сделал вывод, что возвращаемые значения ширины немного не понятные..
как узнать для данного шрифта правильный размер при fsItalic ?
antonn (2010-01-19 21:24:00) [1]например потому что есть текстурные шрифты
Anatoly Podgoretsky (2010-01-19 21:17:00) [2]> Игорь Шевченко (19.01.2010 20:45:38) [38]
Вот поэтому и системой и делается простой расчет, нафига им нетривиальность.
Anatoly Podgoretsky (2010-01-19 21:16:00) [3]> Демо (19.01.2010 17:36:33) [33]
А нафига ты посимвольно их делаешь, когда у тебя есть размер всей строки, вот его и корректируй
Игорь Шевченко (2010-01-19 20:45:00) [4]Для расчета позиций символов с учетом их взаимного расположения нужно вызывать функции GetKerningPairs и(или) GetCharacterPlacement
Все это я к чему - вывод текста может оказаться весьма нетривиальным занятием
Демо (2010-01-19 20:22:00) [5]
> Игорь Шевченко © (19.01.10 19:45) [36]
> Демо © (19.01.10 19:32) [35] Одни и те же символы по соседству
> с разными символами могут быть придвинуты к соседнему или
> наоборот, отодвинуты от соседа. То есть, для получения размера
> строки важна не сумма ширин отдельных символов, а сумма
> с учетом их взаимного расположения.
Понятно.
У меня вывод был посимвольный, поэтомусмещение вычислялось относительно предыдущего символа.
Вроде как всё было нормально. Ничто никуда не съезжало.
Игорь Шевченко (2010-01-19 19:45:00) [6]Демо © (19.01.10 19:32) [35]
Одни и те же символы по соседству с разными символами могут быть придвинуты к соседнему или наоборот, отодвинуты от соседа. То есть, для получения размера строки важна не сумма ширин отдельных символов, а сумма с учетом их взаимного расположения.
Демо (2010-01-19 19:32:00) [7]
> А ничего, что размер символа зависит от его позиции ?
Поясни мысль?
Игорь Шевченко (2010-01-19 17:45:00) [8]Демо © (19.01.10 17:36) [33]
А ничего, что размер символа зависит от его позиции ?
Демо (2010-01-19 17:36:00) [9]В своё время была у меня такая задача.
Я поступил таким образом:
Для каждого стиля завёл массив
WSym: array[Char] of Integer;
HSym: array[Char] of Integer;
WSymBold: array[Char] of Integer;
HSymBold: array[Char] of Integer;
WSymItalic: array[Char] of Integer;
HSymItalic: array[Char] of Integer;
WSymUnderLine: array[Char] of Integer;
HSymUnderLine: array[Char] of Integer;
Предварительно вычислял размеры символов и заносил в массив.
При выводе на холст оставалось пройти по строке, получить длину каждого символа и рассчитать длину строки.
Игорь Шевченко (2010-01-19 15:55:00) [10]antonn © (19.01.10 15:53) [31]
> все таки это смахивает больше на костыль
Разумеется. Для некостыльных решений я привел три ссылки, еще у Фэня в книжке подробно обсуждается эта проблема.
antonn (2010-01-19 15:53:00) [11]все таки это смахивает больше на костыль :)
Игорь Шевченко (2010-01-19 15:43:00) [12]antonn © (19.01.10 13:53) [29]
Я вчера малость попробовал, так чтобы слово fluff влезло, надо высоту шрифта прибавлять. Шрифт брал размером 72, с засечками и без них.
antonn (2010-01-19 13:53:00) [13]я бы догадался, что борются с этим добавляя некое смещение. Только имея дело не только с tahoma, а с более размашистыми шрифтами предопределенное смещение нужно вычислять самому, либо просто узнавать размеры отрендеренного шрифта.
Anatoly Podgoretsky (2010-01-19 13:11:00) [14]> antonn (19.01.2010 12:46:27) [27]
Не ищи не ерунды, это ошибка (особенность) в генофонде. Борются добавляя предопределенное смещение
antonn (2010-01-19 12:46:00) [15]
> А ты не пробовал просто DrawText использовать с флагом DT_CALCRECT?
с ним такая же ерунда
Демо (2010-01-19 09:54:00) [16]
> novichek (19.01.10 01:49) [25]
А ты не пробовал просто DrawText использовать с флагом DT_CALCRECT?
novichek (2010-01-19 01:49:00) [17]нормально вроде бы входит..
function GetWidthText(bmp: TBitmap; text: String): Integer;
var
arr: array[0..0] of TABC;
begin
if trim(text)='' then exit(0);
result:= bmp.Canvas.TextWidth(text);
GetCharABCWidthsW(bmp.Canvas.Handle, ord(text[system.Length(text)]), ord(text[system.Length(text)]), arr);
if arr[0].abcC < 0 then result:= result - arr[0].abcC;
end;
Игорь Шевченко (2010-01-19 01:39:00) [18]novichek (19.01.10 01:23) [23]
Попробуй, чтобы влезло слово fluff или Fluff
novichek (2010-01-19 01:23:00) [19]GetCharABCWidthsW(bmp.Canvas.Handle, ord(test[length(test)]), ord(test[length(test)]), arr);
dOverhangTrailing:= bmp.Canvas.TextWidth(test);
if arr[0].abcC < 0 then dOverhangTrailing:= dOverhangTrailing + (arr[0].abcC*-1);
bmp.Width:= dOverhangTrailing;
novichek (2010-01-19 01:10:00) [20]попробывал явно задать чуть побольше ширину и отрисовать текст
bmp.Canvas.TextOut(0, 0, test);
затем думал установить реальную ширину, используя крайнюю позицию
bmp.Width:= bmp.Canvas.PenPos.X;
нифига.. всё равно не учитывается Italic..
я так понял никто тут не поможет?