Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

canvas.textWidth для разных стилей


Страницы:   1 2 3

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 ?


novichek   (2010-01-19 00:50:00) [21]

"А на практике для Italic увеличивают ширину на значение высоты шрифта, для 98% случаев подходит."

dOverhangTrailing:= bmp.Canvas.TextWidth(test) + bmp.Canvas.TextHeight('t');

bmp.Width:= dOverhangTrailing;

слишком уж много...


novichek   (2010-01-19 00:46:00) [22]

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 - край текста вышел за пределы..


Игорь Шевченко   (2010-01-19 00:27:00) [23]


> что такое GetABCCharWidths


http://msdn.microsoft.com/en-us/library/dd144857(VS.85).aspx


novichek   (2010-01-19 00:23:00) [24]

что такое 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:16:00) [25]


>  и могут быть и китайские символы..


Китайские это фигня по сравнению с арабскими


Игорь Шевченко   (2010-01-19 00:15:00) [26]

Anatoly Podgoretsky ©   (18.01.10 23:53) [14]

Отчасти, я думаю, вместо дополнительных вызовов GetABCCharWidths


novichek   (2010-01-19 00:11:00) [27]

блин, кипит моск...
зжальтесь, покажите на дельфи как использовать GetCharWidth32, GetCharWidth..

вообще зациклился, так как у меня строка в юникоде и могут быть и китайские символы..


Anatoly Podgoretsky   (2010-01-18 23:53:00) [28]

> Игорь Шевченко  (18.01.2010 23:44:12)  [12]

Перестраховка?


Anatoly Podgoretsky   (2010-01-18 23:53:00) [29]

> antonn  (18.01.2010 23:32:11)  [11]

Ну и что, они учитываются в метрики и + 15%
Шрифты то пропорциональные.


Игорь Шевченко   (2010-01-18 23:44:00) [30]

Anatoly Podgoretsky ©   (18.01.10 23:27) [10]

А фиг знает


antonn   (2010-01-18 23:32:00) [31]

есть шрифты типа "Пушкин-style" у которых в italic вензеля и рюшечки так забабахиваются в сторону... :(


Anatoly Podgoretsky   (2010-01-18 23:27:00) [32]

> Игорь Шевченко  (18.01.2010 23:23:09)  [9]

А почему не на sin(a), угол же наклона порядка 15 градусов, а не 90


Игорь Шевченко   (2010-01-18 23:23:00) [33]

А на практике для Italic увеличивают ширину на значение высоты шрифта, для 98% случаев подходит.


antonn   (2010-01-18 23:22:00) [34]

если искать ширину попиксельно с включенным clearType то габариты текста будут сильно завышены :(


novichek   (2010-01-18 23:20:00) [35]

спасибо, пока писал Вы ответили..
попробую разобраться ещё раз )


Игорь Шевченко   (2010-01-18 23:20:00) [36]


> GetTextExtentPoint32(bmp.Canvas.Handle, PChar(text), Length(text),
>  sz);


Это то же самое, что TextWidth


novichek   (2010-01-18 23:19:00) [37]

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

установил размер в 40, жирный-нклонный и шрифт Comic Sans MS, при установке AutoSize край текста не входит..

попробывал GetTextExtentPoint32(bmp.Canvas.Handle, PChar(text), Length(text), sz);

sz.cy то же неверно...

помогите кто знает как правильно узнать ширину..


Игорь Шевченко   (2010-01-18 23:13:00) [38]

http://support.microsoft.com/kb/74298/en-us

Сильным в C быть не надо, в статье перечислены функции, котоые нужно вызывать в нужной последовательности.

Ширина строки определяется абсолютно верно, а для того, чтобы определить ширину прямоугольника, описанного вокруг строки, нужно отнимать, как написано в статье, Textmetric.tmOverhang

Есть более сложный и более точный способ:

http://www.codeproject.com/KB/GDI/italicText.aspx


antonn   (2010-01-18 23:13:00) [39]

когда то создавал подобную тему, ответ 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;


novichek   (2010-01-18 22:51:00) [40]

ну было бы..
только вот для одного шрифта разное для другого одинаковое а то ещё и меньше..

простите, я немного не силен в Си, не могли бы показать на дельфи как правильно узнать реальную ширину строки с учётом fsItalic ?


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо