Ejemplo n.º 1
0
bool wxWindowsPrintPreview::RenderPageIntoBitmap(wxBitmap& bmp, int pageNum)
{
    // The preview, as implemented in wxPrintPreviewBase (and as used prior to
    // wx3) is inexact: it uses screen DC, which has much lower resolution and
    // has other properties different from printer DC, so the preview is not
    // quite right.
    //
    // To make matters worse, if the application depends heavily on
    // GetTextExtent() or does text layout itself, the output in preview and on
    // paper can be very different. In particular, wxHtmlEasyPrinting is
    // affected and the preview can be easily off by several pages.
    //
    // To fix this, we render the preview into high-resolution enhanced
    // metafile with properties identical to the printer DC. This guarantees
    // metrics correctness while still being fast.


    // print the preview into a metafile:
    wxPrinterDC printerDC(m_printDialogData.GetPrintData());
    wxEnhMetaFileDC metaDC(printerDC,
                           wxEmptyString,
                           printerDC.GetSize().x, printerDC.GetSize().y);

    if ( !RenderPageIntoDC(metaDC, pageNum) )
        return false;

    wxEnhMetaFile *metafile = metaDC.Close();
    if ( !metafile )
        return false;

    // now render the metafile:
    wxMemoryDC bmpDC;
    bmpDC.SelectObject(bmp);
    bmpDC.Clear();

    wxRect outRect(0, 0, bmp.GetWidth(), bmp.GetHeight());
    metafile->Play(&bmpDC, &outRect);


    delete metafile;

    // TODO: we should keep the metafile and reuse it when changing zoom level

    return true;
}
Ejemplo n.º 2
0
bool wxWindowsPrintPreview::RenderPageFragment(float scaleX, float scaleY,
                                               int *nextFinalLine,
                                               wxPrinterDC& printer,
                                               wxMemoryDC& finalDC,
                                               const wxRect& rect,
                                               int pageNum)
{
    // compute 'rect' equivalent in the small final bitmap:
    const wxRect smallRect(wxPoint(0, *nextFinalLine),
                           wxPoint(int(rect.GetRight() * scaleX),
                                   int(rect.GetBottom() * scaleY)));
    wxLogTrace("printing",
               "rendering fragment of page %i: [%i,%i,%i,%i] scaled down to [%i,%i,%i,%i]",
               pageNum,
               rect.x, rect.y, rect.GetRight(), rect.GetBottom(),
               smallRect.x, smallRect.y, smallRect.GetRight(), smallRect.GetBottom()
               );

    // create DC and bitmap compatible with printer DC:
    wxBitmap large(rect.width, rect.height, printer);
    if ( !large.IsOk() )
        return false;

    // render part of the page into it:
    {
        PageFragmentDC memoryDC(&printer, large,
                                rect.GetPosition(),
                                wxSize(m_pageWidth, m_pageHeight));
        if ( !memoryDC.IsOk() )
            return false;

        memoryDC.Clear();

        if ( !RenderPageIntoDC(memoryDC, pageNum) )
            return false;
    } // release bitmap from memoryDC

    // now scale the rendered part down and blit it into final output:

    wxImage img;
    {
        wxDIB dib(large);
        if ( !dib.IsOk() )
            return false;
        large = wxNullBitmap; // free memory a.s.a.p.
        img = dib.ConvertToImage();
    } // free the DIB now that it's no longer needed, too

    if ( !img.IsOk() )
        return false;

    img.Rescale(smallRect.width, smallRect.height, wxIMAGE_QUALITY_HIGH);
    if ( !img.IsOk() )
        return false;

    wxBitmap bmp(img);
    if ( !bmp.IsOk() )
        return false;

    img = wxNullImage;
    finalDC.DrawBitmap(bmp, smallRect.x, smallRect.y);
    if ( bmp.IsOk() )
    {
        *nextFinalLine += smallRect.height;
        return true;
    }

    return false;
}