home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Pascal / BPASCAL.700 / D12 / TRUETYPE.ZIP / TTDEMO.PAS next >
Encoding:
Pascal/Delphi Source File  |  1992-10-01  |  13.2 KB  |  460 lines

  1. {***************************************************}
  2. {                                                   }
  3. {   Windows 3.1 TrueType Font Demonstration Program }
  4. {   Copyright (c) 1992 by Borland International     }
  5. {                                                   }
  6. {***************************************************}
  7.  
  8. {$N+}
  9.  
  10. program TrueTypeDemo;
  11.  
  12. { This program demonstrates some of the flexibility of the
  13.   TrueType font system for Windows 3.1 by generating a complex
  14.   display of rotated text.  The Font Selection dialog from the
  15.   Common Dialogs DLL is also demonstrated.
  16. }
  17.  
  18. {$R TTDEMO}
  19.  
  20. uses WinTypes, WinProcs, Win31, OWindows, ODialogs, Strings, CommDlg, BWCC;
  21.  
  22. const
  23.  
  24. { Application error message }
  25.  
  26.   em_WrongWinVersion = -10;
  27.  
  28. { Resource IDs }
  29.  
  30.   id_Menu  = 100;
  31.   id_About = 100;
  32.   id_Icon  = 1;
  33.  
  34. { Menu command IDs }
  35.  
  36.   cm_Shadows        = 201;
  37.   cm_Fonts          = 203;
  38.   cm_HelpAbout      = 300;
  39.  
  40. type
  41.  
  42. { Application main window }
  43.  
  44.   PFontWindow = ^TFontWindow;
  45.   TFontWindow = object(TWindow)
  46.  
  47.     MainFontRec,
  48.     LogoFontRec,
  49.     BorlandFontRec    : TLogFont;
  50.  
  51.     FanColor          : array [0..9] of TColorRef;
  52.     ShadowAll         : Boolean;
  53.     Rendering         : Boolean;
  54.  
  55.     constructor Init(AParent: PWindowsObject; ATitle: PChar);
  56.     function  GetClassName: PChar; virtual;
  57.     procedure GetWindowClass( var WC: TWndClass); virtual;
  58.  
  59.     procedure Paint(DC: HDC; var PS: TPaintStruct); virtual;
  60.  
  61.     procedure CMHelpAbout(var Msg: TMessage);
  62.       virtual cm_First + cm_HelpAbout;
  63.     procedure CMShadows(var Msg: TMessage);
  64.       virtual cm_First + cm_Shadows;
  65.     procedure CMFonts(var Msg: TMessage);
  66.       virtual cm_First + cm_Fonts;
  67.     procedure WMGetMinMaxInfo(var Msg: TMessage);
  68.       virtual wm_First + wm_GetMinMaxInfo;
  69.     procedure WMSize(var Msg: TMessage);
  70.       virtual wm_First + wm_Size;
  71.   end;
  72.  
  73. { Application object }
  74.  
  75.   TFontApp = object(TApplication)
  76.     procedure Error(ErrorCode: Integer); virtual;
  77.     procedure InitApplication; virtual;
  78.     procedure InitMainWindow; virtual;
  79.   end;
  80.  
  81. { Initialized globals }
  82.  
  83. const
  84.   DemoTitle: PChar = 'TrueType Demo';
  85.  
  86. { TFontWindow Methods }
  87.  
  88. { Constructs an instance of the TFontWindow.  Sets up the window's menu,
  89.   then initializes the Logical Font structures for the three fonts to
  90.   be used in the demo.
  91. }
  92. constructor TFontWindow.Init(AParent: PWindowsObject; ATitle: PChar);
  93. begin
  94.   TWindow.Init(AParent, ATitle);
  95.   Attr.Menu := LoadMenu(HInstance, PChar(id_Menu));
  96.  
  97. { Initialize the logical font record for the 'fan' text.  Default
  98.   is TimesNewRoman.
  99. }
  100.   with MainFontRec do
  101.   begin
  102.     lfHeight        := 26;
  103.     lfWidth         := 10;
  104.     lfEscapement    := 0;
  105.     lfOrientation   := 0;
  106.     lfWeight        := fw_Bold;
  107.     lfItalic        := 0;
  108.     lfUnderline     := 0;
  109.     lfStrikeOut     := 0;
  110.     lfCharSet       := ANSI_CharSet;
  111.     lfOutPrecision  := Out_Default_Precis;
  112.     lfClipPrecision := Clip_Default_Precis;
  113.     lfQuality       := Proof_Quality;
  114.     lfPitchAndFamily:= Variable_Pitch or FF_Roman;
  115.     StrCopy(lfFaceName,'Times New Roman');
  116.   end;
  117.  
  118.   LogoFontRec := MainFontRec;
  119.  
  120.   BorlandFontRec:= MainFontRec;
  121.   with BorlandFontRec do
  122.   begin
  123.     lfHeight:= 60;
  124.     lfWidth := 0;           {Choose best width for this height }
  125.     lfWeight:= 900;
  126.     StrCopy(lfFaceName, 'Arial');
  127.   end;
  128.  
  129. { Initialize an array of colors used to color the fan text }
  130.   FanColor[0] := RGB(255,0,0);
  131.   FanColor[1] := RGB(128,0,0);
  132.   FanColor[2] := RGB(255,128,0);
  133.   FanColor[3] := RGB(80,80,0);
  134.   FanColor[4] := RGB(80,255,0);
  135.   FanColor[5] := RGB(0,128,0);
  136.   FanColor[6] := RGB(0,128,255);
  137.   FanColor[7] := RGB(0,0,255);
  138.   FanColor[8] := RGB(128,128,128);
  139.   FanColor[9] := RGB(255,0,0);
  140.  
  141.   ShadowAll := False;
  142.   Rendering := False;
  143. end;
  144.  
  145. { Responds to repaint requests by completely redrawing the
  146.   fanned-text demo display.
  147. }
  148. procedure TFontWindow.Paint(DC: HDC; var PS: TPaintStruct);
  149. const
  150.   ArcText     = 'TrueType';
  151.   FanText     = 'Turbo Pascal for Windows';
  152.   BorlandText = 'Borland';
  153.   WaitText    = 'Windows is rendering fonts...';
  154.   Radius      = 100;   { Controls circle about which text is fanned }
  155.  
  156.   Deg2Rad : Extended = PI / 18;    { Used for angle calculations }
  157. type
  158.   TTextExtent = record
  159.     W, H: Word;
  160.   end;
  161. var
  162.   FontRec   : TLogFont;
  163.   FontMetric: TOutlineTextMetric;
  164.   FontHeight: Integer;
  165.   d         : Word;
  166.   x, y, j, k: Integer;
  167.   Theta     : Real;
  168.   P         : PChar;
  169.   CRect     : TRect;
  170.   BaseWidth,
  171.   DesiredExtent,
  172.   FanTextLen: Word;
  173.   TextExt   : TTextExtent;
  174. begin
  175.   P := ArcText;
  176.   FanTextLen := StrLen(FanText);
  177.  
  178.   SaveDC(DC);
  179.  
  180.   if Rendering then
  181.     { Display a message that Windows is rendering fonts, please wait... }
  182.     SetWindowText(HWindow, WaitText);
  183.  
  184. { Create the "TT" logo, in black-on-gray, at the upper left-hand
  185.   corner of the window.
  186. }
  187.   FontRec := LogoFontRec;
  188.   SetBkMode(DC, Transparent);
  189.   SetTextColor(DC, RGB(128, 128, 128));
  190.   FontRec.lfHeight:= FontRec.lfHeight * 2;
  191.   FontRec.lfWidth := Trunc(FontRec.lfWidth * 2.1);
  192.   SelectObject(DC, CreateFontIndirect(FontRec));
  193.   TextOut(DC, 18, 5, 'T', 1);
  194.   SetTextColor(DC, RGB(0, 0, 0));
  195.   TextOut(DC, 32, 13, 'T', 1);
  196.  
  197. { Next, get the TextMetrics for the font to be used as the fan
  198.   text.  This will be used to control the fanning, and to size
  199.   the window.
  200. }
  201.   GetClientRect(HWindow, CRect);
  202.   FontRec := MainFontRec;
  203.   DeleteObject(SelectObject(DC, CreateFontIndirect(FontRec)));
  204.   GetOutlineTextMetrics(DC, SizeOf(FontMetric), @FontMetric);
  205.   FontHeight := FontMetric.otmTextMetrics.tmHeight;
  206.   SetViewportOrg(DC, FontHeight+2, 0);
  207.   Dec(CRect.Right, FontHeight+2);
  208.   BaseWidth := LoWord(GetTextExtent(DC, FanText, FanTextLen));
  209.  
  210. { Always draw the inner circle around which the text will be
  211.   fanned (draw two circles for nice effect).  If Alignment
  212.   Marks are on, then draw the outer circle as well.  Use a Null
  213.   brush to avoid writing over text.
  214. }
  215.   SelectObject(DC, GetStockObject(Null_Brush));
  216.   Ellipse(DC, -(Radius-5),  -(Radius-5),  (Radius-5),  Radius-5);
  217.   Ellipse(DC, -(Radius-10), -(Radius-10), (Radius-10), Radius-10);
  218.  
  219.   SetTextColor(DC, FanColor[0]);
  220.   for d:= 27 to 36 do
  221.   begin
  222.     x := Round(Radius * cos( d * Deg2Rad));
  223.     y := Round(Radius * sin(-d * Deg2Rad)); { -d because y axis is inverted }
  224.  
  225.     Theta := -d * Deg2Rad;
  226.     if X <> 0 then
  227.       Theta := ArcTan((CRect.Right / CRect.Bottom) * (Y / X));
  228.  
  229.     j := Round(CRect.Right  * cos(Theta));
  230.     k := Round(CRect.Bottom * sin(Theta));
  231.  
  232. { Calculate how long the displayed string should be.
  233. }
  234.     DesiredExtent:= Round(Sqrt(Sqr(x*1.0 - j) + Sqr(y*1.0 - k))) - 5;
  235.     FontRec := MainFontRec;
  236.     FontRec.lfEscapement:= d * 100;
  237.     FontRec.lfWidth     := Trunc(FontMetric.otmTextMetrics.tmAveCharWidth *
  238.       (DesiredExtent / BaseWidth));
  239.     DeleteObject(SelectObject(DC, CreateFontIndirect(FontRec)));
  240.     Longint(TextExt) := GetTextExtent(DC, FanText, FanTextLen);
  241.  
  242. { Shave off some character width until the string fits
  243. }
  244.     while (TextExt.W > DesiredExtent) and (FontRec.lfWidth <> 0) do
  245.     begin
  246.       Dec(FontRec.lfWidth);
  247.       DeleteObject(SelectObject(DC, CreateFontIndirect(FontRec)));
  248.       Longint(TextExt) := GetTextExtent(DC, FanText, FanTextLen);
  249.     end;
  250.  
  251. { Expand the string if necessary to make it fit the desired extent.
  252. }
  253.     if TextExt.W < DesiredExtent then
  254.       SetTextJustification(DC, DesiredExtent - TextExt.W, 3);
  255.  
  256. { If shadowing is enabled, draw an underlying copy of the string
  257.   in black.  Then, draw the text in the actual color.
  258. }
  259.     if ShadowAll then
  260.     begin
  261.       SetTextColor(DC, RGB(0, 0, 0));
  262.       TextOut(DC, x+2, y+1, FanText, FanTextLen);
  263.     end;
  264.     SetTextColor(DC, FanColor[d - 27]);
  265.     TextOut(DC, x, y, FanText, FanTextLen);
  266.     SetTextJustification(DC, 0, 0);  {Clear justifier's internal error
  267.                                       accumulator}
  268.  
  269.     if P[0] <> #0 then
  270.     begin
  271.       FontRec := LogoFontRec;
  272.       FontRec.lfEscapement:= (d + 10) * 100;
  273.       FontRec.lfWidth     := 0;
  274.       DeleteObject(SelectObject(DC, CreateFontIndirect(FontRec)));
  275.       SetTextColor(DC, 0);
  276.       x := Round((Radius - FontHeight - 5) * cos( d * Deg2Rad));
  277.       y := Round((Radius - FontHeight - 5) * sin(-d * Deg2Rad));
  278.       TextOut(DC, x, y, P, 1);
  279.       inc(P);
  280.     end;
  281.   end;      {for d:= 27 to 36}
  282.  
  283. { Render the Borland logo in the bottom-right corner.
  284. }
  285.   DeleteObject(SelectObject(DC, CreateFontIndirect(BorlandFontRec)));
  286.   Longint(TextExt) := GetTextExtent(DC, BorlandText, StrLen(BorlandText));
  287.   SetTextColor(DC, RGB(0, 0, 0));
  288.   TextOut(DC, CRect.Right - TextExt.W, CRect.Bottom - TextExt.H,
  289.               BorlandText, StrLen(BorlandText));
  290.   SetTextColor(DC, RGB(255, 0, 0));
  291.   TextOut(DC, CRect.Right - TextExt.W - 5, CRect.Bottom - TextExt.H,
  292.               BorlandText, StrLen(BorlandText));
  293.  
  294. { Restore the window caption to the proper title string, then clear the
  295.   rendering flag.  The flag will be set again when the window is resized.
  296. }
  297.   if Rendering then
  298.   begin
  299.     SetWindowText(HWindow, Attr.Title);
  300.     Rendering := False;
  301.   end;
  302.  
  303.   DeleteObject(SelectObject(DC, GetStockObject(System_Font)));
  304.   RestoreDC(DC, -1);
  305. end;
  306.  
  307. { Posts the About box dialog from the Help Menu.
  308. }
  309. procedure TFontWindow.CMHelpAbout(var Msg: TMessage);
  310. begin
  311.   Application^.ExecDialog(New(PDialog, Init(@Self, PChar(id_About))));
  312. end;
  313.  
  314. { Toggles the state of the text shadow display.  Repaints
  315.   the window to show the new state.
  316. }
  317. procedure TFontWindow.CMShadows(var Msg: TMessage);
  318. begin
  319.   ShadowAll := not ShadowAll;  { Set data field for repaint }
  320.   if ShadowAll then
  321.     CheckMenuItem(Attr.Menu, cm_Shadows, mf_ByCommand or mf_Checked)
  322.   else
  323.     CheckMenuItem(Attr.Menu, cm_Shadows, mf_ByCommand or mf_UnChecked);
  324.  
  325. { If the new state is to not show shadows, then clear the window
  326.   before repainting.  Otherwise, don't clear so that alignment
  327.   marks seem to appear without the text redrawing (it will actually
  328.   be redrawing over itself).
  329. }
  330.   InvalidateRect(HWindow, nil, not ShadowAll);
  331. end;
  332.  
  333. { Posts the ChooseFont dialog from CommDlg.tpu to allow the
  334.   user to select a new font.
  335. }
  336. procedure TFontWindow.CMFonts(var Msg: TMessage);
  337. var
  338.   ChooseRec: TChooseFont;
  339.   FontRec  : TLogFont;
  340. begin
  341.   FontRec := MainFontRec;
  342.   FillChar(ChooseRec, Sizeof(ChooseRec), #0);
  343.   with ChooseRec do
  344.   begin
  345.     lStructSize:= SizeOf(TChooseFont);
  346.     HWndOwner  := HWindow;
  347.     Flags      := cf_AnsiOnly or cf_TTOnly or cf_ScreenFonts
  348.                   or cf_EnableTemplate or cf_InitToLogFontStruct;
  349.     nFontType  := Screen_FontType;
  350.     lpLogFont  := @FontRec;
  351.     lpTemplateName := 'FontDlg';
  352.     ChooseRec.hInstance := System.hInstance;
  353.   end;
  354. { Post the dialog and check the result.  If OK clicked, then
  355.   only get the font name - we don't care what size the user
  356.   selected, since the demo uses canned sizes.  Invalidate the
  357.   window to redraw with the new font.
  358. }
  359.   if ChooseFont(ChooseRec) then
  360.   begin
  361.     StrCopy(MainFontRec.lfFaceName, FontRec.lfFaceName);
  362.     MainFontRec.lfWeight := FontRec.lfWeight;
  363.     MainFontRec.lfItalic := FontRec.lfItalic;
  364.     Rendering := True;
  365.     InvalidateRect(HWindow, nil, True);
  366.   end;
  367. end;
  368.  
  369. { Provides Windows with a minimum size for the application window,
  370.   so that the fonts don't get too small.
  371. }
  372. procedure TFontWindow.WMGetMinMaxInfo(var Msg: TMessage);
  373. type
  374.   TPointArray = array [0..4] of TPoint;
  375.   PPointArray = ^TPointArray;
  376. begin
  377.   PPointArray(Msg.LParam)^[3].X := 300;
  378.   PPointArray(Msg.LParam)^[3].Y := 300;
  379. end;
  380.  
  381. { Changes the window's class name so an icon can be associated with
  382.   this window.
  383. }
  384. function TFontWindow.GetClassName: PChar;
  385. begin
  386.   GetClassName := 'OWLTrueTypeDemoWindow';
  387. end;
  388.  
  389. { Associates an icon with the window class.
  390. }
  391. procedure TFontWindow.GetWindowClass( var WC: TWndClass);
  392. begin
  393.   TWindow.GetWindowClass(WC);
  394.   WC.hIcon := LoadIcon(hInstance, PChar(id_Icon));
  395. end;
  396.  
  397. { When the window is resized, the size of the fonts may need to change.
  398.   This sets the Rendering flag so the Paint method can tell the user
  399.   that delays in painting are due to Windows generating new fonts.
  400. }
  401. procedure TFontWindow.WMSize(var Msg: TMessage);
  402. begin
  403.   TWindow.WMSize(Msg);
  404.   Rendering := True;
  405. end;
  406.  
  407.  
  408.  
  409. procedure TFontApp.Error(ErrorCode: Integer);
  410. begin
  411.   if ErrorCode = em_WrongWinVersion then
  412.   begin
  413.     MessageBox(0, 'This program requires Windows 3.1 TrueType fonts.',
  414.                   'Wrong Windows Version', mb_OK);
  415.     Halt(Byte(ErrorCode));
  416.   end
  417.   else
  418.     inherited Error(ErrorCode);
  419. end;
  420.  
  421. type
  422.   WinVersion = record
  423.     WinMajor,
  424.     WinMinor,
  425.     DosMajor,
  426.     DosMinor: Byte;
  427.   end;
  428.  
  429. { Verifies that the current operating environment is Win 3.1 or later }
  430. procedure TFontApp.InitApplication;
  431. var
  432.   v: WinVersion;
  433. begin
  434.   Longint(V) := GetVersion;
  435.   if not ((V.WinMajor >= 3) and (V.WinMinor >= 10)) then
  436.     Status := em_WrongWinVersion;
  437. end; 
  438.  
  439.  
  440. { Constructs the an instance of TFontWindow as the TFontApp's
  441.   MainWindow object.
  442. }
  443. procedure TFontApp.InitMainWindow;
  444. begin
  445.   MainWindow := New(PFontWindow, Init(nil, Application^.Name));
  446. end;
  447.  
  448.  
  449. var
  450.   App: TFontApp;
  451.  
  452.  
  453. { Main program }
  454.  
  455. begin
  456.   App.Init(DemoTitle);
  457.   App.Run;
  458.   App.Done;
  459. end.
  460.