Форум: "Начинающим";
Текущий архив: 2010.03.21;
Скачать: [xml.tar.bz2];
Внизcanvas.textWidth для разных стилей Найти похожие ветки
← →
novichek (2010-01-18 22:31) [0]Устанавливаю стиль в 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 ?
← →
Игорь Шевченко © (2010-01-18 22:42) [1]
> canvas.textWidth возвращает то же самое что и при отсутствии
> стиля.
Было бы странно обратное.
http://www.rsdn.ru/forum/winapi/1098456.flat.aspx
← →
novichek (2010-01-18 22:51) [2]ну было бы..
только вот для одного шрифта разное для другого одинаковое а то ещё и меньше..
простите, я немного не силен в Си, не могли бы показать на дельфи как правильно узнать реальную ширину строки с учётом fsItalic ?
← →
antonn © (2010-01-18 23:13) [3]когда то создавал подобную тему, ответ MBo+Джо:
function GetStringRect (const AString: string; const X,Y: Integer; AFont: TFont): TRect;
var
DC: HDC;
RGN: HRGN;
begin
DC := CreateCompatibleDC(0);
Win32Check(DC<>0);
try
SelectObject(DC, AFont.Handle);
Win32Check(BeginPath(DC));
try
TextOut(DC,X,Y,PChar(AString),Length(AString));
finally
EndPath(DC);
end;
RGN := PathToRegion(DC);
Win32Check(RGN<>0);
try
GetRgnBox(RGN,Result);
finally
DeleteObject(RGN);
end;
finally
DeleteDC(DC);
end;
end;
procedure TForm10.Button1Click(Sender: TObject);
var
Rct: TRect;
Size: TSize;
begin
Image1.Canvas.Font.Name := "Tahoma";
Image1.Canvas.Font.Size := 14;
Image1.Canvas.Font.Style := [fsItalic];
Rct := GetStringRect(Caption,10,20,Image1.Canvas.Font);
Image1.Canvas.Brush.Style := bsSolid;
Image1.Canvas.Brush.Color := clRed;
Image1.Canvas.FillRect(Rct);
Image1.Canvas.Brush.Style := bsClear;
Image1.Canvas.TextOut(10,20,Caption);
end;
мой велосипедный ужас:procedure GetGrebaniyFontWidth(s:string; _F:Tfont; var _R:Trect);
const MaxPixelCount = MaxInt div SizeOf(TRGBTriple);
type TBack_Settings=(bs_Gradient_horizontal,bs_Gradient_vertical,bs_Picture);
PRGBArray = ^TRGBArray;
TRGBArray = array[0..MaxPixelCount-1] of TRGBTriple;
var _x,_y:integer; used:boolean;
Row: PRGBArray;
_B:TBitmap;
begin
_B:=TBitmap.Create;
try
_B.PixelFormat:=pf24bit;
_B.Canvas.Font:=_F;
_B.Width:=_B.Canvas.TextWidth(s)+trunc(_B.Canvas.TextWidth(s)*0.5);
_B.Height:=_B.Canvas.TextHeight(s); _B.Canvas.FillRect(_B.Canvas.ClipRect);
_R.Top:=_B.Height; _R.Bottom:=0; _R.Left:=_B.Width; _R.Right:=0;
_B.Canvas.TextOut(0,0,s);
for _y:=0 to _b.Height-1 do begin
Row:=_b.ScanLine[_y];
used:=true;
for _x:=_B.Width-1 downto 0 do
if used then begin
if (Row[_x].rgbtRed=0) then begin
used:=false;
if _r.Right<_x then _R.Right:=_x;
end;
end;
used:=true;
for _x:=0 to _B.Width-1 do
if used then begin
if (Row[_x].rgbtRed=0) then begin
used:=false;
if _r.Left>_x then _R.Left:=_x;
end;
end;
used:=true;
for _x:=0 to _B.Width-1 do
if used then begin
if (Row[_x].rgbtRed=0)and(_R.Top>_y) then begin
used:=false;
_R.top:=_y;
end;
end;
used:=true;
for _x:=0 to _B.Width-1 do
if used then begin
if (Row[_x].rgbtRed=0)and(_R.Bottom<_y) then begin
used:=false;
_R.Bottom:=_y;
end;
end;
end;
finally
_B.Free;
end;
end;
← →
Игорь Шевченко © (2010-01-18 23:13) [4]http://support.microsoft.com/kb/74298/en-us
Сильным в C быть не надо, в статье перечислены функции, котоые нужно вызывать в нужной последовательности.
Ширина строки определяется абсолютно верно, а для того, чтобы определить ширину прямоугольника, описанного вокруг строки, нужно отнимать, как написано в статье, Textmetric.tmOverhang
Есть более сложный и более точный способ:
http://www.codeproject.com/KB/GDI/italicText.aspx
← →
novichek (2010-01-18 23:19) [5]хотел посмотреть в самой дельфи, как например авторазмер вычисляется для той же лабельки, так и нифига некорректно.
установил размер в 40, жирный-нклонный и шрифт Comic Sans MS, при установке AutoSize край текста не входит..
попробывал GetTextExtentPoint32(bmp.Canvas.Handle, PChar(text), Length(text), sz);
sz.cy то же неверно...
помогите кто знает как правильно узнать ширину..
← →
Игорь Шевченко © (2010-01-18 23:20) [6]
> GetTextExtentPoint32(bmp.Canvas.Handle, PChar(text), Length(text),
> sz);
Это то же самое, что TextWidth
← →
novichek (2010-01-18 23:20) [7]спасибо, пока писал Вы ответили..
попробую разобраться ещё раз )
← →
antonn © (2010-01-18 23:22) [8]если искать ширину попиксельно с включенным clearType то габариты текста будут сильно завышены :(
← →
Игорь Шевченко © (2010-01-18 23:23) [9]А на практике для Italic увеличивают ширину на значение высоты шрифта, для 98% случаев подходит.
← →
Anatoly Podgoretsky © (2010-01-18 23:27) [10]> Игорь Шевченко (18.01.2010 23:23:09) [9]
А почему не на sin(a), угол же наклона порядка 15 градусов, а не 90
← →
antonn © (2010-01-18 23:32) [11]есть шрифты типа "Пушкин-style" у которых в italic вензеля и рюшечки так забабахиваются в сторону... :(
← →
Игорь Шевченко © (2010-01-18 23:44) [12]Anatoly Podgoretsky © (18.01.10 23:27) [10]
А фиг знает
← →
Anatoly Podgoretsky © (2010-01-18 23:53) [13]> antonn (18.01.2010 23:32:11) [11]
Ну и что, они учитываются в метрики и + 15%
Шрифты то пропорциональные.
← →
Anatoly Podgoretsky © (2010-01-18 23:53) [14]> Игорь Шевченко (18.01.2010 23:44:12) [12]
Перестраховка?
← →
novichek (2010-01-19 00:11) [15]блин, кипит моск...
зжальтесь, покажите на дельфи как использовать GetCharWidth32, GetCharWidth..
вообще зациклился, так как у меня строка в юникоде и могут быть и китайские символы..
← →
Игорь Шевченко © (2010-01-19 00:15) [16]Anatoly Podgoretsky © (18.01.10 23:53) [14]
Отчасти, я думаю, вместо дополнительных вызовов GetABCCharWidths
← →
Игорь Шевченко © (2010-01-19 00:16) [17]
> и могут быть и китайские символы..
Китайские это фигня по сравнению с арабскими
← →
novichek (2010-01-19 00:23) [18]что такое GetABCCharWidths ?
я так понимаю, мне нужно узнать ширину последнего символа и учитывать разницу в наклоне..
arr: array[0..0] of TABC;
...
GetCharABCWidthsFloat(bmp.Canvas.Handle, Ord("t"), Ord("t"), arr);
arr[0].abcC отрицательно, да и другие вообще огромные числа..
что дальге делать не пойму, в сишном коде
if(dOverhangTrailing<0)
{
lWidth-=(LONG)dOverhangTrailing; // Last character"s overhang
}
что значит ?
← →
Игорь Шевченко © (2010-01-19 00:27) [19]
> что такое GetABCCharWidths
http://msdn.microsoft.com/en-us/library/dd144857(VS.85).aspx
← →
novichek (2010-01-19 00:46) [20]GetCharABCWidthsW(bmp.Canvas.Handle, 0, 255, arr);
dOverhangTrailing:= 0;
for I := 1 to length(test) do dOverhangTrailing:= dOverhangTrailing + arr[Ord(test[i])].abcA+ arr[Ord(test[i])].abcB+ arr[Ord(test[i])].abcC;
bmp.Width:= dOverhangTrailing;
почему-то то же самое что и TextWidth - край текста вышел за пределы..
← →
novichek (2010-01-19 00:50) [21]"А на практике для Italic увеличивают ширину на значение высоты шрифта, для 98% случаев подходит."
dOverhangTrailing:= bmp.Canvas.TextWidth(test) + bmp.Canvas.TextHeight("t");
bmp.Width:= dOverhangTrailing;
слишком уж много...
← →
novichek (2010-01-19 01:10) [22]попробывал явно задать чуть побольше ширину и отрисовать текст
bmp.Canvas.TextOut(0, 0, test);
затем думал установить реальную ширину, используя крайнюю позицию
bmp.Width:= bmp.Canvas.PenPos.X;
нифига.. всё равно не учитывается Italic..
я так понял никто тут не поможет?
← →
novichek (2010-01-19 01:23) [23]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;
← →
Игорь Шевченко © (2010-01-19 01:39) [24]novichek (19.01.10 01:23) [23]
Попробуй, чтобы влезло слово fluff или Fluff
← →
novichek (2010-01-19 01:49) [25]нормально вроде бы входит..
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 09:54) [26]
> novichek (19.01.10 01:49) [25]
А ты не пробовал просто DrawText использовать с флагом DT_CALCRECT?
← →
antonn © (2010-01-19 12:46) [27]
> А ты не пробовал просто DrawText использовать с флагом DT_CALCRECT?
с ним такая же ерунда
← →
Anatoly Podgoretsky © (2010-01-19 13:11) [28]> antonn (19.01.2010 12:46:27) [27]
Не ищи не ерунды, это ошибка (особенность) в генофонде. Борются добавляя предопределенное смещение
← →
antonn © (2010-01-19 13:53) [29]я бы догадался, что борются с этим добавляя некое смещение. Только имея дело не только с tahoma, а с более размашистыми шрифтами предопределенное смещение нужно вычислять самому, либо просто узнавать размеры отрендеренного шрифта.
← →
Игорь Шевченко © (2010-01-19 15:43) [30]antonn © (19.01.10 13:53) [29]
Я вчера малость попробовал, так чтобы слово fluff влезло, надо высоту шрифта прибавлять. Шрифт брал размером 72, с засечками и без них.
← →
antonn © (2010-01-19 15:53) [31]все таки это смахивает больше на костыль :)
← →
Игорь Шевченко © (2010-01-19 15:55) [32]antonn © (19.01.10 15:53) [31]
> все таки это смахивает больше на костыль
Разумеется. Для некостыльных решений я привел три ссылки, еще у Фэня в книжке подробно обсуждается эта проблема.
← →
Демо © (2010-01-19 17:36) [33]В своё время была у меня такая задача.
Я поступил таким образом:
Для каждого стиля завёл массив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 17:45) [34]Демо © (19.01.10 17:36) [33]
А ничего, что размер символа зависит от его позиции ?
← →
Демо © (2010-01-19 19:32) [35]
> А ничего, что размер символа зависит от его позиции ?
Поясни мысль?
← →
Игорь Шевченко © (2010-01-19 19:45) [36]Демо © (19.01.10 19:32) [35]
Одни и те же символы по соседству с разными символами могут быть придвинуты к соседнему или наоборот, отодвинуты от соседа. То есть, для получения размера строки важна не сумма ширин отдельных символов, а сумма с учетом их взаимного расположения.
← →
Демо © (2010-01-19 20:22) [37]
> Игорь Шевченко © (19.01.10 19:45) [36]
> Демо © (19.01.10 19:32) [35] Одни и те же символы по соседству
> с разными символами могут быть придвинуты к соседнему или
> наоборот, отодвинуты от соседа. То есть, для получения размера
> строки важна не сумма ширин отдельных символов, а сумма
> с учетом их взаимного расположения.
Понятно.
У меня вывод был посимвольный, поэтомусмещение вычислялось относительно предыдущего символа.
Вроде как всё было нормально. Ничто никуда не съезжало.
← →
Игорь Шевченко © (2010-01-19 20:45) [38]Для расчета позиций символов с учетом их взаимного расположения нужно вызывать функции GetKerningPairs и(или) GetCharacterPlacement
Все это я к чему - вывод текста может оказаться весьма нетривиальным занятием
← →
Anatoly Podgoretsky © (2010-01-19 21:16) [39]> Демо (19.01.2010 17:36:33) [33]
А нафига ты посимвольно их делаешь, когда у тебя есть размер всей строки, вот его и корректируй
← →
Anatoly Podgoretsky © (2010-01-19 21:17) [40]> Игорь Шевченко (19.01.2010 20:45:38) [38]
Вот поэтому и системой и делается простой расчет, нафига им нетривиальность.
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2010.03.21;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.009 c