home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / OWLTTYPE.PAK / TRUETYPE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  11.8 KB  |  419 lines

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