круговая печать
От: Viktor Sklyar Украина  
Дата: 20.09.06 12:18
Оценка:
Hello, All!

Возникла необходимость печатать по кругу. Скажите куда посмотреть?

Спасибо.
С Уважением.
Re: круговая печать
От: Аноним  
Дата: 20.09.06 12:34
Оценка:
Здравствуйте, Viktor Sklyar, Вы писали:

VS>Hello, All!


VS>Возникла необходимость печатать по кругу. Скажите куда посмотреть?


VS>Спасибо.


А нельзя ли поподробнее, что значит, "печатать по кругу"?
Re[2]: круговая печать
От: Viktor Sklyar Украина  
Дата: 20.09.06 12:35
Оценка:
Здравствуйте, Аноним, Вы писали:

VS>>Возникла необходимость печатать по кругу. Скажите куда посмотреть?

А>А нельзя ли поподробнее, что значит, "печатать по кругу"?

ну типа как на компакт дисках
С Уважением.
Re[3]: круговая печать
От: Аноним  
Дата: 20.09.06 12:39
Оценка:
VS>ну типа как на компакт дисках

Т.е. тебе текст надо выводить не прямой, а по какому-то пути?
Re[4]: круговая печать
От: Viktor Sklyar Украина  
Дата: 20.09.06 13:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Т.е. тебе текст надо выводить не прямой, а по какому-то пути?


совершенно верно, а точнее по окружности с заданным радиусом
С Уважением.
Re[5]: круговая печать
От: Lorenzo_LAMAS  
Дата: 20.09.06 14:24
Оценка:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/paths_2him.asp

вот тут ничего полезного нет?
Of course, the code must be complete enough to compile and link.
Re[6]: круговая печать
От: Viktor Sklyar Украина  
Дата: 20.09.06 14:54
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/paths_2him.asp


L_L>вот тут ничего полезного нет?


не вижу

а если серьезно, то вроде как там только 2 функции вывода текста TextOut и DrawText
С Уважением.
Re[7]: круговая печать
От: mcf  
Дата: 21.09.06 07:24
Оценка:
Здравствуйте, Viktor Sklyar, Вы писали:

VS>Здравствуйте, Lorenzo_LAMAS, Вы писали:


L_L>>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/paths_2him.asp


L_L>>вот тут ничего полезного нет?


VS>не вижу


VS>а если серьезно, то вроде как там только 2 функции вывода текста TextOut и DrawText


Дык печатай каждую буковку отдельно, определяй местоположение и наклон.
Re[8]: круговая печать
От: Viktor Sklyar Украина  
Дата: 21.09.06 12:03
Оценка:
Здравствуйте, mcf, Вы писали:


VS>>а если серьезно, то вроде как там только 2 функции вывода текста TextOut и DrawText


mcf>Дык печатай каждую буковку отдельно, определяй местоположение и наклон.


это первое что пришло мне в голову, но возможно есть какое-то готовое решение? API?
С Уважением.
Re[9]: круговая печать
От: dotidot Россия  
Дата: 21.09.06 12:42
Оценка: 1 (1) +2
Здравствуйте, Viktor Sklyar, Вы писали:

VS>Здравствуйте, mcf, Вы писали:


VS>это первое что пришло мне в голову, но возможно есть какое-то готовое решение? API?

agg умеет рисовать текст вдоль кривой.
см. здесь
Re[10]: круговая печать
От: vinnitu Украина  
Дата: 21.09.06 16:59
Оценка:
Здравствуйте, dotidot, Вы писали:

D>Здравствуйте, Viktor Sklyar, Вы писали:


VS>>Здравствуйте, mcf, Вы писали:


VS>>это первое что пришло мне в голову, но возможно есть какое-то готовое решение? API?

D>agg умеет рисовать текст вдоль кривой.
D>см. здесь

вот спасибо, такой библиотеки я еще не видел. Прекрасная работа.
С Уважением.
Re: круговая печать
От: vinnitu Украина  
Дата: 22.09.06 13:15
Оценка:
вот. буду переделывать на С++, результаты мне нравятся

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Math, Menus, Spin;

type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    SpinEdit1: TSpinEdit;
    SpinEdit2: TSpinEdit;
    MainMenu1: TMainMenu;
    Font1: TMenuItem;
    FontDialog1: TFontDialog;
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Font1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

var
  OS:        OSVERSIONINFO;
  IsNT,
  FChanged:  Boolean;

