📄 renderpages.cpp
字号:
/* * * renderpages.cpp * Copyright (C) 2006 Michael H. Overlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact at poster_printer@yahoo.com * */#include "renderpages.h"#include "gdiutils.h"#include "mathutils.h"#include "spoolutils.h"#include "utils.h"#include <windows.h>#include <strsafe.h>#define MAX_CUTGUIDE_CCH 256#define CUTGUIDE_LINE_SPACE_INCHES (1.0/128)#define FUDGE_MOSAICFROMZOOM 1.0E-12void RenderMosaicPage_Internal( OUT HDC hdc, IN const RECT* prlDest, IN const POINT& ptPage, IN const RenderSpec& rs, IN const PageSpec& ps, IN HENHMETAFILE hMeta, IN const SourceSpec &ss, OUT RECTD *prdRenderedImageBounds_Inches ) ;void DrawCutGuide(OUT HDC hdc, IN const RECTD& in_rdCutGuide_Inches, IN const POINTD& in_ptdLogPix, IN BOOL bVertical, IN const POINT& ptPage, IN double dCutGuide_Inches) ;void OffsetViewportOrg(OUT HDC hdc, IN const POINT& pt) { OffsetViewportOrgEx(hdc, pt.x, pt.y, NULL);}void OffsetWindowOrg(OUT HDC hdc, IN const POINT& pt) { OffsetWindowOrgEx(hdc, pt.x, pt.y, NULL);}void SetViewportOrg(OUT HDC hdc, IN const POINT& pt) { SetViewportOrgEx(hdc, pt.x, pt.y, NULL);}void SetWindowOrg(OUT HDC hdc, IN const POINT& pt) { SetWindowOrgEx(hdc, pt.x, pt.y, NULL);}void SetViewportExt(OUT HDC hdc, IN const SIZEL& szl) { SetViewportExtEx(hdc, szl.cx, szl.cy, NULL);}void SetWindowExt(OUT HDC hdc, IN const SIZEL& szl) { SetWindowExtEx(hdc, szl.cx, szl.cy, NULL);}// 6/1void RenderMosaicPage( OUT HDC hdc, IN const RECT& rlDest, IN const POINT& ptPage, IN const RenderSpec& rs, IN const PageSpec& ps, IN HENHMETAFILE hMeta, IN const SourceSpec &ss ) { RenderMosaicPage_Internal(hdc, &rlDest, ptPage, rs, ps, hMeta, ss, NULL);}void RenderMosaicPage_Internal( OUT HDC hdc, IN const RECT* prlDest, IN const POINT& ptPage, IN const RenderSpec& rs, IN const PageSpec& ps, IN HENHMETAFILE hMeta, IN const SourceSpec &ss, OUT RECTD *prdRenderedImageBounds_Inches ) { // IS ALL PHYSICAL PAGE HEIGHT AVAILABLE FOR PRINTING? // THIS TYPICALLY MEANS PAGE IS TRACTOR-FEAD BOOL bAllHeight = (ps.szlPhysicalPage.cy == ps.szlPrintable.cy); // IS ALL PHYSICAL PAGE WIDTH AVAILABLE FOR PRINTING? BOOL bAllWidth = (ps.szlPhysicalPage.cx == ps.szlPrintable.cx); // PIXELS PER INCH "LOGPIXELS" POINTD ptdPageLogPixels = { ps.szlPhysicalPage.cx / ps.szdPhysicalPage_Inches.cx, ps.szlPhysicalPage.cy / ps.szdPhysicalPage_Inches.cy }; // TOTAL SIZE OF MOSAIC OF PAGES SIZED szdPhysicalMosaic_Inches = { ps.szdPhysicalPage_Inches.cx * rs.szMosaic.cx, ps.szdPhysicalPage_Inches.cy * rs.szMosaic.cy }; // OFFSET INTO PHYSICAL PAGE OF PRINTABLE AREA, IN INCHES POINTD ptdOffsetPrintable_Inches = { ps.ptlOffsetPrintable.x / ptdPageLogPixels.x, ps.ptlOffsetPrintable.y / ptdPageLogPixels.y }; // PAGE PRINTABLE SIZE IN INCHES SIZED szdPrintablePage_Inches = { ps.szlPrintable.cx / ptdPageLogPixels.x, ps.szlPrintable.cy / ptdPageLogPixels.y }; // TOTAL PRINTABLE MOSAIC SIZE IN INCHES SIZED szdPrintableMosaic_Inches = { szdPrintablePage_Inches.cx * rs.szMosaic.cx, szdPrintablePage_Inches.cy * rs.szMosaic.cy }; // OFFSET OF IMAGE SELECTION WITHIN TOTAL IMAGE POINTD ptdImageSelectionOffsetIntoTotal_Inches = { ss.rdSelection_Inches.left - ss.rdTotalImage_Inches.left, ss.rdSelection_Inches.top - ss.rdTotalImage_Inches.top }; // TOTAL FREE PRINTABLE MOSAIC SIZE IN INCHES -- SPACE AVAILABLE FOR THE IMAGE ITSELF // APART FROM OVERLAPPING MARGINS, CUTTING GUIDES, AND EDGE MARGINS SIZED szdMargins_Inches; szdMargins_Inches.cy = ps.ms.rdEdgeMargins_Inches.top + ps.ms.rdEdgeMargins_Inches.bottom - (ps.szdPhysicalPage_Inches.cy - szdPrintablePage_Inches.cy); if (!bAllHeight) { szdMargins_Inches.cy += (rs.szMosaic.cy - 1) * (ps.ms.dOverlapMargin_Inches + (rs.bCutGuides ? ps.ms.dCutGuideMargin_Inches : 0)); } szdMargins_Inches.cx = ps.ms.rdEdgeMargins_Inches.left + ps.ms.rdEdgeMargins_Inches.right - (ps.szdPhysicalPage_Inches.cx - szdPrintablePage_Inches.cx); if (!bAllWidth) { szdMargins_Inches.cx += (rs.szMosaic.cx - 1) * (ps.ms.dOverlapMargin_Inches + (rs.bCutGuides ? ps.ms.dCutGuideMargin_Inches : 0)); } SIZED szdFreePrintableMosaic_Inches = { szdPrintableMosaic_Inches.cx - szdMargins_Inches.cx, szdPrintableMosaic_Inches.cy - szdMargins_Inches.cy }; // IMAGE SELECTION SIZE IN INCHES SIZED szdImageSelection_Inches = { RW(ss.rdSelection_Inches), RH(ss.rdSelection_Inches) }; // ZOOMED SELECTED IMAGE TOTAL SIZE IN INCHES double dZoom; if (rs.mode == RenderSpec::eZoom) { //dZoom = rs.wZoom / 100.0; dZoom = rs.dZoom; } else { if (szdImageSelection_Inches.cx * szdFreePrintableMosaic_Inches.cy < szdImageSelection_Inches.cy * szdFreePrintableMosaic_Inches.cx) { dZoom = szdFreePrintableMosaic_Inches.cy / szdImageSelection_Inches.cy; } else { dZoom = szdFreePrintableMosaic_Inches.cx / szdImageSelection_Inches.cx; } } SIZED szdZoomedImageSelection_Inches = { szdImageSelection_Inches.cx * dZoom, szdImageSelection_Inches.cy * dZoom }; SIZED szdTotalImage_Inches = { RW(ss.rdTotalImage_Inches), RH(ss.rdTotalImage_Inches) }; SIZED szdZoomedTotalImage_Inches = { szdTotalImage_Inches.cx * dZoom, szdTotalImage_Inches.cy * dZoom }; // 5/29 ADD A "bCenter" FLAG TO RenderSpec (WAS DEFAULT) POINTD ptdZoomedImageSelectionOffsetIntoFreePrintableMosaic_Inches = { (rs.bCenter ? ( szdFreePrintableMosaic_Inches.cx - szdZoomedImageSelection_Inches.cx ) / 2.0 : 0.0), (rs.bCenter ? ( szdFreePrintableMosaic_Inches.cy - szdZoomedImageSelection_Inches.cy ) / 2.0 : 0.0) }; RECTD rdZoomedImageSelectionIntoFreePrintableMosaic_Inches = { ptdZoomedImageSelectionOffsetIntoFreePrintableMosaic_Inches.x, ptdZoomedImageSelectionOffsetIntoFreePrintableMosaic_Inches.y, ptdZoomedImageSelectionOffsetIntoFreePrintableMosaic_Inches.x + szdZoomedImageSelection_Inches.cx, ptdZoomedImageSelectionOffsetIntoFreePrintableMosaic_Inches.y + szdZoomedImageSelection_Inches.cy }; POINTD ptdZoomedTotalImageOffsetIntoFreePrintableMosaic_Inches = { ptdZoomedImageSelectionOffsetIntoFreePrintableMosaic_Inches.x - ptdImageSelectionOffsetIntoTotal_Inches.x * dZoom, ptdZoomedImageSelectionOffsetIntoFreePrintableMosaic_Inches.y - ptdImageSelectionOffsetIntoTotal_Inches.y * dZoom }; RECTD rdZoomedTotalImageIntoFreePrintableMosaic_Inches = { ptdZoomedTotalImageOffsetIntoFreePrintableMosaic_Inches.x, ptdZoomedTotalImageOffsetIntoFreePrintableMosaic_Inches.y, ptdZoomedTotalImageOffsetIntoFreePrintableMosaic_Inches.x + szdZoomedTotalImage_Inches.cx, ptdZoomedTotalImageOffsetIntoFreePrintableMosaic_Inches.y + szdZoomedTotalImage_Inches.cy }; // START WITH ENTIRE PRINTABLE RECT -- AS USUAL RELATIVE TO UPPER-LEFT CORNER OR PRINTABLE AREA ITSELF // LATER ALL WILL BE TRANSLATED TO ITS LOCATION IN TOTAL PRINTABLE SPACE // WE ONLY NEED TO CLIP OUT THE CUT GUIDES IF ANY, BECAUSE THE MARGINS ARE TAKEN CARE OF BY CLIPPING // THE SELECTED IMAGE AREA RECTD rdCutoutClipThisPage_Inches = { 0, 0, szdPrintablePage_Inches.cx, szdPrintablePage_Inches.cy }; // JUST AT THE TOP AND TO THE LEFT OF PAGES THAT DON'T LIE AT THE // MOSAIC TOP, LEFT BORDERS (THAT'S ALL YOU NEED TO CUT) // *FIXED* DEBUG - FIX -- SEEM TO HAVE FORGOTTEN bAllWidth, bAllHeight if (rs.bCutGuides) { if (ptPage.y != 0 && !bAllHeight) { rdCutoutClipThisPage_Inches.top += ps.ms.dCutGuideMargin_Inches; } if (ptPage.x != 0 && !bAllWidth) { rdCutoutClipThisPage_Inches.left += ps.ms.dCutGuideMargin_Inches; } } POINTD ptdOffsetIntoFreePrintableMosaicThisPage_Inches = { szdPrintablePage_Inches.cx * ptPage.x, szdPrintablePage_Inches.cy * ptPage.y }; ptdOffsetIntoFreePrintableMosaicThisPage_Inches.x -= ps.ms.rdEdgeMargins_Inches.left - ptdOffsetPrintable_Inches.x; ptdOffsetIntoFreePrintableMosaicThisPage_Inches.y -= ps.ms.rdEdgeMargins_Inches.top - ptdOffsetPrintable_Inches.y; if (!bAllHeight) { ptdOffsetIntoFreePrintableMosaicThisPage_Inches.y -= ptPage.y * (ps.ms.dOverlapMargin_Inches + (rs.bCutGuides ? ps.ms.dCutGuideMargin_Inches : 0)); } if (!bAllWidth) { ptdOffsetIntoFreePrintableMosaicThisPage_Inches.x -= ptPage.x * (ps.ms.dOverlapMargin_Inches + (rs.bCutGuides ? ps.ms.dCutGuideMargin_Inches : 0)); } if (prdRenderedImageBounds_Inches != NULL) { RECTD rdTemp1; ::SetRect(rdTemp1, ptdOffsetIntoFreePrintableMosaicThisPage_Inches, szdPrintablePage_Inches); RECTD rdTemp2; ::IntersectRect(rdTemp2, rdTemp1, rdZoomedImageSelectionIntoFreePrintableMosaic_Inches); ::OffsetRect(rdTemp2, - ptdOffsetIntoFreePrintableMosaicThisPage_Inches.x, - ptdOffsetIntoFreePrintableMosaicThisPage_Inches.y); ::IntersectRect(*prdRenderedImageBounds_Inches, rdTemp2, rdCutoutClipThisPage_Inches); } if (hdc != NULL) { int nSaveDC = ::SaveDC(hdc); RECT rlZoomedImageSelectionIntoFreePrintableMosaic; RoundMult(rlZoomedImageSelectionIntoFreePrintableMosaic, rdZoomedImageSelectionIntoFreePrintableMosaic_Inches, ptdPageLogPixels); RECT rlZoomedTotalImageIntoFreePrintableMosaic; RoundMult(rlZoomedTotalImageIntoFreePrintableMosaic, rdZoomedTotalImageIntoFreePrintableMosaic_Inches, ptdPageLogPixels); RECT rlCutoutClipThisPage; RoundMult(rlCutoutClipThisPage, rdCutoutClipThisPage_Inches, ptdPageLogPixels); // NOW WE WANT THIS PAGES PRINTABLE COORDS TO BE DISPLACED // TO LIE AT IT'S MOSAIC POSITION, AND TO CLIP THE CUTTING GUIDES // AND TO CLIP THE OVERALL ZOOMED IMAGE SELECTION SetMapMode(hdc, MM_ANISOTROPIC); SetViewport(hdc, *prlDest); SetWindowExt(hdc, ps.szlPrintable); SetWindowOrgEx(hdc, 0, 0, NULL); // 5/31 DRAW THE CUTTING GUIDES IF ANY // *FIXED* DEBUG - FIX -- SEEM TO HAVE FORGOTTEN bAllWidth, bAllHeight if (rs.bCutGuides && ptPage.x != 0 && !bAllWidth) { RECTD rdCutGuide_Inches = { 0, 0, ps.ms.dCutGuideMargin_Inches, szdPrintablePage_Inches.cy }; ::DrawCutGuide(hdc, rdCutGuide_Inches, ptdPageLogPixels, TRUE, ptPage, ps.ms.dCutGuideMargin_Inches); } if (rs.bCutGuides && ptPage.y != 0 && !bAllHeight) { RECTD rdCutGuide_Inches = { 0, 0, szdPrintablePage_Inches.cx, ps.ms.dCutGuideMargin_Inches, }; ::DrawCutGuide(hdc, rdCutGuide_Inches, ptdPageLogPixels, FALSE, ptPage, ps.ms.dCutGuideMargin_Inches); } IntersectClipRect(hdc, rlCutoutClipThisPage); POINT ptlOffsetIntoFreePrintableMosaicThisPage; RoundMult(ptlOffsetIntoFreePrintableMosaicThisPage, ptdOffsetIntoFreePrintableMosaicThisPage_Inches, ptdPageLogPixels); OffsetWindowOrg(hdc, ptlOffsetIntoFreePrintableMosaicThisPage); IntersectClipRect(hdc, rlZoomedImageSelectionIntoFreePrintableMosaic); // 7/9 ::SetStretchBltMode(hdc, COLORONCOLOR); PlayEnhMetaFile(hdc, hMeta, &rlZoomedTotalImageIntoFreePrintableMosaic); ::RestoreDC(hdc, nSaveDC); }}void CalculateMosaicSizeFromZoom( OUT SIZE& szMosaic, IN double dZoom, IN const RenderSpec& rs, IN const PageSpec& ps, IN const SourceSpec &ss) { // IS ALL PHYSICAL PAGE HEIGHT AVAILABLE FOR PRINTING? // THIS TYPICALLY MEANS PAGE IS TRACTOR-FEAD BOOL bAllHeight = (ps.szlPhysicalPage.cy == ps.szlPrintable.cy); // IS ALL PHYSICAL PAGE WIDTH AVAILABLE FOR PRINTING? BOOL bAllWidth = (ps.szlPhysicalPage.cx == ps.szlPrintable.cx); // PIXELS PER INCH "LOGPIXELS" POINTD ptdPageLogPixels = { ps.szlPhysicalPage.cx / ps.szdPhysicalPage_Inches.cx, ps.szlPhysicalPage.cy / ps.szdPhysicalPage_Inches.cy }; // PAGE PRINTABLE SIZE IN INCHES SIZED szdPrintablePage_Inches = { ps.szlPrintable.cx / ptdPageLogPixels.x, ps.szlPrintable.cy / ptdPageLogPixels.y }; SIZED szdImageSelection_Inches = { RW(ss.rdSelection_Inches), RH(ss.rdSelection_Inches) }; SIZED szdMinFreePrintableMosaic_Inches = { szdImageSelection_Inches.cx * dZoom, szdImageSelection_Inches.cy * dZoom }; SIZED szdOuterMargin = { ps.ms.rdEdgeMargins_Inches.left + ps.ms.rdEdgeMargins_Inches.right - (ps.szdPhysicalPage_Inches.cx - szdPrintablePage_Inches.cx), ps.ms.rdEdgeMargins_Inches.top + ps.ms.rdEdgeMargins_Inches.bottom - (ps.szdPhysicalPage_Inches.cy - szdPrintablePage_Inches.cy) }; double dMoreInnerMargin = ps.ms.dOverlapMargin_Inches + (rs.bCutGuides ? ps.ms.dCutGuideMargin_Inches : 0); SIZED szdMoreInnerMargin = { (bAllWidth ? 0 : dMoreInnerMargin), (bAllHeight ? 0 : dMoreInnerMargin) }; SIZED szdMinMosaic; szdMinMosaic.cy = ( szdMinFreePrintableMosaic_Inches.cy + szdOuterMargin.cy - szdMoreInnerMargin.cy ) / (szdPrintablePage_Inches.cy - szdMoreInnerMargin.cy); szdMinMosaic.cx = ( szdMinFreePrintableMosaic_Inches.cx + szdOuterMargin.cx - szdMoreInnerMargin.cx ) / (szdPrintablePage_Inches.cx - szdMoreInnerMargin.cx); if (szdMinMosaic.cx < 1) { szMosaic.cx = 1; } else { // 6/3 SAW 5 + 9E-16 GET ROUNDED UP TO 6, LOSS OF PRECISION IN CALCULATIONS // AD-HOC FACTOR TO FIX THIS szMosaic.cx = ::RoundUp(szdMinMosaic.cx - FUDGE_MOSAICFROMZOOM); } if (szdMinMosaic.cy < 1) { szMosaic.cy = 1; } else { szMosaic.cy = ::RoundUp(szdMinMosaic.cy - FUDGE_MOSAICFROMZOOM);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -