home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlttype.pak / TRUETYPE.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  12KB  |  415 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //----------------------------------------------------------------------------
  4. #include <owl\owlpch.h>
  5. #include <owl\applicat.h>
  6. #include <owl\framewin.h>
  7. #include <owl\dialog.h>
  8. #include <owl\dc.h>
  9. #include <owl\choosefo.h>
  10. #include <owl\printer.h>
  11. #include <owl\editfile.rh>
  12. #include <string.h>
  13. #include <math.h>
  14. #include "truetype.h"
  15.  
  16. inline double Round(double x) {return floor(x + .5);}
  17. inline double Sqr(double x)   {return pow(x, 2);}
  18.  
  19.  
  20. //----------------------------------------------------------------------------
  21. // TWindowPrintout
  22.  
  23. class TWindowPrintout : public TPrintout {
  24.   public:
  25.     TWindowPrintout(const char* title, TWindow* window);
  26.  
  27.     void GetDialogInfo(int& minPage, int& maxPage,
  28.                                int& selFromPage, int& selToPage);
  29.     void PrintPage(int page, TRect& rect, unsigned flags);
  30.     void SetBanding(BOOL b) {Banding = b;}
  31.     BOOL HasPage(int pageNumber) {return pageNumber == 1;}
  32.  
  33.   protected:
  34.     TWindow* Window;
  35.     BOOL     Scale;
  36. };
  37.  
  38. TWindowPrintout::TWindowPrintout(const char* title, TWindow* window)
  39.   : TPrintout(title)
  40. {
  41.   Window = window;
  42.   Scale = TRUE;
  43. }
  44.  
  45. void
  46. TWindowPrintout::PrintPage(int, TRect& rect, unsigned)
  47. {
  48.   // Conditionally scale the DC to the window so the printout will
  49.   // resemble the window
  50.   //
  51.   int    prevMode;
  52.   TSize  oldVExt, oldWExt;
  53.   if (Scale) {
  54.     prevMode = DC->SetMapMode(MM_ISOTROPIC);
  55.     TRect windowSize = Window->GetClientRect();
  56.     DC->SetViewportExt(PageSize, &oldVExt);
  57.     DC->SetWindowExt(windowSize.Size(), &oldWExt);
  58.     DC->IntersectClipRect(windowSize);
  59.     DC->DPtoLP(rect, 2);
  60.   }
  61.  
  62.   // Call the window to paint itself
  63.   Window->Paint(*DC, FALSE, rect);
  64.  
  65.   // Restore changes made to the DC
  66.   if (Scale) {
  67.     DC->SetWindowExt(oldWExt);
  68.     DC->SetViewportExt(oldVExt);
  69.     DC->SetMapMode(prevMode);
  70.   }
  71. }
  72.  
  73. // Do not enable page range in the print dialog since only one page is
  74. // available to be printed
  75. //
  76. void
  77. TWindowPrintout::GetDialogInfo(int& minPage, int& maxPage,
  78.                                int& selFromPage, int& selToPage)
  79. {
  80.   minPage = 0;
  81.   maxPage = 0;
  82.   selFromPage = selToPage = 0;
  83. }
  84.  
  85. //----------------------------------------------------------------------------
  86. //
  87. class TFontWindow: public TFrameWindow {
  88.   public:
  89.     TFontWindow(TWindow* parent, const char* title);
  90.  
  91.   protected:
  92.     void Paint(TDC&, BOOL erase, TRect&);
  93.  
  94.     void EvGetMinMaxInfo(MINMAXINFO far&);
  95.     void EvSize(UINT, TSize&);
  96.  
  97.     void CmAbout();
  98.     void CmFilePrint();
  99.     void CmAlignmentMarks();
  100.     void CmFonts();
  101.     void CmShadows();
  102.  
  103.   private:
  104.     LOGFONT   MainFontRec;
  105.     LOGFONT   CornerFontRec;
  106.     LOGFONT   BorlandFontRec;
  107.     TColor    FanColor[10];
  108.     BOOL      ShadowAll;
  109.     BOOL      ShowAlignmentMarks;
  110.     BOOL      Rendering;
  111.     TPrinter* Printer;
  112.  
  113.   DECLARE_RESPONSE_TABLE(TFontWindow);
  114. };
  115.  
  116. DEFINE_RESPONSE_TABLE1(TFontWindow, TFrameWindow)
  117.   EV_WM_GETMINMAXINFO,
  118.   EV_WM_SIZE,
  119.   EV_COMMAND(CM_ABOUT, CmAbout),
  120.   EV_COMMAND(CM_FILEPRINT, CmFilePrint),
  121.   EV_COMMAND(CM_ALIGNMENTMARKS, CmAlignmentMarks),
  122.   EV_COMMAND(CM_FONTS, CmFonts),
  123.   EV_COMMAND(CM_SHADOWS, CmShadows),
  124. END_RESPONSE_TABLE;
  125.  
  126.  
  127. TFontWindow::TFontWindow(TWindow* parent, const char* title)
  128.   : TFrameWindow(parent, title),
  129.     TWindow(parent, title)
  130. {
  131.   AssignMenu(MR_TRUETYPE);
  132.  
  133.   MainFontRec.lfHeight = 26;
  134.   MainFontRec.lfWidth = 10;
  135.   MainFontRec.lfEscapement = 0;
  136.   MainFontRec.lfOrientation = 0;
  137.   MainFontRec.lfWeight = FW_BOLD;
  138.   MainFontRec.lfItalic = 0;
  139.   MainFontRec.lfUnderline = 0;
  140.   MainFontRec.lfStrikeOut = 0;
  141.   MainFontRec.lfCharSet = ANSI_CHARSET;
  142.   MainFontRec.lfOutPrecision = OUT_DEFAULT_PRECIS;
  143.   MainFontRec.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  144.   MainFontRec.lfQuality = PROOF_QUALITY;
  145.   MainFontRec.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
  146.   strcpy(MainFontRec.lfFaceName, "Times New Roman");
  147.  
  148.   CornerFontRec = MainFontRec;
  149.  
  150.   BorlandFontRec = MainFontRec;
  151.   BorlandFontRec.lfHeight = 60;
  152.   BorlandFontRec.lfWidth = 0;   // choose best width for this height
  153.   BorlandFontRec.lfWeight = 900;
  154.   strcpy(BorlandFontRec.lfFaceName, "Arial");
  155.  
  156.   // Array of colors used to color the fan text
  157.   FanColor[0] = TColor(255,0,0);
  158.   FanColor[1] = TColor(128,0,0);
  159.   FanColor[2] = TColor(255,128,0);
  160.   FanColor[3] = TColor(80,80,0);
  161.   FanColor[4] = TColor(80,255,0);
  162.   FanColor[5] = TColor(0,128,0);
  163.   FanColor[6] = TColor(0,128,255);
  164.   FanColor[7] = TColor(0,0,255);
  165.   FanColor[8] = TColor(128,128,128);
  166.   FanColor[9] = TColor(255,0,0);
  167.  
  168.   ShadowAll = 0;
  169.   ShowAlignmentMarks = 0;
  170.   Rendering = 0;
  171.   Printer = new TPrinter;
  172. }
  173.  
  174. //
  175. // Limit the minimum size of the window to 300x300, so the fonts don't get
  176. // too small
  177. //
  178. void
  179. TFontWindow::EvGetMinMaxInfo(MINMAXINFO far& mminfo)
  180. {
  181.   mminfo.ptMinTrackSize.x = 300;
  182.   mminfo.ptMinTrackSize.y = 300;
  183. }
  184.  
  185. //
  186. // Set the Re-render flag if the window changes size & is visible
  187. //
  188. void
  189. TFontWindow::EvSize(UINT sizeType, TSize& size)
  190. {
  191.   TWindow::EvSize(sizeType, size);
  192.   if (sizeType == SIZENORMAL || sizeType == SIZEFULLSCREEN) {
  193.     Rendering = TRUE;
  194.     Invalidate(TRUE);
  195.   }
  196. }
  197.  
  198. const char ArcText[] = "TrueType";
  199. const char* WaitText = "Windows is rendering fonts...";
  200. const char* FanText = "Borland C++ for Windows";
  201. const char* BorlandText = "Borland";
  202. const int   Radius = 100;
  203. const float Deg2Rad = M_PI / 18;
  204.  
  205. void
  206. TFontWindow::Paint(TDC& dc, BOOL, TRect&)
  207. {
  208.   const char* p = ArcText;
  209.   int fanTextLen = strlen(FanText);
  210.  
  211.   dc.SaveDC();
  212.  
  213.   if (Rendering)
  214.     // display a message that Windows is rendering fonts, please wait...
  215.     SetWindowText(WaitText);
  216.  
  217.   LOGFONT fontRec = CornerFontRec;
  218.   dc.SetBkMode(TRANSPARENT);
  219.   dc.SetTextColor(TColor(128,128,128));
  220.   fontRec.lfHeight = fontRec.lfHeight * 2;
  221.   fontRec.lfWidth = floor(fontRec.lfWidth * 2.1);
  222.   TFont* font = new TFont(&fontRec);
  223.   dc.SelectObject(*font);
  224.   dc.TextOut(18, 5, "T", 1);
  225.   dc.SetTextColor(TColor(0,0,0));
  226.   dc.TextOut(32, 13,"T", 1);
  227.   dc.RestoreFont();
  228.   delete font;
  229.  
  230.   TRect r = GetClientRect();
  231.  
  232.   fontRec = MainFontRec;
  233.   font = new TFont(&fontRec);
  234.   dc.SelectObject(*font);
  235.   
  236.   UINT fmSize = ::GetOutlineTextMetrics(HDC(dc), 0, 0);
  237.   OUTLINETEXTMETRIC* fontMetric = (OUTLINETEXTMETRIC*)new char[fmSize];
  238.   fontMetric->otmpFamilyName = 0;
  239.   fontMetric->otmpFaceName = 0;
  240.   fontMetric->otmpStyleName = 0;
  241.   fontMetric->otmpFullName = 0;
  242.   dc.GetOutlineTextMetrics(fmSize, *fontMetric);
  243.   int fontHeight = fontMetric->otmTextMetrics.tmHeight;
  244.   dc.SetViewportOrg(fontHeight+2, 0);
  245.   r.right -= fontHeight+2;
  246.   TSize size;
  247.   dc.GetTextExtent(FanText, fanTextLen, size);
  248.   int baseWidth = size.cx;
  249.   dc.RestoreFont();
  250.   delete font;
  251.  
  252.   dc.SelectStockObject(NULL_BRUSH);
  253.   if (ShowAlignmentMarks)
  254.     dc.Ellipse( -r.right, -r.bottom, r.right, r.bottom);
  255.   dc.Ellipse(-(Radius-5), -(Radius-5), Radius-5, Radius-5);
  256.   dc.Ellipse(-(Radius-10), -(Radius-10), Radius-10, Radius-10);
  257.  
  258.   dc.SetTextColor(FanColor[0]);
  259.   for (int d = 27; d <= 36; d++) {
  260.     int x = Round(Radius * cos(d * Deg2Rad));
  261.     int y = Round(Radius * sin(-d * Deg2Rad)); //-d because y axis is inverted
  262.  
  263.     float theta = -d * Deg2Rad;
  264.     if (x)
  265.       theta = atan((r.right / (r.bottom * 1.0)) * (y / (x * 1.0)));
  266.     int j = Round(r.right * cos(theta));
  267.     int k = Round(r.bottom * sin(theta));
  268.  
  269.     if (ShowAlignmentMarks) {
  270.       dc.MoveTo(x,y);
  271.       dc.LineTo(j,k);
  272.     }
  273.  
  274.     int desiredExtent = Round(sqrt(Sqr(x*1.0 - j) + Sqr(y*1.0 - k))) - 5;
  275.     fontRec = MainFontRec;
  276.     fontRec.lfEscapement = d * 100;
  277.     fontRec.lfOrientation = d * 100;
  278.     fontRec.lfWidth = floor(fontMetric->otmTextMetrics.tmAveCharWidth * (desiredExtent / (baseWidth * 1.0)));
  279.     font = new TFont(&fontRec);
  280.     dc.SelectObject(*font);
  281.  
  282.     // Shave off some character width until the string fits
  283.     //
  284.     dc.GetTextExtent(FanText, fanTextLen, size);
  285.     for (; size.cx > desiredExtent && fontRec.lfWidth; fontRec.lfWidth--) {
  286.       dc.RestoreFont();
  287.       delete font;
  288.       font = new TFont(&fontRec);
  289.       dc.SelectObject(*font);
  290.       dc.GetTextExtent(FanText, fanTextLen, size);
  291.     }
  292.  
  293.     // Expand the string if necessary to make it fit the desired extent
  294.     if (size.cx < desiredExtent)
  295.       dc.SetTextJustification(desiredExtent - size.cx, 3);
  296.     if (ShadowAll) {
  297.       dc.SetTextColor(TColor(0,0,0));
  298.       dc.TextOut(x+2, y+1, FanText, fanTextLen);
  299.     }
  300.     dc.SetTextColor(FanColor[d - 27]);
  301.     dc.TextOut(x, y, FanText, fanTextLen);
  302.     dc.SetTextJustification(0,0);  // clear justifier's internal error accumulator
  303.     dc.RestoreFont();
  304.     delete font;
  305.  
  306.     if (*p) {
  307.       fontRec = CornerFontRec;
  308.       fontRec.lfEscapement = (d+10) * 100;
  309.       fontRec.lfOrientation = (d+10) * 100;
  310.       fontRec.lfWidth = 0;
  311.       font = new TFont(&fontRec);
  312.       dc.SelectObject(*font);
  313.       dc.SetTextColor(0);
  314.       x = floor((Radius - fontHeight - 5) * cos(d * Deg2Rad));
  315.       y = floor((Radius - fontHeight - 5) * sin(-d * Deg2Rad));
  316.       dc.TextOut(x, y, p, 1);
  317.       dc.RestoreFont();
  318.       delete font;
  319.       p++;
  320.     }
  321.   }
  322.  
  323.   font = new TFont(&BorlandFontRec);
  324.   dc.SelectObject(*font);
  325.   dc.GetTextExtent(BorlandText, strlen(BorlandText), size);
  326.   dc.SetTextColor(TColor(0,0,0));
  327.   dc.TextOut(r.right-size.cx, r.bottom-size.cy, BorlandText, strlen(BorlandText));
  328.   dc.SetTextColor(TColor(255,0,0));
  329.   dc.TextOut(r.right-size.cx-5, r.bottom-size.cy, BorlandText, strlen(BorlandText));
  330.   dc.RestoreFont();
  331.   delete font;
  332.  
  333.   if (Rendering) {
  334.     // restore the window caption to the proper title string
  335.     SetWindowText(Title);
  336.     // clear the rendering flag.  It will be set again when the window is resized (WMSIZE)
  337.     Rendering = FALSE;
  338.   }
  339.  
  340.   dc.RestoreDC();
  341.   delete fontMetric;
  342. }
  343.  
  344. void
  345. TFontWindow::CmShadows()
  346. {
  347.   ShadowAll = !ShadowAll;
  348.   CheckMenuItem(GetMenu(), CM_SHADOWS,
  349.                 MF_BYCOMMAND | (ShadowAll ? MF_CHECKED : MF_UNCHECKED));
  350.   Invalidate(!ShadowAll);  // Erase if going Shadow -> no Shadow
  351. }
  352.  
  353. void
  354. TFontWindow::CmAlignmentMarks()
  355. {
  356.   ShowAlignmentMarks = !ShowAlignmentMarks;
  357.   CheckMenuItem(GetMenu(), CM_ALIGNMENTMARKS,
  358.                 MF_BYCOMMAND | (ShowAlignmentMarks ? MF_CHECKED : MF_UNCHECKED));
  359.   Invalidate(!ShowAlignmentMarks);  // Erase if going Marks -> no Marks
  360. }
  361.  
  362. void
  363. TFontWindow::CmAbout()
  364. {
  365.   TDialog(this, "About").Execute();
  366. }
  367.  
  368. void
  369. TFontWindow::CmFilePrint()
  370. {
  371.   if (Printer) {
  372.     TWindowPrintout printout("True Type Printout", this);
  373.     printout.SetBanding(TRUE);
  374.     Printer->Print(this, printout, TRUE);
  375.   }
  376. }
  377.  
  378. void
  379. TFontWindow::CmFonts()
  380. {
  381.   TChooseFontDialog::TData fontData;
  382.   fontData.LogFont = MainFontRec;
  383.   fontData.Flags = CF_ANSIONLY | CF_TTONLY | CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT;
  384.   fontData.FontType = SCREEN_FONTTYPE;
  385.   fontData.SizeMin = 20;
  386.   fontData.SizeMax = 20;
  387.  
  388.   if (TChooseFontDialog(this, fontData, "FontDlg").Execute()) {
  389.     // Only get the font name, weight, and italics - we don't care about size
  390.     strcpy(MainFontRec.lfFaceName, fontData.LogFont.lfFaceName);
  391.     MainFontRec.lfWeight = fontData.LogFont.lfWeight;
  392.     MainFontRec.lfItalic = fontData.LogFont.lfItalic;
  393.     Rendering = TRUE;
  394.     Invalidate(TRUE);
  395.   }
  396. }
  397.  
  398. //----------------------------------------------------------------------------
  399.  
  400. class TFontApp : public TApplication {
  401.   public:
  402.     TFontApp() : TApplication() {}
  403.     void InitMainWindow()
  404.     {
  405.       MainWindow = new TFontWindow(0, "TrueType Font Lab");
  406.       MainWindow->SetIcon(this, 1);
  407.     }
  408. };
  409.  
  410. int
  411. OwlMain(int /*argc*/, char* /*argv*/ [])
  412. {
  413.   return TFontApp().Run();
  414. }
  415.