procedure CanvasTextOutAngle(c: TCanvas; x,y: Integer; d: Integer; s: string);
{-----------------------------------------------------------
  PURPOSE
    To output rotated text in the same font as the font on
    the supplied canvas. The font must also be a scaleable
    font.
  INPUT PARAMETERS
    c - The canvas on which to output the text. The font for
      the canvas must be a scalable font.
    x,y - The x,y screen coordinates you would normally
      supply the TextOut procedure.
    d - The angle in tenths of degrees. For example 10 would
      be 1 degree. 450 would be 45 degrees. 1 would be
      1/10 of a degree.
    s - The text to be output to the canvas.
  HISTORY
    6/18/1995 First version written by Curtis Keisler.
    11/23/1999 First version written by Walter Schick walter@xynx.com.
    Added support for Win NT, speeded-up somewhat, cleaned-up code.

-----------------------------------------------------------}
var
  LogRec:        LOGFONT;     //Storage area for font information
  OldFontHandle,              //The old font handle
  NewFontHandle: HFONT;       //Temporary font handle
begin
  if (IsNT) and (d>6000) then d:=d-740;
  SetTextAlign(c.Handle, TA_BASELINE);
  GetObject(c.Font.Handle, SizeOf(LogRec), @LogRec);
  LogRec.lfEscapement:=d;
  if (IsNT) then LogRec.lfOrientation:=-d;
  LogRec.lfQuality:=PROOF_QUALITY;
  NewFontHandle:=CreateFontIndirect(LogRec);
  OldFontHandle:=SelectObject(c.Handle,NewFontHandle);
  TextOut(c.Handle, x, y, PChar(s), 1);
  NewFontHandle:=SelectObject(c.Handle,OldFontHandle);
  DeleteObject(NewFontHandle);
end;

procedure CircularText(c: TCanvas; CenterX, CenterY: Integer; Radius: Integer;
            StartAngle: Integer; s: string; Style: Integer);
{-----------------------------------------------------------
  PURPOSE
    Calculates the position and angle of each character
    from the input string; they are drawn inside a circle
    defined by its center and radius, starting from the top
  INPUT PARAMETERS
    c - The canvas on which to output the text. The font for
        the canvas must be a scalable font.
    CenterX, CenterY - The circle center screen coordinates.
    Radius - The circle radius length.
    StartAngle - Angle where writing begins
    s - The text to be output to the canvas.
    Style - 0 : Left-Justified
            1 : Center-Justified
            1 : Right-Justified
  CALLS
    Calls CanvasTextOutAngle
  HISTORY
    4/30/1999  Added Center- and Right-justified text
    4/29/1999  Straighten up trigonometry: removed fudge factor;
               added StartAngle
    4/27/1999  First version written by Jacques Oberto.
    11/23/1999 Modifications written by Walter Schick.
               Added Options and fonts, cleaned-up some code,
               some other minor changes
-----------------------------------------------------------}
var
  RotAngle:   Extended;   //Rotation angle of each character
  PosAngle:   Extended;   //Angle on the circle at which to draw each character
  TotalAngle: Extended;   //Cumulated RotAngles
  Offset:     Extended;   //Angle between left and middle of the character
  FinalAngle: Extended;   //Total angle ocupied by text
  DummyAngle: Extended;
  i:          Integer;
begin
  FinalAngle:=0;
  //calculated total angle occupied by text
  for i:=1 to  length(s) do FinalAngle:=FinalAngle + ArcSin((c.TextWidth(s[i]))/Radius);
  case Style of
    1: DummyAngle:=FinalAngle / 2;
    2: DummyAngle:=FinalAngle;
    ELSE
      DummyAngle := FinalAngle
  end;
  Startangle:=StartAngle - Round(RadToDeg((DummyAngle))) +
    Round(RadToDeg(ArcSin((c.TextWidth(s[1])/2)/Radius)));
  TotalAngle:=0 ;
  for i:=1 to length(s) do
  begin
    //Trigonometry: angle = ArcSin(opposite side / adjacent side)
    Offset:=ArcSin((c.TextWidth(s[i])/2)/Radius);
    RotAngle:=RadToDeg(TotalAngle) + StartAngle;
    //We want 0 degree on top of the circle so we need to remove 90 degrees
    PosAngle:=DegToRad(Rotangle-90);
    CanvasTextOutAngle(Form1.Canvas,
                       //x coord on the circle circumference, for a given angle & radius
                       Round((Radius )*cos(PosAngle-Offset))+ CenterX,
                       //y coord , same
                       Round((Radius )*sin(PosAngle-Offset))+ CenterY,
                       //Angle in 10th degrees, negative because rotation is opposite
                       Round(RotAngle * -10), s[i]);
    //Increases TotalAngle by half angle of character + half angle of next character
    IF   i < LENGTH(s)    //  efg, 23 Jan 2000.  Avoid range check error.
    THEN TotalAngle:=TotalAngle + ArcSin((c.TextWidth(s[i])/2 + c.TextWidth(s[i+1])/2)/Radius);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form1.Refresh;
  SetBkMode(Canvas.Handle,TRANSPARENT);
  Canvas.Ellipse(4,4,350,350);
  if not FChanged then
  begin
    Canvas.Font.Name:='Arial';
    Canvas.Font.Size:=18;
  end;
  try
    CircularText(Canvas, 178, 178, SpinEdit2.Value, SpinEdit1.Value, Edit1.Text, 1);
    Except on EInvalidOp do
    begin
     MessageDlg('Please choose a greater radius', mtWarning, [mbOK], 0);
    end;
  end;  
