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

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

определение максимально размера шрифта


novichek ©   (2010-01-09 23:12:00) 

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

пока делаю так:

устанавливаю размер шрифта канвы в 1.
в цикле увеличиваю размер шрифта пока canvas.TextWidth(myString) меньше ширины битмапа.
затем проверяю по высоте если больше то откатываю в цикле на 1 пока TextHight вернет значение меньше высоты.

прошу Вас подсказать, нет ли более изящного (быстрого, правильного,..)  решения ?

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


Дмитрий С   (2010-01-10 14:30:00) [1]

Можно сократить количество итераций цикла, усложнив алгоритм в [6] как при быстром поиске.


novichek   (2010-01-10 11:51:00) [2]

KilkennyCat ©, спасибо большое,  в далеке сознания была такая мысль )


KilkennyCat   (2010-01-10 11:23:00) [3]

Да это еще вопрос, выгадается ли... выполнение  Font.Size := Font.Size - 1; с последующим сравнением намного быстрее, чем  fz = Int (bitmap.width * fz / x )


KilkennyCat   (2010-01-10 11:21:00) [4]

что-либо прогнозировать разумно только для моноширинных шрифтов. Хотя, конечно, можно рассчитать некоторую зависимость и снизить число итераций цикла. Но на мой взгляд, учитывая не такой уж большой диапазон (от 6 до 18, да? иначе читать уже неудобно), какие-либо дополнительные вычисления не имеют смысла, ибо отнимут много времени на разработку, причем настолько много, что не компенсируется выгаданными микросекундами и за сотню лет использования программой всеми китайцами.


novichek   (2010-01-10 11:15:00) [5]

ну в принципе я так и делал с самого начала...
я вот всё пытаюсь отойти от цикла как-то.
например:

 fz = bitmap.canvas.font.size;

 x:= bitmap.canvas.textWidth(MaxString);
 
 и вот тут как-то бы вычислить новый fz, что бы X был наиболее приближен к bitmap.width
 я надеюсь что это же пропорционально и, например, новый
 fz = Int (bitmap.width * fz / x )

что-то такое.. будет работать правильно?


KilkennyCat   (2010-01-10 01:11:00) [6]

угу. используй [6] и не парься.


novichek   (2010-01-10 01:08:00) [7]

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


KilkennyCat   (2010-01-10 01:03:00) [8]

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


KilkennyCat   (2010-01-10 01:02:00) [9]


> смутило "возвращает значение высоты "

Разумеется. Текст имеет не только ширину, и может иметь не только одну строку. Тебе высота нужна? нет. ну дык и наплюй.


novichek   (2010-01-10 00:57:00) [10]

простите, наверное я не так понял, как то заумно написано:

DT_CALCRECT  
Выясняет ширину и высоту прямоугольника. Если имеется несколько строк текста, функция DrawText использует ширину прямоугольника, указанную параметром lpRect и продлевает основу прямоугольника, чтобы ограничить последнюю строку текста. Если самое большое слово шире, чем прямоугольник, ширина дополняется. Если текст - меньше, чем ширина прямоугольника, ширина уменьшается. Если есть только одна строка текста, DrawText изменяет правую сторону прямоугольника так, чтобы она ограничивала последнюю букву в строке. И в том, и в другом случае,

DrawText возвращает значение высоты отформатированного текста, но не выводит текст.

так же меня смутило "возвращает значение высоты "....


Юрий Зотов   (2010-01-10 00:56:00) [11]

S - самая длинная строка.

with Canvas do
 while TextWidth(S) > ClipRect.Right  do
   Font.Size := Font.Size - 1;


KilkennyCat   (2010-01-10 00:50:00) [12]


> я так понимаю он сожмется или растянется..

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


novichek   (2010-01-10 00:16:00) [13]

KilkennyCat ©, я так понимаю он сожмется или растянется..
сжатый вывод некрасивый...

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


novichek   (2010-01-10 00:11:00) [14]

хм.. вот сделал:

 function calcMaxSizeFont(val: String; w, y: Integer): Word;
 var
   LFont: TLogFont;
 begin
   if (w<2) or (h<2) then exit(1);
   LFont.lfHeight := y;
   LFont.lfWidth  := w div Length(val);
 end;

немножко непонятно, а как же узнать сам размер-то шрифта?
и так же наверное нужно учитывать что за шрифт у канвы..

я пока делаю так уродливо:

 function calcMaxSizeFont(val: String; w, y: Integer): Word;
 var
   canv: TCanvas;
 begin
   if (w<10) or (h<10) then exit(1);
   canv:= TCanvas.Create;
   canv.Font:= b1.Canvas.Font;
   canv.Font.Size:= 1;
   while canv.TextHeight('yЁ') < h do canv.Font.Size:= canv.Font.Size + 1;
   canv.Font.Size:= canv.Font.Size - 1;
   while canv.TextWidth(val) > w do canv.Font.Size:= canv.Font.Size - 1;
   result:= canv.Font.Size;
   canv.Free;
 end;


KilkennyCat   (2010-01-10 00:02:00) [15]

drawtext с флагом dt_CalcRect


{RASkov}   (2010-01-09 23:48:00) [16]

> [0] novichek   (09.01.10 23:12)

Попробуй var LFont: TLogFont; R: TRect канвы, S: String данная строка и примерно так:

 .....
 LFont.lfHeight := R.Bottom-R.Top;
 if LFont.lfHeight = 0 then LFont.lfHeight:=1;
 
 LFont.lfWidth  := (R.Right-R.Left) div Length(S);
 if LFont.lfWidth  = 0 then LFont.lfWidth :=1;
 .....


Наверх

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