示例#1
0
/*
 * This is the real print function: print the active screen
 */
void BOARD_PRINTOUT_CONTROLER::DrawPage()
{
    int          tmpzoom;
    wxPoint      tmp_startvisu;
    wxPoint      old_org;
    wxPoint      DrawOffset;    // Offset de trace
    double       userscale;
    double       DrawZoom = 1;
    wxDC*        dc = GetDC();
    PCB_SCREEN*  screen = (PCB_SCREEN*) m_Parent->GetScreen();
    bool         printMirror = m_PrintParams.m_PrintMirror;

    wxBusyCursor dummy;

    // Save old draw scale and draw offset
    tmp_startvisu = screen->m_StartVisu;
    tmpzoom = screen->GetZoom();
    old_org = screen->m_DrawOrg;

    // Change draw scale and offset to draw the whole page
    screen->SetScalingFactor( DrawZoom );
    screen->m_DrawOrg.x   = screen->m_DrawOrg.y = 0;
    screen->m_StartVisu.x = screen->m_StartVisu.y = 0;

    PCB_BASE_FRAME* pcbframe = (PCB_BASE_FRAME*) m_Parent;

    wxSize  pageSizeIU = pcbframe->GetPageSizeIU();  // internal units
    EDA_RECT bbbox     = pcbframe->GetBoard()->ComputeBoundingBox();

    // In module editor, the module is located at 0,0 but for printing
    // it is moved to pageSizeIU.x/2, pageSizeIU.y/2.
    // So the equivalent board must be moved:
    if( m_Parent->IsType( MODULE_EDITOR_FRAME ) )
    {
        bbbox.Move( wxPoint( pageSizeIU.x/2, pageSizeIU.y/2 ) );
    }

    // Compute the PCB size in internal units
    userscale = m_PrintParams.m_PrintScale;

    if( userscale == 0 )                //  fit in page
    {
        // Margin = 0.4 inch
#if defined(KICAD_NANOMETRE)
        int extra_margin = int( 0.4 * 25400 );      // nanometers
#else
        int extra_margin = int( 0.4 * 1000 );       // deci-mils
#endif

        pageSizeIU.x = bbbox.GetWidth()  + extra_margin * 2;
        pageSizeIU.y = bbbox.GetHeight() + extra_margin * 2;

        userscale   = 0.99;
    }

    if( (m_PrintParams.m_PrintScale > 1.0)          //  scale > 1 -> Recadrage
       || (m_PrintParams.m_PrintScale == 0) )       //  fit in page
    {
        DrawOffset += bbbox.Centre();
    }

    if( m_PrintParams.m_PageSetupData )
    {
        wxSize pagesize;

        pagesize.x = int( pageSizeIU.x / userscale );
        pagesize.y = int( pageSizeIU.y / userscale );

        FitThisSizeToPageMargins( pagesize, *m_PrintParams.m_PageSetupData );
    }

    // Compute Accurate scale 1
    if( userscale == 1.0 )
    {
        // We want a 1:1 scale and margins for printing
        MapScreenSizeToPaper();
        int w, h;
        GetPPIPrinter( &w, &h );
        double accurate_Xscale = ( (double) ( DrawZoom * w ) ) / (double) PCB_INTERNAL_UNIT;
        double accurate_Yscale = ( (double) ( DrawZoom * h ) ) / (double) PCB_INTERNAL_UNIT;

        if( IsPreview() )  // Scale must take in account the DC size in Preview
        {
            // Get the size of the DC in pixels
            wxSize       PlotAreaSize;
            dc->GetSize( &PlotAreaSize.x, &PlotAreaSize.y );
            GetPageSizePixels( &w, &h );
            accurate_Xscale *= PlotAreaSize.x;
            accurate_Xscale /= (double) w;
            accurate_Yscale *= PlotAreaSize.y;
            accurate_Yscale /= (double) h;
        }
        accurate_Xscale *= m_PrintParams.m_XScaleAdjust;
        accurate_Yscale *= m_PrintParams.m_YScaleAdjust;
        // Fine scale adjust
        dc->SetUserScale( accurate_Xscale, accurate_Yscale );
    }

    // Get the final size of the DC in pixels
    wxSize       PlotAreaSizeInPixels;
    dc->GetSize( &PlotAreaSizeInPixels.x, &PlotAreaSizeInPixels.y );
    double scalex, scaley;
    dc->GetUserScale(&scalex, &scaley);
    wxSize PlotAreaSizeInUserUnits;
    PlotAreaSizeInUserUnits.x = (int) (PlotAreaSizeInPixels.x/scalex);
    PlotAreaSizeInUserUnits.y = (int) (PlotAreaSizeInPixels.y/scaley);

    /* In some cases the plot origin is the centre of the page
     *  when:
     *  - Asked
     *  - scale > 1
     *  - fit in page
     */
    if( m_PrintParams.m_ForceCentered
       || (m_PrintParams.m_PrintScale > 1.0)        //  scale > 1
       || (m_PrintParams.m_PrintScale == 0) )       //  fit in page
    {
        DrawOffset.x -= PlotAreaSizeInUserUnits.x / 2;
        DrawOffset.y -= PlotAreaSizeInUserUnits.y / 2;
    }

    screen->m_DrawOrg = DrawOffset;

    GRResetPenAndBrush( dc );

    if( m_PrintParams.m_Print_Black_and_White )
        GRForceBlackPen( true );

    EDA_DRAW_PANEL* panel = m_Parent->GetCanvas();
    EDA_RECT        tmp   = *panel->GetClipBox();

    // Set clip box to the max size
    #define MAX_VALUE (INT_MAX/2)   // MAX_VALUE is the max we can use in an integer
                                    // and that allows calculations without overflow
    panel->SetClipBox( EDA_RECT( wxPoint( 0, 0 ), wxSize( MAX_VALUE, MAX_VALUE ) ) );

    m_Parent->GetScreen()->m_IsPrinting = true;
    int bg_color = g_DrawBgColor;

    if( m_PrintParams.m_Print_Sheet_Ref )
        m_Parent->TraceWorkSheet( dc, screen, m_PrintParams.m_PenDefaultSize );

    if( printMirror )
    {
        // To plot mirror, we reverse the y axis, and modify the plot y origin
        dc->SetAxisOrientation( true, true );

        if( userscale < 1.0 )
            scaley /= userscale;

        /* Plot offset y is moved by the y plot area size in order to have
         * the old draw area in the new draw area, because the draw origin has not moved
         * (this is the upper left corner) but the Y axis is reversed, therefore the plotting area
         * is the y coordinate values from  - PlotAreaSize.y to 0 */
        int y_dc_offset = PlotAreaSizeInPixels.y;
        y_dc_offset = (int) ( ( double ) y_dc_offset * userscale );
        dc->SetDeviceOrigin( 0, y_dc_offset );
        int ysize = (int) ( PlotAreaSizeInPixels.y / scaley );
        DrawOffset.y += ysize;

        /* in order to keep the board position in the sheet
         * (when user scale <= 1) the y offset in moved by the distance between
         * the middle of the page and the middle of the board
         * This is equivalent to put the mirror axis to the board centre
         * for scales > 1, the DrawOffset was already computed to have the board centre
         * to the middle of the page.
         */
        wxPoint pcb_centre = bbbox.Centre();

        if( userscale <= 1.0 )
            DrawOffset.y += pcb_centre.y - (ysize / 2);

        dc->SetLogicalOrigin( screen->m_DrawOrg.x, screen->m_DrawOrg.y );
        panel->SetClipBox( EDA_RECT( wxPoint( -MAX_VALUE/2, -MAX_VALUE/2 ),
                                     panel->GetClipBox()->GetSize() ) );
    }

    g_DrawBgColor = WHITE;

    /* when printing in color mode, we use the graphic OR mode that gives the same look as the screen
     * But because the background is white when printing, we must use a trick:
     * In order to plot on a white background in OR mode we must:
     * 1 - Plot all items in black, this creates a local black backgroud
     * 2 - Plot in OR mode on black "local" background
     */
    if( !m_PrintParams.m_Print_Black_and_White )
    {   // Creates a "local" black background
        GRForceBlackPen( true );
        m_Parent->PrintPage( dc, m_PrintParams.m_PrintMaskLayer, printMirror, &m_PrintParams );
        GRForceBlackPen( false );
    }

    m_Parent->PrintPage( dc, m_PrintParams.m_PrintMaskLayer, printMirror, &m_PrintParams );

    g_DrawBgColor = bg_color;
    m_Parent->GetScreen()->m_IsPrinting = false;
    panel->SetClipBox( tmp );

    GRForceBlackPen( false );

    screen->m_StartVisu = tmp_startvisu;
    screen->m_DrawOrg   = old_org;
    screen->SetZoom( tmpzoom );
}