end;

procedure TForm1.Font1Click(Sender: TObject);
begin
  if FontDialog1.Execute then
  begin
    Canvas.Font:=FontDialog1.Font;
    FChanged:=true;
  end;
end;

begin
  OS.dwOSVersionInfoSize:=SizeOf(OSVERSIONINFO);
  GetVersionEx(OS);
  IsNT:=OS.dwPlatformId=VER_PLATFORM_WIN32_NT;
end.
С Уважением.
Re[2]: круговая печать - помогите оптимизировать
От: vinnitu Украина  
Дата: 25.09.06 15:46
Оценка:
Пишу c WTL.

Получается коряво, помогите оптимизировать.


#define _USE_MATH_DEFINES
#include <math.h>

const double pi = 3.14159265358979323846;
const double degToRad = /*pi / 180.*/0.017453292519943295769236907684886;
const double radToDeg = /*1 / degToRad*/57.295779513082320876798154814105;

void TextOutAngle(CDC & dc, int x, int y, int d, CString & s)
{
    dc.SetTextAlign(TA_BASELINE);

    // Allocate memory for a LOGFONT structure.                    //как тут получить текущий шрифт и слегка изменить?
    PLOGFONT plf = (PLOGFONT) LocalAlloc(LPTR, sizeof(LOGFONT));   //перепробовал куча вариков, тока этот работает

    // Specify a font typeface name and weight.
    strcpy(plf->lfFaceName, "Arial");                              //так чтобы шрифт не менять, а использовать текущий
    plf->lfQuality = PROOF_QUALITY;

    plf->lfEscapement = d;
    CFont hFont;
    hFont.CreateFontIndirect(plf);
    HFONT hfntPrev = dc.SelectFont(hFont);

    dc.TextOut(x, y, s, 1);
    dc.SelectFont(hfntPrev);

    // Free the memory allocated for the LOGFONT structure.
    LocalFree((LOCALHANDLE) plf);                                    //понимаю так что этого не будет
}

void CircularText(CDC & dc, int CenterX, int CenterY, int Radius, int StartAngle, CString & s, int style)
{
    CSize sz;
    double FinalAngle = 0;
    for (int i = 0; i < s.GetLength(); i++)
    {
        dc.GetTextExtent((LPCTSTR)s + i, 1, &sz);
        FinalAngle += asin((double)sz.cx / Radius);
    }

    float DummyAngle = (style == 1)? FinalAngle / 2 : FinalAngle;
    
    dc.GetTextExtent((LPCTSTR)s, 1, &sz);
    StartAngle -= floor(radToDeg * DummyAngle /*+ 0.5*/);
    StartAngle += floor(radToDeg * asin((double)sz.cx / 2 / Radius) /*+ 0.5*/);

    double TotalAngle = 0;
    for (int i = 0; i < s.GetLength(); i++)
    {
        dc.GetTextExtent((LPCTSTR)s + i, 1, &sz);
        double Offset = asin((double)sz.cx / 2 / Radius);
        double RotAngle = radToDeg * TotalAngle + StartAngle;
        double PosAngle = degToRad * (RotAngle - 90);

        CString s2 = (LPCTSTR)s + i;
        TextOutAngle(dc,
            floor(Radius * cos(PosAngle - Offset) /*+ 0.5*/) + CenterX,
            floor(Radius * sin(PosAngle - Offset) /*+ 0.5*/) + CenterY,
            floor(RotAngle * -10), s2);

        if (i < s.GetLength())
        {
            CSize sz2;
            dc.GetTextExtent((LPCTSTR)s + i + 1, 1, &sz2);
            TotalAngle += asin(((double)sz.cx / 2 + (double)sz2.cx / 2) / Radius);
        }
    }
}
С Уважением.
Re[3]: круговая печать - помогите оптимизировать
От: Alex_Avr Россия  
Дата: 26.09.06 07:23
Оценка:
Здравствуйте, vinnitu

Для получения параметров текущего шрифта можно использовать функцию
GetObject примерно таким (для Win API) образом (подсмотрено в MFC в реализации CFont::GetLogFont):


LOGFONT lgFont; // создаем структуру на стеке, LocalAlloc/LocalFree, new/delete здесь незачем использовать

