diff options
Diffstat (limited to 'WebKit/win/WebFrame.cpp')
-rw-r--r-- | WebKit/win/WebFrame.cpp | 135 |
1 files changed, 99 insertions, 36 deletions
diff --git a/WebKit/win/WebFrame.cpp b/WebKit/win/WebFrame.cpp index 0e8ee80..319fbbc 100644 --- a/WebKit/win/WebFrame.cpp +++ b/WebKit/win/WebFrame.cpp @@ -2150,12 +2150,10 @@ static HDC hdcFromContext(PlatformGraphicsContext* pctx) void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, float headerHeight) { HDC hdc = hdcFromContext(pctx); - const IntRect& marginRect = printerMarginRect(hdc); - const float scale = scaleFactor(hdc, marginRect, pageRect); - int x = static_cast<int>(scale * pageRect.x()); + int x = pageRect.x(); int y = 0; - RECT headerRect = {x, y, x + static_cast<int>(scale * pageRect.width()), y + static_cast<int>(scale * headerHeight)}; + RECT headerRect = {x, y, x + pageRect.width(), y + static_cast<int>(headerHeight)}; ui->drawHeaderInRect(d->webView, &headerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(hdc))); } @@ -2163,16 +2161,29 @@ void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, con void WebFrame::drawFooter(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, UINT page, UINT pageCount, float headerHeight, float footerHeight) { HDC hdc = hdcFromContext(pctx); - const IntRect& marginRect = printerMarginRect(hdc); - - const float scale = scaleFactor(hdc, marginRect, pageRect); - int x = static_cast<int>(scale * pageRect.x()); - int y = static_cast<int>(scale * max(static_cast<int>(headerHeight) + pageRect.height(), m_pageHeight-static_cast<int>(footerHeight))); - RECT footerRect = {x, y, x + static_cast<int>(scale * pageRect.width()), y + static_cast<int>(scale * footerHeight)}; + + int x = pageRect.x(); + int y = max(static_cast<int>(headerHeight) + pageRect.height(), m_pageHeight -static_cast<int>(footerHeight)); + RECT footerRect = {x, y, x + pageRect.width(), y + static_cast<int>(footerHeight)}; ui->drawFooterInRect(d->webView, &footerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(hdc)), page+1, pageCount); } +static XFORM buildXFORMFromCairo(HDC targetDC, cairo_t* previewContext) +{ + XFORM scaled; + GetWorldTransform(targetDC, &scaled); + + cairo_matrix_t ctm; + cairo_get_matrix(previewContext, &ctm); + + // Scale to the preview screen bounds + scaled.eM11 = ctm.xx; + scaled.eM22 = ctm.yy; + + return scaled; +} + void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCtx, HDC printDC, IWebUIDelegate* ui, float headerHeight, float footerHeight, UINT page, UINT pageCount) { Frame* coreFrame = core(this); @@ -2180,48 +2191,83 @@ void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCt const IntRect& pageRect = m_pageRects[page]; const IntRect& marginRect = printerMarginRect(printDC); - cairo_save(pctx); + // In preview, the printDC is a placeholder, so just always use the HDC backing the graphics context. + HDC hdc = hdcFromContext(pctx); + spoolCtx->save(); - float scale = scaleFactor(printDC, marginRect, pageRect); - cairo_scale(pctx, scale, scale); + + XFORM original, scaled; + GetWorldTransform(hdc, &original); + + bool preview = (hdc != printDC); + if (preview) { + // If this is a preview, the Windows HDC was set to a non-scaled state so that Cairo will + // draw correctly. We need to retain the correct preview scale here for use when the Cairo + // drawing completes so that we can scale our GDI-based header/footer calls. This is a + // workaround for a bug in Cairo (see https://bugs.freedesktop.org/show_bug.cgi?id=28161) + scaled = buildXFORMFromCairo(hdc, pctx); + } - IntRect cairoMarginRect (marginRect); - cairoMarginRect.scale (1 / scale); + float scale = scaleFactor(printDC, marginRect, pageRect); + + IntRect cairoMarginRect(marginRect); + cairoMarginRect.scale(1 / scale); - // Modify Cairo and GDI World Transform to account for margin in the - // subsequent WebKit-controlled 'paintContents' drawing operations: - spoolCtx->translate(cairoMarginRect.x(), cairoMarginRect.y() + headerHeight); + // We cannot scale the display HDC because the print surface also scales fonts, + // resulting in invalid printing (and print preview) + cairo_scale(pctx, scale, scale); + cairo_translate(pctx, cairoMarginRect.x(), cairoMarginRect.y() + headerHeight); // Modify Cairo (only) to account for page position. cairo_translate(pctx, -pageRect.x(), -pageRect.y()); coreFrame->view()->paintContents(spoolCtx, pageRect); - cairo_translate(pctx, pageRect.x(), pageRect.y()); - - XFORM originalWorld; - ::GetWorldTransform(printDC, &originalWorld); - - // Position GDI world transform to account for margin in GDI-only - // header/footer calls - XFORM newWorld = originalWorld; - newWorld.eDx = marginRect.x(); - newWorld.eDy = marginRect.y(); - - ::SetWorldTransform(printDC, &newWorld); - + + if (preview) { + // If this is a preview, the Windows HDC was set to a non-scaled state so that Cairo would + // draw correctly. We need to rescale the HDC to the correct preview scale so our GDI-based + // header/footer calls will draw properly. This is a workaround for a bug in Cairo. + // (see https://bugs.freedesktop.org/show_bug.cgi?id=28161) + SetWorldTransform(hdc, &scaled); + } + + XFORM xform = TransformationMatrix().translate(marginRect.x(), marginRect.y()).scale(scale); + ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY); + if (headerHeight) drawHeader(pctx, ui, pageRect, headerHeight); if (footerHeight) drawFooter(pctx, ui, pageRect, page, pageCount, headerHeight, footerHeight); - ::SetWorldTransform(printDC, &originalWorld); + SetWorldTransform(hdc, &original); cairo_show_page(pctx); ASSERT(!cairo_status(pctx)); spoolCtx->restore(); - cairo_restore(pctx); } + +static void setCairoTransformToPreviewHDC(cairo_t* previewCtx, HDC previewDC) +{ + XFORM passedCTM; + GetWorldTransform(previewDC, &passedCTM); + + // Reset HDC WorldTransform to unscaled state. Scaling must be + // done in Cairo to avoid drawing errors. + XFORM unscaledCTM = passedCTM; + unscaledCTM.eM11 = 1.0; + unscaledCTM.eM22 = 1.0; + + SetWorldTransform(previewDC, &unscaledCTM); + + // Make the Cairo transform match the information passed to WebKit + // in the HDC's WorldTransform. + cairo_matrix_t ctm = { passedCTM.eM11, passedCTM.eM12, passedCTM.eM21, + passedCTM.eM22, passedCTM.eDx, passedCTM.eDy }; + + cairo_set_matrix(previewCtx, &ctm); +} + #endif HRESULT STDMETHODCALLTYPE WebFrame::spoolPages( @@ -2240,13 +2286,28 @@ HRESULT STDMETHODCALLTYPE WebFrame::spoolPages( ASSERT_NOT_REACHED(); return E_POINTER; } + + HDC targetDC = (ctx) ? (HDC)ctx : printDC; - cairo_surface_t* printSurface = cairo_win32_printing_surface_create(printDC); - ctx = cairo_create(printSurface); - if (!ctx) { + cairo_surface_t* printSurface = 0; + if (ctx) + printSurface = cairo_win32_surface_create(targetDC); // in-memory + else + printSurface = cairo_win32_printing_surface_create(targetDC); // metafile + + PlatformGraphicsContext* pctx = (PlatformGraphicsContext*)cairo_create(printSurface); + if (!pctx) { cairo_surface_destroy(printSurface); return E_FAIL; } + + if (ctx) { + // If this is a preview, the Windows HDC was sent with scaling information. + // Retrieve it and reset it so that it draws properly. This is a workaround + // for a bug in Cairo (see https://bugs.freedesktop.org/show_bug.cgi?id=28161) + setCairoTransformToPreviewHDC(pctx, targetDC); + } + cairo_surface_set_fallback_resolution(printSurface, 72.0, 72.0); #endif @@ -2260,7 +2321,9 @@ HRESULT STDMETHODCALLTYPE WebFrame::spoolPages( return E_FAIL; UINT pageCount = (UINT) m_pageRects.size(); +#if PLATFORM(CG) PlatformGraphicsContext* pctx = (PlatformGraphicsContext*)ctx; +#endif if (!pageCount || startPage > pageCount) { ASSERT_NOT_REACHED(); |