home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / PREVIEW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  10.7 KB  |  385 lines

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