HFONT hFont; // здесь должен быть хэндл текущего шрифта
HFONT hNewFont = NULL; // здесь будет хэндл нового шрифта

if (::GetObject(hFont, sizeof(lgFont), &lgFont))
{
    // меняем нужные поля в lgFont;
    // ...

    // Создаем шрифт c модифицированными параметрами
    hNewFont = ::CreateFontIndirect (&lgFont);
    if (hNewFont != NULL)
    {
        // выбираем новый шрифт в контексте устройства и печатем что хотим
    }
}


На счет WTL не знаю, но, возможно, что у CFont есть готовая функции типа GetLogFont.
Если нет, то вышеприведенный код переделать для WTL нетрудно.
С уважением, Александр Авраменко.
Re[4]: круговая печать - помогите оптимизировать
От: vinnitu Украина  
Дата: 26.09.06 09:20
Оценка:
Здравствуйте, Alex_Avr, Вы писали:

if (::GetObject(hFont, sizeof(lgFont), &lgFont))


несколько смущает вызов функции без ссылки на графические контекст
С Уважением.
Re[4]: круговая печать - помогите оптимизировать
От: vinnitu Украина  
Дата: 26.09.06 09:44
Оценка:
с учётом рекомендаций

void TextOutAngle(CDC & dc, int x, int y, int d, CString & s)
{
    dc.SetTextAlign(TA_BASELINE);

    CFont oldFont = dc.GetCurrentFont();

    LOGFONT lf;
    oldFont.GetLogFont(lf);

    strcpy(lf.lfFaceName, "Arial"); //только вот незадача, тут если не выбирать самому шрифт
                                        //(а его выбирать не нужно, а использовать текущий), то буквы не поворачиваются!!)
                                        //вот у меня в тестовом приложении вообще по умолчанию System Font
        lf.lfQuality = PROOF_QUALITY;
     lf.lfEscapement = d;

    CFont newFont;
    newFont.CreateFontIndirect(&lf);
    dc.SelectFont(newFont);

    dc.TextOut(x, y, s, 1);

    dc.SelectFont(oldFont);
}
С Уважением.
Re[5]: круговая печать - помогите оптимизировать
От: Alex_Avr Россия  
Дата: 26.09.06 10:49
Оценка:
Здравствуйте, vinnitu, Вы писали:

V>
V>if (::GetObject(hFont, sizeof(lgFont), &lgFont))
V>


V>несколько смущает вызов функции без ссылки на графические контекст


Это нормально, т.к. сам по себе шрифт существует отдельно от контекста устройства,
это самостоятельный объект ОС. В контексте устройства сам шрифт не хранится,
используется только его хэндл как указатель на объект.

Соответственно, если у нас уже есть хэндл шрифта,
то для получения информации о шрифте контекст устройства не нужен. Ты же не используешь
контекст устройства при вызове CreateFontIndirect.
С уважением, Александр Авраменко.
Re[6]: круговая печать - помогите оптимизировать
От: vinnitu Украина  
Дата: 26.09.06 10:51
Оценка:
Здравствуйте, Alex_Avr, Вы писали:

A_A>Это нормально, т.к. сам по себе шрифт существует отдельно от контекста устройства,

A_A>это самостоятельный объект ОС. В контексте устройства сам шрифт не хранится,
A_A>используется только его хэндл как указатель на объект.

A_A>Соответственно, если у нас уже есть хэндл шрифта,

A_A>то для получения информации о шрифте контекст устройства не нужен. Ты же не используешь
A_A>контекст устройства при вызове CreateFontIndirect.

да, я понимаю, но на входе имеем только HDC и от него мы пляшем
С Уважением.
Re[5]: круговая печать - помогите оптимизировать
От: Alex_Avr Россия  
Дата: 26.09.06 10:56
Оценка:
Здравствуйте, vinnitu

V>
V>void TextOutAngle(CDC & dc, int x, int y, int d, CString & s)
V>{
        // ...
V>    LOGFONT lf;
V>    oldFont.GetLogFont(lf);

V>    strcpy(lf.lfFaceName, "Arial"); //только вот незадача, тут если не выбирать самому шрифт
V>                                        //(а его выбирать не нужно, а использовать текущий), то буквы не поворачиваются!!)
V>                                        //вот у меня в тестовом приложении вообще по умолчанию System Font
V>      lf.lfQuality = PROOF_QUALITY;
V>     lf.lfEscapement = d;
        // ...
V>}
V>


Похоже, что дело в том, что системный шрифт по умолчанию является растровым
(типа FixedSys/MS Sans Serif/MS Serif), а не векторным (TrueType/OpenType шрифтом, типа Aria/Times New Roman/Helvetica).
Вращение же растровых шрифтов Win API не поддерживает.
С уважением, Александр Авраменко.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.