home *** CD-ROM | disk | FTP | other *** search
- //----------------------------------------------------------------------------
- // ObjectWindows - (C) Copyright 1992, 1993 by Borland International
- // include\owl\preview.h
- // Definition of print preview classes
- //----------------------------------------------------------------------------
- #include <owl\owlpch.h>
- #include <owl\preview.h>
- #include <owl\printer.h>
- #include <owl\gdiobjec.h>
- #include <owl\dc.h>
- #include <owl\printdia.h>
- #include <math.h>
-
- //
- // Some inlines to provide platform independence since we drop directly to API
- // calls to implement some of TPrintPreviewDC.
- //
- #if defined(__WIN32__)
- inline BOOL SetWindowExt(HDC hdc, int w, int h) {return ::SetWindowExtEx(hdc, w, h, 0);}
- inline BOOL SetViewportExt(HDC hdc, int w, int h) {return ::SetViewportExtEx(hdc, w, h, 0);}
- inline BOOL SetViewportOrg(HDC hdc, int x, int y) {return ::SetViewportOrgEx(hdc, x, y, 0);}
- #endif
-
- TPrintPreviewDC::TPrintPreviewDC(TDC& screen,
- TPrintDC& printdc,
- const TRect& client,
- const TRect& clip)
- : TPrintDC(screen),
- PrnDC(printdc),
- PrnFont(0),
- CurrentPreviewFont(0)
- {
- //
- // Set the initial mode & extents for the screen dc
- //
- ::SetMapMode(GetHDC(), MM_ANISOTROPIC);
- ::SetWindowExt(GetHDC(), client.Width(), client.Height());
- ::SetViewportExt(GetHDC(), client.Width(), client.Height());
-
- //
- // Static call to virtual method, but some mapping must be done now.
- //
- ReScale();
-
- //
- // Assume clip rect is in device points - DPs are same in new viewport
- //
- SelectClipRgn(clip);
- PrnFont = (HFONT)PrnDC.GetCurrentObject(OBJ_FONT);
- SyncFont();
- }
-
- TPrintPreviewDC::~TPrintPreviewDC()
- {
- // cleanup screen dc
- //
- ::DeleteObject(::SelectObject(GetHDC(), ::GetStockObject(SYSTEM_FONT)));
- delete CurrentPreviewFont;
- }
-
- HDC
- TPrintPreviewDC::GetAttributeHDC() const
- {
- return PrnDC;
- }
-
- //
- // Intercept setting of the printer font, making & keeping a copy of it and
- // calling SyncFont if needed to recreate the preview font.
- //
- void
- TPrintPreviewDC::SelectObject(const TFont& newFont)
- {
- if ((HFONT)newFont) {
- LOGFONT lf;
- newFont.GetObject(lf);
-
- TFont* oldPreviewF = CurrentPreviewFont;
- CurrentPreviewFont = new TFont(&lf);
-
- PrnDC.SelectObject(*CurrentPreviewFont);
- delete oldPreviewF;
-
- if ((HFONT)(*CurrentPreviewFont) != PrnFont) {
- PrnFont = (HFONT)(*CurrentPreviewFont);
- SyncFont();
- }
- }
- }
-
- void
- TPrintPreviewDC::SelectStockObject(int index)
- {
- PrnDC.SelectStockObject(index);
- switch (index) {
- case ANSI_FIXED_FONT:
- case ANSI_VAR_FONT:
- case DEVICE_DEFAULT_FONT:
- case OEM_FIXED_FONT:
- case SYSTEM_FONT:
- case SYSTEM_FIXED_FONT: {
- HFONT stockFont = (HFONT)GetStockObject(index);
- if (stockFont != PrnFont) {
- PrnFont = stockFont;
- SyncFont();
- }
- break;
- }
- default:
- TPrintDC::SelectStockObject(index);
- }
- }
-
- void
- TPrintPreviewDC::RestoreFont()
- {
- PrnDC.RestoreFont();
- PrnFont = (HFONT)PrnDC.GetCurrentObject(OBJ_FONT);
- TPrintDC::RestoreFont();
- SyncFont();
- }
-
- int
- TPrintPreviewDC::GetDeviceCaps(int index) const
- {
- switch (index) {
- case CLIPCAPS:
- case RASTERCAPS:
- case CURVECAPS:
- case LINECAPS:
- case POLYGONALCAPS:
- case TEXTCAPS: // report capabilities supported on both devices
- return PrnDC.GetDeviceCaps(index) & TPrintDC::GetDeviceCaps(index);
-
- // otherwise, report printer caps and let GDI sort out differences
- default:
- return PrnDC.GetDeviceCaps(index);
- }
- }
-
- inline int
- GlyphHeight(TEXTMETRIC& tm)
- {
- return tm.tmHeight < 0
- ? tm.tmHeight
- : -(tm.tmHeight - tm.tmInternalLeading);
- }
-
- //
- // SyncFont performs a simple font match attempt, with a retry option if
- // the GDI selected match is too different from the selected printer font.
- // In print preview, matching the size of the characters is more important
- // than matching their appearance. In most cases, the print preview will
- // barely be legible anyway. Size is most important because you don't
- // want character size differences to change the line breaks or page
- // breaks of the on-screen document from what they would be on the
- // printed page. This effect is minimized in this TPrintPreviewDC object,
- // since info reports such as GetTextMetrics and GetTextExtent are always
- // reported from the printer dc using the real font. Internal calculations
- // should be the same for preview as for printing, but the output accuracy
- // will depend upon the accuracy of font selection.
- //
- // It is also possible to take over control of the text output functions
- // through this DC object - the TextOut and other text methods are virtual.
- // You can place each character on the preview screen yourself, if you
- // desire more precision in character placement than GDI's font matching
- // can provide. That's a lot of work, and a lot of code, and isn't
- // necessary to meet the needs of most applications.
- //
- // SyncFont is virtual so that you may substitute your own font matching
- // algorythm with more font matching heuristics.
- //
- void
- TPrintPreviewDC::SyncFont()
- {
- //
- // set screen font to match current printer font.
- //
- LOGFONT lf;
- ::GetObject(PrnFont, sizeof(lf), &lf);
-
- TEXTMETRIC tm;
- PrnDC.GetTextMetrics(tm);
-
- lf.lfHeight = GlyphHeight(tm);
- lf.lfWidth = tm.tmAveCharWidth;
- lf.lfWeight = tm.tmWeight;
- lf.lfItalic = tm.tmItalic;
- lf.lfUnderline = tm.tmUnderlined;
- lf.lfStrikeOut = tm.tmStruckOut;
- lf.lfCharSet = tm.tmCharSet;
- lf.lfOutPrecision = OUT_TT_PRECIS;
- lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lf.lfQuality = DRAFT_QUALITY;
-
- // Keep just the pitch (low 2 bits). Ignore the family
- //
- lf.lfPitchAndFamily = BYTE((tm.tmPitchAndFamily & 0x0003) | FF_DONTCARE);
- PrnDC.GetTextFace(sizeof(lf.lfFaceName), lf.lfFaceName);
-
- ::DeleteObject(::SelectObject(GetHDC(), ::CreateFontIndirect(&lf)));
-
- //
- // if height isn't right, relax the font pitch and facename requirements
- //
- GetTextMetrics(tm);
- if (abs(abs(lf.lfHeight) - abs(GlyphHeight(tm))) > 2) {
- if (lf.lfPitchAndFamily & FF_DECORATIVE)
- lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DECORATIVE;
- else
- lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
- lf.lfFaceName[0] = 0;
- ::DeleteObject(::SelectObject(GetHDC(), CreateFontIndirect(&lf)));
- }
- }
-
- //
- // Rescale the preview DC by adjusting its window & viewport
- //
- // Assume the viewport extent (scrve) is set to the size of the window
- // client area. All we have to do to map the addressable points of the
- // printer DC into the screen DC, then, is set the screen window extent
- // equal to the maximum addressable logical point of the printer dc.
- // PrnDC.DPtoLP will pull the device point through the printer's mapping
- // mode conversions, giving us the maximum point we should allow on the
- // screen dc.
- //
- void
- TPrintPreviewDC::ReScale()
- {
- TSize scrve;
- ::GetViewportExtEx(GetHDC(), &scrve);
-
- TPoint scrwe(PrnDC.GetDeviceCaps(HORZRES), PrnDC.GetDeviceCaps(VERTRES));
- PrnDC.DPtoLP(&scrwe);
-
- ::SetMapMode(GetHDC(), MM_ANISOTROPIC);
- ::SetWindowExt(GetHDC(), scrwe.x, scrwe.y);
- ::SetViewportExt(GetHDC(), scrve.cx, scrve.cy);
- ReOrg();
- }
-
- //
- // Reset the DC's origin
- //
- void
- TPrintPreviewDC::ReOrg()
- {
- TPoint origin = PrnDC.GetViewportOrg();
- PrnDC.DPtoLP(&origin);
- LPtoSDP(&origin);
- ::SetViewportOrg(GetHDC(), origin.x, origin.y);
-
- PrnDC.GetWindowOrg(origin);
- ::SetViewportOrg(GetHDC(), origin.x, origin.y);
- }
-
- TColor
- TPrintPreviewDC::SetBkColor(TColor color)
- {
- TColor result = PrnDC.SetBkColor(color);
- ::SetBkColor(GetHDC(), PrnDC.GetBkColor());
- return result;
- }
-
- TColor
- TPrintPreviewDC::SetTextColor(TColor color)
- {
- TColor result = PrnDC.SetTextColor(color);
- ::SetTextColor(GetHDC(), PrnDC.GetTextColor());
- return result;
- }
-
- int
- TPrintPreviewDC::SetMapMode(int mode)
- {
- int result = PrnDC.SetMapMode(mode);
- ReScale();
- return result;
- }
-
- BOOL
- TPrintPreviewDC::SetViewportOrg(const TPoint& origin, TPoint far* oldOrg)
- {
- BOOL result = PrnDC.SetViewportOrg(origin, oldOrg);
- ReOrg();
- return result;
- }
-
- BOOL
- TPrintPreviewDC::OffsetViewportOrg(const TPoint& delta, TPoint far* oldOrg)
- {
- BOOL result = PrnDC.OffsetViewportOrg(delta, oldOrg);
- ReOrg();
- return result;
- }
-
- BOOL
- TPrintPreviewDC::SetViewportExt(const TSize& extent, TSize far* oldExtent)
- {
- BOOL result = PrnDC.SetViewportExt(extent, oldExtent);
- ReScale();
- return result;
- }
-
- BOOL
- TPrintPreviewDC::ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom,
- TSize far* oldExtent)
- {
- BOOL result = PrnDC.ScaleViewportExt( xNum, xDenom, yNum, yDenom, oldExtent);
- ReScale();
- return result;
- }
-
- BOOL
- TPrintPreviewDC::SetWindowExt(const TSize& extent, TSize far* oldExtent)
- {
- BOOL result = PrnDC.SetWindowExt(extent, oldExtent);
- ReScale();
- return result;
- }
-
- BOOL
- TPrintPreviewDC::ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom,
- TSize far* oldExtent)
- {
- BOOL result = PrnDC.ScaleWindowExt(xNum, xDenom, yNum, yDenom, oldExtent);
- ReScale();
- return result;
- }
-
-
- DEFINE_RESPONSE_TABLE1(TPreviewPage, TWindow)
- EV_WM_SIZE,
- END_RESPONSE_TABLE;
-
- IMPLEMENT_CASTABLE(TPreviewPage);
-
- TPreviewPage::TPreviewPage(TWindow* parent, TPrintout& printout,
- TPrintDC& prndc, TSize& printExtent, int pagenum)
- : TWindow(parent),
- Printout(printout),
- PrintDC(prndc),
- PrintExtent(printExtent),
- PageNum(pagenum)
- {
- Attr.Style = WS_CHILD | WS_BORDER | WS_VISIBLE;
- SetBkgndColor(TColor::White);
- }
-
- //
- // Using a TPrintPreviewDC, 'print' the current page (PageNum) of Printout
- // onto the window DC provided,
- //
- void
- TPreviewPage::Paint(TDC& dc, BOOL, TRect& clip)
- {
- TPrintPreviewDC pdc(dc, PrintDC, GetClientRect(), clip);
- Printout.SetPrintParams(&pdc, PrintExtent);
-
- if (Printout.HasPage(PageNum)) {
- Printout.BeginPrinting();
- Printout.BeginDocument(PageNum, PageNum, pfBoth);
-
- // Change clip rect into the shared logical coordinate space, & print
- //
- pdc.SDPtoLP(clip);
- Printout.PrintPage(PageNum, clip, pfBoth);
-
- Printout.EndDocument();
- Printout.EndPrinting();
- } else
- dc.PatBlt(0, 0, Attr.W, Attr.H, WHITENESS);
- }
-
- //
- // Always repaint whole window if size is changed
- //
- void
- TPreviewPage::EvSize(UINT sizeType, TSize& size)
- {
- Invalidate();
- TWindow::EvSize(sizeType, size);
- }
-