home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / PREVIEW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  10.8 KB  |  389 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1992, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Definition of print preview classes
  6. //----------------------------------------------------------------------------
  7. #include <owl/owlpch.h>
  8. #include <owl/preview.h>
  9. #include <owl/printer.h>
  10. #include <owl/gdiobjec.h>
  11. #include <owl/dc.h>
  12. #include <owl/printdia.h>
  13. #include <math.h>
  14.  
  15. //
  16. // Some inlines to provide platform independence since we drop directly to API
  17. // calls to implement some of TPrintPreviewDC.
  18. //
  19. #if defined(BI_PLAT_WIN32)
  20.   inline bool SetWindowExt(HDC hdc, int w, int h) {return ::SetWindowExtEx(hdc, w, h, 0);}
  21.   inline bool SetWindowOrg(HDC hdc, int w, int h) {return ::SetWindowOrgEx(hdc, w, h, 0);}
  22.   inline bool SetViewportExt(HDC hdc, int w, int h) {return ::SetViewportExtEx(hdc, w, h, 0);}
  23.   inline bool SetViewportOrg(HDC hdc, int x, int y) {return ::SetViewportOrgEx(hdc, x, y, 0);}
  24. #endif
  25.  
  26. TPrintPreviewDC::TPrintPreviewDC(TDC&         screen,
  27.                                  TPrintDC&    printdc,
  28.                                  const TRect& client,
  29.                                  const TRect& clip)
  30. :
  31.   TPrintDC(screen),
  32.   PrnDC(printdc),
  33.   PrnFont(0),
  34.   CurrentPreviewFont(0)
  35. {
  36.   //
  37.   // Set the initial mode & extents for the screen dc
  38.   //
  39.   ::SetMapMode(GetHDC(), MM_ANISOTROPIC);
  40.   ::SetWindowExt(GetHDC(), client.Width(), client.Height());
  41.   ::SetViewportExt(GetHDC(), client.Width(), client.Height());
  42.  
  43.   //
  44.   // Static call to virtual method, but some mapping must be done now.
  45.   //
  46.   ReScale();
  47.  
  48.   //
  49.   // Assume clip rect is in device points - DPs are same in new viewport
  50.   //
  51.   SelectClipRgn(clip);
  52.   PrnFont = (HFONT)PrnDC.GetCurrentObject(OBJ_FONT);
  53.   SyncFont();
  54. }
  55.  
  56. TPrintPreviewDC::~TPrintPreviewDC()
  57. {
  58.   // cleanup screen dc
  59.   //
  60.   ::DeleteObject(::SelectObject(GetHDC(), ::GetStockObject(SYSTEM_FONT)));
  61.   delete CurrentPreviewFont;
  62. }
  63.  
  64. HDC
  65. TPrintPreviewDC::GetAttributeHDC() const
  66. {
  67.   return PrnDC;
  68. }
  69.  
  70. //
  71. // Intercept setting of the printer font, making & keeping a copy of it and
  72. // calling SyncFont if needed to recreate the preview font.
  73. //
  74. void
  75. TPrintPreviewDC::SelectObject(const TFont& newFont)
  76. {
  77.   if ((HFONT)newFont) {
  78.     LOGFONT   lf;
  79.     newFont.GetObject(lf);
  80.  
  81.     TFont*  oldPreviewF = CurrentPreviewFont;
  82.     CurrentPreviewFont = new TFont(&lf);
  83.  
  84.     PrnDC.SelectObject(*CurrentPreviewFont);
  85.     delete oldPreviewF;
  86.  
  87.     if ((HFONT)(*CurrentPreviewFont) != PrnFont) {
  88.       PrnFont = (HFONT)(*CurrentPreviewFont);
  89.       SyncFont();
  90.     }
  91.   }
  92. }
  93.  
  94. void
  95. TPrintPreviewDC::SelectStockObject(int index)
  96. {
  97.   PrnDC.SelectStockObject(index);
  98.   switch (index) {
  99.     case ANSI_FIXED_FONT:
  100.     case ANSI_VAR_FONT:
  101.     case DEVICE_DEFAULT_FONT:
  102.     case OEM_FIXED_FONT:
  103.     case SYSTEM_FONT:
  104.     case SYSTEM_FIXED_FONT: {
  105.       HFONT stockFont = (HFONT)GetStockObject(index);
  106.       if (stockFont != PrnFont) {
  107.         PrnFont = stockFont;
  108.         SyncFont();
  109.       }
  110.       break;
  111.     }
  112.     default:
  113.       TPrintDC::SelectStockObject(index);
  114.   }
  115. }
  116.  
  117. void
  118. TPrintPreviewDC::RestoreFont()
  119. {
  120.   PrnDC.RestoreFont();
  121.   PrnFont = (HFONT)PrnDC.GetCurrentObject(OBJ_FONT);
  122.   TPrintDC::RestoreFont();
  123.   SyncFont();
  124. }
  125.  
  126. int
  127. TPrintPreviewDC::GetDeviceCaps(int index) const
  128. {
  129.   switch (index) {
  130.     case CLIPCAPS:
  131.     case RASTERCAPS:
  132.     case CURVECAPS:
  133.     case LINECAPS:
  134.     case POLYGONALCAPS:
  135.     case TEXTCAPS:      // report capabilities supported on both devices
  136.       return PrnDC.GetDeviceCaps(index) & TPrintDC::GetDeviceCaps(index);
  137.  
  138.       // otherwise, report printer caps and let GDI sort out differences
  139.     default:
  140.       return PrnDC.GetDeviceCaps(index);
  141.   }
  142. }
  143.  
  144. inline int
  145. GlyphHeight(TEXTMETRIC& tm)
  146. {
  147.   return tm.tmHeight < 0
  148.             ? tm.tmHeight
  149.             : -(tm.tmHeight - tm.tmInternalLeading);
  150. }
  151.  
  152. //
  153. // SyncFont performs a simple font match attempt, with a retry option if
  154. // the GDI selected match is too different from the selected printer font.
  155. // In print preview, matching the size of the characters is more important
  156. // than matching their appearance.  In most cases, the print preview will
  157. // barely be legible anyway.  Size is most important because you don't
  158. // want character size differences to change the line breaks or page
  159. // breaks of the on-screen document from what they would be on the
  160. // printed page.  This effect is minimized in this TPrintPreviewDC object,
  161. // since info reports such as GetTextMetrics and GetTextExtent are always
  162. // reported from the printer dc using the real font.  Internal calculations
  163. // should be the same for preview as for printing, but the output accuracy
  164. // will depend upon the accuracy of font selection.
  165. //
  166. // It is also possible to take over control of the text output functions
  167. // through this DC object - the TextOut and other text methods are virtual.
  168. // You can place each character on the preview screen yourself, if you
  169. // desire more precision in character placement than GDI's font matching
  170. // can provide.  That's a lot of work, and a lot of code, and isn't
  171. // necessary to meet the needs of most applications.
  172. //
  173. // SyncFont is virtual so that you may substitute your own font matching
  174. // algorythm with more font matching heuristics.
  175. //
  176. void
  177. TPrintPreviewDC::SyncFont()
  178. {
  179.   //
  180.   // set screen font to match current printer font.
  181.   //
  182.   LOGFONT lf;
  183.   ::GetObject(PrnFont, sizeof(lf), &lf);
  184.  
  185.   TEXTMETRIC tm;
  186.   PrnDC.GetTextMetrics(tm);
  187.  
  188.   lf.lfHeight         = GlyphHeight(tm);
  189.   lf.lfWidth          = tm.tmAveCharWidth;
  190.   lf.lfWeight         = tm.tmWeight;
  191.   lf.lfItalic         = tm.tmItalic;
  192.   lf.lfUnderline      = tm.tmUnderlined;
  193.   lf.lfStrikeOut      = tm.tmStruckOut;
  194.   lf.lfCharSet        = tm.tmCharSet;
  195.   lf.lfOutPrecision   = OUT_TT_PRECIS;
  196.   lf.lfClipPrecision  = CLIP_DEFAULT_PRECIS;
  197.   lf.lfQuality        = DRAFT_QUALITY;
  198.   
  199.   // Keep just the pitch (low 2 bits). Ignore the family
  200.   //
  201.   lf.lfPitchAndFamily = uint8((tm.tmPitchAndFamily & 0x0003) | FF_DONTCARE);
  202.   PrnDC.GetTextFace(sizeof(lf.lfFaceName), lf.lfFaceName);
  203.  
  204.   ::DeleteObject(::SelectObject(GetHDC(), ::CreateFontIndirect(&lf)));
  205.  
  206.   //
  207.   // if height isn't right, relax the font pitch and facename requirements
  208.   //
  209.   GetTextMetrics(tm);
  210.   if (abs(abs(lf.lfHeight) - abs(GlyphHeight(tm))) > 2) {
  211.     if (lf.lfPitchAndFamily & FF_DECORATIVE)
  212.       lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DECORATIVE;
  213.     else
  214.       lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  215.     lf.lfFaceName[0] = 0;
  216.     ::DeleteObject(::SelectObject(GetHDC(), CreateFontIndirect(&lf)));
  217.   }
  218. }
  219.  
  220. //
  221. // Rescale the preview DC by adjusting its window & viewport
  222. //
  223. // Assume the viewport extent (scrve) is set to the size of the window
  224. // client area.  All we have to do to map the addressable points of the
  225. // printer DC into the screen DC, then, is set the screen window extent
  226. // equal to the maximum addressable logical point of the printer dc.
  227. // PrnDC.DPtoLP will pull the device point through the printer's mapping
  228. // mode conversions, giving us the maximum point we should allow on the
  229. // screen dc.
  230. //
  231. void
  232. TPrintPreviewDC::ReScale()
  233. {
  234.   TSize scrve;
  235.   ::GetViewportExtEx(GetHDC(), &scrve);
  236.  
  237.   TPoint scrwe(PrnDC.GetDeviceCaps(HORZRES), PrnDC.GetDeviceCaps(VERTRES));
  238.   PrnDC.DPtoLP(&scrwe);
  239.  
  240.   ::SetMapMode(GetHDC(), MM_ANISOTROPIC);
  241.   ::SetWindowExt(GetHDC(), scrwe.x, scrwe.y);
  242.   ::SetViewportExt(GetHDC(), scrve.cx, scrve.cy);
  243.   ReOrg();
  244. }
  245.  
  246. //
  247. // Reset the DC's origin
  248. //
  249. void
  250. TPrintPreviewDC::ReOrg()
  251. {
  252.   TPoint origin = PrnDC.GetViewportOrg();
  253.   PrnDC.DPtoLP(&origin);
  254.   LPtoSDP(&origin);
  255.   ::SetViewportOrg(GetHDC(), origin.x, origin.y);
  256.  
  257.   PrnDC.GetWindowOrg(origin);
  258.   ::SetWindowOrg(GetHDC(), origin.x, origin.y);
  259. }
  260.  
  261. TColor
  262. TPrintPreviewDC::SetBkColor(TColor color)
  263. {
  264.   TColor result = PrnDC.SetBkColor(color);
  265.   ::SetBkColor(GetHDC(), PrnDC.GetBkColor());
  266.   return result;
  267. }
  268.  
  269. TColor
  270. TPrintPreviewDC::SetTextColor(TColor color)
  271. {
  272.   TColor result = PrnDC.SetTextColor(color);
  273.   ::SetTextColor(GetHDC(), PrnDC.GetTextColor());
  274.   return result;
  275. }
  276.  
  277. int
  278. TPrintPreviewDC::SetMapMode(int mode)
  279. {
  280.   int result = PrnDC.SetMapMode(mode);
  281.   ReScale();
  282.   return result;
  283. }
  284.  
  285. bool
  286. TPrintPreviewDC::SetViewportOrg(const TPoint& origin, TPoint far* oldOrg)
  287. {
  288.   bool result = PrnDC.SetViewportOrg(origin, oldOrg);
  289.   ReOrg();
  290.   return result;
  291. }
  292.  
  293. bool
  294. TPrintPreviewDC::OffsetViewportOrg(const TPoint& delta, TPoint far* oldOrg)
  295. {
  296.   bool result = PrnDC.OffsetViewportOrg(delta, oldOrg);
  297.   ReOrg();
  298.   return result;
  299. }
  300.  
  301. bool
  302. TPrintPreviewDC::SetViewportExt(const TSize& extent, TSize far* oldExtent)
  303. {
  304.   bool result = PrnDC.SetViewportExt(extent, oldExtent);
  305.   ReScale();
  306.   return result;
  307. }
  308.  
  309. bool
  310. TPrintPreviewDC::ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom,
  311.                                   TSize far* oldExtent)
  312. {
  313.   bool result = PrnDC.ScaleViewportExt( xNum, xDenom, yNum, yDenom, oldExtent);
  314.   ReScale();
  315.   return result;
  316. }
  317.  
  318. bool
  319. TPrintPreviewDC::SetWindowExt(const TSize& extent, TSize far* oldExtent)
  320. {
  321.   bool result = PrnDC.SetWindowExt(extent, oldExtent);
  322.   ReScale();
  323.   return result;
  324. }
  325.  
  326. bool
  327. TPrintPreviewDC::ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom,
  328.                                 TSize far* oldExtent)
  329. {
  330.   bool result = PrnDC.ScaleWindowExt(xNum, xDenom, yNum, yDenom, oldExtent);
  331.   ReScale();
  332.   return result;
  333. }
  334.  
  335.  
  336. DEFINE_RESPONSE_TABLE1(TPreviewPage, TWindow)
  337.   EV_WM_SIZE,
  338. END_RESPONSE_TABLE;
  339.  
  340. IMPLEMENT_CASTABLE(TPreviewPage);
  341.  
  342. TPreviewPage::TPreviewPage(TWindow* parent, TPrintout& printout,
  343.                            TPrintDC& prndc, TSize& printExtent, int pagenum)
  344.       : TWindow(parent),
  345.         Printout(printout),
  346.         PrintDC(prndc),
  347.         PrintExtent(printExtent),
  348.         PageNum(pagenum)
  349. {
  350.   Attr.Style = WS_CHILD | WS_BORDER | WS_VISIBLE;
  351.   SetBkgndColor(TColor::White);
  352. }
  353.  
  354. //
  355. // Using a TPrintPreviewDC, 'print' the current page (PageNum) of Printout
  356. // onto the window DC provided, 
  357. //
  358. void
  359. TPreviewPage::Paint(TDC& dc, bool, TRect& clip)
  360. {
  361.   TPrintPreviewDC pdc(dc, PrintDC, GetClientRect(), clip);
  362.   Printout.SetPrintParams(&pdc, PrintExtent);
  363.  
  364.   if (Printout.HasPage(PageNum)) {
  365.     Printout.BeginPrinting();
  366.     Printout.BeginDocument(PageNum, PageNum, pfBoth);
  367.  
  368.     // Change clip rect into the shared logical coordinate space, & print
  369.     //
  370.     pdc.SDPtoLP(clip);
  371.     Printout.PrintPage(PageNum, clip, pfBoth);
  372.  
  373.     Printout.EndDocument();
  374.     Printout.EndPrinting();
  375.   }
  376.   else 
  377.     dc.PatBlt(0, 0, Attr.W, Attr.H, WHITENESS);
  378. }
  379.  
  380. //
  381. // Always repaint whole window if size is changed
  382. //
  383. void
  384. TPreviewPage::EvSize(uint sizeType, TSize& size)
  385. {
  386.   Invalidate();
  387.   TWindow::EvSize(sizeType, size);
  388. }
  389.