Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
2-1264058602
tipman
2010-01-21 10:23
2010.03.21
Запуск файла с любым расширением ( *.doc) в качестве исполняемого


15-1262056626
товарищ икс
2009-12-29 06:17
2010.03.21
Младший бит на php


4-1226836612
kolj
2008-11-16 14:56
2010.03.21
Проблема с SendMessage


2-1263488516
HRustBB
2010-01-14 20:01
2010.03.21
как вызвать процедуру по ссылке?


2-1264014723
@!!ex
2010-01-20 22:12
2010.03.21
Как преобразовать кодировку GB2312 в UTF-8 или 16?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский