void PCB_BASE_FRAME::CursorGoto( const wxPoint& aPos, bool aWarp ) { // factored out of pcbnew/find.cpp PCB_SCREEN* screen = (PCB_SCREEN*)GetScreen(); INSTALL_UNBUFFERED_DC( dc, m_canvas ); // There may be need to reframe the drawing. if( !m_canvas->IsPointOnDisplay( aPos ) ) { screen->SetCrossHairPosition( aPos ); RedrawScreen( aPos, aWarp ); } else { // Put cursor on item position m_canvas->CrossHairOff( &dc ); screen->SetCrossHairPosition( aPos ); if( aWarp ) m_canvas->MoveCursorToCrossHair(); } m_canvas->CrossHairOn( &dc ); m_canvas->CrossHairOn( &dc ); }
void WinEDA_GerberFrame::OnCloseWindow(wxCloseEvent & Event) /***********************************************************/ { PCB_SCREEN * screen; screen = ScreenPcb ; while( screen ) { if(screen->IsModify()) break; screen = screen->Next(); } if ( screen ) { if( ! IsOK(this, _("Layer modified, Continue ?")) ) { Event.Veto(); return; } } while( screen ) // suppression flag modify pour eviter d'autres message { screen->ClrModify(); screen = screen->Next(); } /* Reselection de l'ecran de base, pour les evenements de refresh générés par wxWindows */ m_CurrentScreen = ActiveScreen = ScreenPcb; SaveSettings(); Destroy(); }
void WinEDA_PcbFrame::RedrawActiveWindow(wxDC * DC, bool EraseBg) /****************************************************************/ /* Trace le PCB, et les elements complementaires ( axes, grille .. ) pour l'ecran actif et ses sous ecran */ { PCB_SCREEN * Screen = GetScreen(); if ( ! m_Pcb || ! Screen ) return; ActiveScreen = GetScreen(); GRSetDrawMode(DC, GR_COPY); if ( EraseBg ) DrawPanel->EraseScreen(DC); DrawPanel->DrawBackGround(DC); Trace_Pcb(DC, GR_OR); TraceWorkSheet(DC, GetScreen()); Affiche_Status_Box(); /* Reaffichage des curseurs */ for( Screen = GetScreen(); Screen != NULL; Screen = Screen->Next() ) { if( m_CurrentScreen->ManageCurseur ) m_CurrentScreen->ManageCurseur(DrawPanel, DC, FALSE); Screen->Trace_Curseur(DrawPanel, DC); } }
VECTOR2I GRID_HELPER::GetGrid() const { PCB_SCREEN* screen = m_frame->GetScreen(); const wxRealPoint& size = screen->GetGridSize(); return VECTOR2I( KiROUND( size.x ), KiROUND( size.y ) ); }
void WinEDA_PcbFrame::OnCloseWindow(wxCloseEvent & Event) /********************************************************/ { PCB_SCREEN * screen; DrawPanel->m_AbortRequest = TRUE; screen = ScreenPcb ; while( screen ) { if(screen->IsModify()) break; screen = screen->Next(); } if ( screen ) { unsigned ii; wxMessageDialog dialog(this, _("Board modified, Save before exit ?"), _("Confirmation"), wxYES_NO | wxCANCEL | wxICON_EXCLAMATION | wxYES_DEFAULT); ii = dialog.ShowModal(); switch ( ii ) { case wxID_CANCEL: Event.Veto(); return; case wxID_NO: break; case wxID_OK: case wxID_YES: SavePcbFile(GetScreen()->m_FileName); break; } } while( screen ) // suppression flag modify pour eviter d'autres message { screen->ClrModify(); screen = screen->Next(); } /* Reselection de l'ecran de base, pour les evenements de refresh générés par wxWindows */ m_CurrentScreen = ActiveScreen = ScreenPcb; SaveSettings(); Destroy(); }
static void BuildDimension( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { PCB_SCREEN* screen = (PCB_SCREEN*) aPanel->GetScreen(); DIMENSION* Dimension = (DIMENSION*) screen->GetCurItem(); wxPoint pos = aPanel->GetParent()->GetCrossHairPosition(); if( Dimension == NULL ) return; // Erase previous dimension. if( aErase ) { Dimension->Draw( aPanel, aDC, GR_XOR ); } Dimension->SetLayer( screen->m_Active_Layer ); if( status_dimension == 1 ) { Dimension->m_featureLineDO = pos; Dimension->m_crossBarF = Dimension->m_featureLineDO; Dimension->AdjustDimensionDetails( ); } else { wxPoint delta; int dx, dy; double angle, depl; delta = Dimension->m_featureLineDO - Dimension->m_featureLineGO; /* Calculating the direction of travel perpendicular to the selected axis. */ angle = atan2( delta.y, delta.x ) + (M_PI / 2); delta = pos - Dimension->m_featureLineDO; depl = ( delta.x * cos( angle ) ) + ( delta.y * sin( angle ) ); dx = KiROUND( depl * cos( angle ) ); dy = KiROUND( depl * sin( angle ) ); Dimension->m_crossBarO.x = Dimension->m_featureLineGO.x + dx; Dimension->m_crossBarO.y = Dimension->m_featureLineGO.y + dy; Dimension->m_crossBarF.x = Dimension->m_featureLineDO.x + dx; Dimension->m_crossBarF.y = Dimension->m_featureLineDO.y + dy; Dimension->AdjustDimensionDetails( ); } Dimension->Draw( aPanel, aDC, GR_XOR ); }
/* * Update the status bar information. */ void PCB_BASE_FRAME::UpdateStatusBar() { EDA_DRAW_FRAME::UpdateStatusBar(); if( DisplayOpt.DisplayPolarCood ) // display polar coordinates { PCB_SCREEN* screen = GetScreen(); if( !screen ) return; wxString Line; double theta, ro; int dx = screen->GetCrossHairPosition().x - screen->m_O_Curseur.x; int dy = screen->GetCrossHairPosition().y - screen->m_O_Curseur.y; if( dx==0 && dy==0 ) theta = 0.0; else theta = atan2( (double) -dy, (double) dx ); theta = theta * 180.0 / M_PI; ro = sqrt( ( (double) dx * dx ) + ( (double) dy * dy ) ); wxString formatter; switch( g_UserUnit ) { case INCHES: formatter = wxT( "Ro %.4f Th %.1f" ); break; case MILLIMETRES: formatter = wxT( "Ro %.3f Th %.1f" ); break; case UNSCALED_UNITS: formatter = wxT( "Ro %f Th %f" ); break; } Line.Printf( formatter, To_User_Unit( g_UserUnit, ro, m_internalUnits ), theta ); // overwrite the absolute cartesian coordinates SetStatusText( Line, 2 ); } }
void WinEDA_ModuleEditFrame::RedrawActiveWindow(wxDC * DC, bool EraseBg) /**********************************************************************/ /* Trace le PCB, et les elements complementaires ( axes, grille .. ) pour l'ecran actif et ses sous ecran */ { MODULE * Module; PCB_SCREEN * screen = GetScreen(); if ( ! m_Pcb || ! screen ) return; ActiveScreen = screen; GRSetDrawMode(DC, GR_COPY); if ( EraseBg ) DrawPanel->EraseScreen(DC); DrawPanel->DrawBackGround(DC); TraceWorkSheet(DC, screen); Module = (MODULE*) m_Pcb->m_Modules; for ( ; Module != NULL; Module = (MODULE *) Module->Pnext ) { Module->Draw(DrawPanel, DC, wxPoint(0,0), GR_OR); } Affiche_Status_Box(); if( screen->ManageCurseur ) screen->ManageCurseur(DrawPanel, DC, FALSE); /* Reaffichage du curseur */ screen->Trace_Curseur(DrawPanel, DC); screen->ClrRefreshReq(); }
void PCB_BASE_FRAME::CursorGoto( const wxPoint& aPos ) { // factored out of pcbnew/find.cpp PCB_SCREEN* screen = (PCB_SCREEN*)GetScreen(); wxClientDC dc( m_canvas ); // There may be need to reframe the drawing. if( !m_canvas->IsPointOnDisplay( aPos ) ) { screen->SetCrossHairPosition( aPos ); RedrawScreen( aPos, true ); } else { // Put cursor on item position m_canvas->CrossHairOff( &dc ); screen->SetCrossHairPosition( aPos ); m_canvas->MoveCursorToCrossHair(); m_canvas->CrossHairOn( &dc ); } }
/* * Update the status bar information. */ void PCB_BASE_FRAME::UpdateStatusBar() { EDA_DRAW_FRAME::UpdateStatusBar(); PCB_SCREEN* screen = GetScreen(); if( !screen ) return; int dx; int dy; double dXpos; double dYpos; wxString line; wxString locformatter; if( DisplayOpt.DisplayPolarCood ) // display polar coordinates { double theta, ro; dx = screen->GetCrossHairPosition().x - screen->m_O_Curseur.x; dy = screen->GetCrossHairPosition().y - screen->m_O_Curseur.y; if( dx==0 && dy==0 ) theta = 0.0; else theta = atan2( (double) -dy, (double) dx ); theta = theta * 180.0 / M_PI; ro = sqrt( ( (double) dx * dx ) + ( (double) dy * dy ) ); wxString formatter; switch( g_UserUnit ) { #if defined( USE_PCBNEW_NANOMETRE ) case INCHES: formatter = wxT( "Ro %.6f Th %.1f" ); break; case MILLIMETRES: formatter = wxT( "Ro %.6f Th %.1f" ); break; #else case INCHES: formatter = wxT( "Ro %.4f Th %.1f" ); break; case MILLIMETRES: formatter = wxT( "Ro %.3f Th %.1f" ); break; #endif case UNSCALED_UNITS: formatter = wxT( "Ro %f Th %f" ); break; } line.Printf( formatter, To_User_Unit( g_UserUnit, ro ), theta ); SetStatusText( line, 3 ); } // Display absolute coordinates: dXpos = To_User_Unit( g_UserUnit, screen->GetCrossHairPosition().x ); dYpos = To_User_Unit( g_UserUnit, screen->GetCrossHairPosition().y ); if ( g_UserUnit == MILLIMETRES ) { dXpos = RoundTo0( dXpos, 1000.0 ); dYpos = RoundTo0( dYpos, 1000.0 ); } // The following sadly is an if Eeschema/if Pcbnew wxString absformatter; switch( g_UserUnit ) { #if defined( USE_PCBNEW_NANOMETRES ) case INCHES: absformatter = wxT( "X %.6f Y %.6f" ); locformatter = wxT( "dx %.6f dy %.6f d %.6f" ); break; case MILLIMETRES: absformatter = wxT( "X %.6f Y %.6f" ); locformatter = wxT( "dx %.6f dy %.6f d %.6f" ); break; #else case INCHES: absformatter = wxT( "X %.4f Y %.4f" ); locformatter = wxT( "dx %.4f dy %.4f d %.4f" ); break; case MILLIMETRES: absformatter = wxT( "X %.3f Y %.3f" ); locformatter = wxT( "dx %.3f dy %.3f d %.3f" ); break; #endif case UNSCALED_UNITS: absformatter = wxT( "X %f Y %f" ); locformatter = wxT( "dx %f dy %f d %f" ); break; } line.Printf( absformatter, dXpos, dYpos ); SetStatusText( line, 2 ); if( !DisplayOpt.DisplayPolarCood ) // display relative cartesian coordinates { // Display relative coordinates: dx = screen->GetCrossHairPosition().x - screen->m_O_Curseur.x; dy = screen->GetCrossHairPosition().y - screen->m_O_Curseur.y; dXpos = To_User_Unit( g_UserUnit, dx ); dYpos = To_User_Unit( g_UserUnit, dy ); if ( g_UserUnit == MILLIMETRES ) { dXpos = RoundTo0( dXpos, 1000.0 ); dYpos = RoundTo0( dYpos, 1000.0 ); } // We already decided the formatter above line.Printf( locformatter, dXpos, dYpos, sqrt( dXpos * dXpos + dYpos * dYpos ) ); SetStatusText( line, 3 ); } }
void EDGE_MODULE::Draw(WinEDA_DrawPanel * panel, wxDC * DC, const wxPoint & offset, int draw_mode) /********************************************************************************/ /* Affichage d'un segment contour de module : Entree : ox, oy = offset de trace draw_mode = mode de trace ( GR_OR, GR_XOR, GR_AND) Les contours sont de differents type: - Segment - Cercles - Arcs */ { int ux0, uy0, dx, dy,rayon, StAngle, EndAngle; int color , type_trace; int zoom; int typeaff; PCB_SCREEN * screen; WinEDA_BasePcbFrame * frame; MODULE * Module = NULL; if ( m_Parent && (m_Parent->m_StructType == TYPEMODULE) ) Module = (MODULE*) m_Parent; GRSetDrawMode(DC, draw_mode); color = g_DesignSettings.m_LayerColor[m_Layer]; if ( panel ) screen = (PCB_SCREEN *) panel->m_Parent->m_CurrentScreen; else screen = ActiveScreen; frame = screen->GetParentPcbFrame(); zoom = screen->GetZoom(); type_trace = m_Shape; ux0 = m_Start.x - offset.x; uy0 = m_Start.y - offset.y; dx = m_End.x - offset.x ; dy = m_End.y - offset.y ; typeaff = frame->m_DisplayModEdge; if( m_Layer <= CMP_N ) typeaff = frame->m_DisplayPcbTrackFill; if( (m_Width /zoom) < L_MIN_DESSIN ) typeaff = FILAIRE; switch (type_trace ) { case S_SEGMENT: if( typeaff == FILAIRE) GRLine(&panel->m_ClipBox, DC, ux0, uy0, dx, dy, color); else Affiche_1_Segment(panel, DC, ux0,uy0,dx,dy,m_Width, typeaff,color); break ; case S_CIRCLE: rayon = (int)hypot((double)(dx-ux0),(double)(dy-uy0) ); if( typeaff == FILAIRE) { GRCircle(&panel->m_ClipBox, DC, ux0, uy0, rayon, color) ; } else { if(typeaff == FILLED ) { GRCircle(&panel->m_ClipBox, DC, ux0, uy0, rayon, m_Width, color); } else { GRCircle(&panel->m_ClipBox, DC, ux0, uy0, rayon + (m_Width/2), color) ; GRCircle(&panel->m_ClipBox, DC, ux0, uy0, rayon - (m_Width/2), color) ; } } break; case S_ARC: rayon = (int)hypot((double)(dx-ux0),(double)(dy-uy0) ); StAngle = (int)ArcTangente( dy-uy0, dx-ux0 ); EndAngle = StAngle + m_Angle; if ( StAngle > EndAngle) EXCHG (StAngle, EndAngle); if( typeaff == FILAIRE) { GRArc(&panel->m_ClipBox, DC, ux0, uy0, StAngle, EndAngle, rayon, color) ; } else if(typeaff == FILLED ) { GRArc(&panel->m_ClipBox, DC, ux0, uy0, StAngle, EndAngle, rayon, m_Width, color); } else { GRArc(&panel->m_ClipBox, DC, ux0, uy0, StAngle, EndAngle, rayon + (m_Width/2), color) ; GRArc(&panel->m_ClipBox, DC, ux0, uy0, StAngle, EndAngle, rayon - (m_Width/2), color) ; } break; case S_POLYGON: { // We must compute true coordinates from m_PolyList // which are relative to module position, orientation 0 int ii, * source, * ptr, * ptr_base; ptr = ptr_base = (int*) MyMalloc( 2 * m_PolyCount * sizeof(int) ); source = m_PolyList; for (ii = 0; ii < m_PolyCount; ii++ ) { int x, y; x = *source; source++; y = *source; source++; if ( Module ) { RotatePoint (&x, &y, Module->m_Orient); x += Module->m_Pos.x; y += Module->m_Pos.y; } x += m_Start0.x - offset.x; y += m_Start0.y - offset.y; *ptr = x; ptr++; *ptr = y; ptr++; } GRPoly(&panel->m_ClipBox, DC, m_PolyCount, ptr_base, TRUE, color, color); free ( ptr_base); break; } } }
void WinEDA_PcbFindFrame::FindItem(wxCommandEvent& event) /********************************************************/ { PCB_SCREEN * screen = m_Parent->GetScreen(); wxPoint locate_pos; wxString msg; bool succes = FALSE; bool FindMarker = FALSE; MODULE * Module; int StartCount; switch ( event.GetId() ) { case ID_FIND_ITEM: s_ItemCount = 0; break; case ID_FIND_MARKER: s_MarkerCount = 0; case ID_FIND_NEXT_MARKER: FindMarker = TRUE; break; } s_OldStringFound = m_NewText->GetValue(); m_Parent->DrawPanel->GetViewStart(&screen->m_StartVisu.x, &screen->m_StartVisu.y); StartCount = 0; if( FindMarker ) { MARQUEUR * Marker = (MARQUEUR *) m_Parent->m_Pcb->m_Drawings; for( ; Marker != NULL; Marker = (MARQUEUR *)Marker->Pnext) { if( Marker->m_StructType != TYPEMARQUEUR ) continue; StartCount++; if ( StartCount > s_MarkerCount ) { succes = TRUE; locate_pos = Marker->m_Pos; s_MarkerCount++; break; } } } else for ( Module = m_Parent->m_Pcb->m_Modules; Module != NULL; Module = (MODULE*)Module->Pnext) { if( WildCompareString( s_OldStringFound, Module->m_Reference->m_Text.GetData(), FALSE ) ) { StartCount++; if ( StartCount > s_ItemCount ) { succes = TRUE; locate_pos = Module->m_Pos; s_ItemCount++; break; } } if( WildCompareString( s_OldStringFound, Module->m_Value->m_Text.GetData(), FALSE ) ) { StartCount++; if ( StartCount > s_ItemCount ) { succes = TRUE; locate_pos = Module->m_Pos; s_ItemCount++; break; } } } if ( succes ) { /* Il y a peut-etre necessite de recadrer le dessin: */ if( ! m_Parent->DrawPanel->IsPointOnDisplay(locate_pos) ) { screen->m_Curseur = locate_pos; m_Parent->Recadre_Trace(TRUE); } else { // Positionnement du curseur sur l'item screen->Trace_Curseur(m_Parent->DrawPanel, m_DC); screen->m_Curseur = locate_pos; GRMouseWarp(m_Parent->DrawPanel, screen->m_Curseur ); m_Parent->DrawPanel->MouseToCursorSchema(); screen->Trace_Curseur(m_Parent->DrawPanel, m_DC); } if( FindMarker ) msg = _("Marker found"); else msg.Printf( _("<%s> Found"), s_OldStringFound.GetData() ); m_Parent->Affiche_Message(msg); EndModal(1); } else { m_Parent->Affiche_Message(wxEmptyString); if( FindMarker ) msg = _("Marker not found"); else msg.Printf( _("<%s> Not Found"), s_OldStringFound.GetData()); DisplayError(this,msg, 10); } EndModal(0); }
/* Insert the new track created in the list of tracks. * amend the points of beginning and end of the track so that they are * connected * Center on pads even if they are off grid. */ static void AddNewTrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) { if( g_FirstTrackSegment == NULL ) return; int dx0, dy0, dx1, dy1; int marge, via_marge; EDA_DRAW_PANEL* panel = pcbframe->GetCanvas(); PCB_SCREEN* screen = pcbframe->GetScreen(); marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 ); via_marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentViaSize() / 2 ); dx1 = g_CurrentTrackSegment->GetEnd().x - g_CurrentTrackSegment->GetStart().x; dy1 = g_CurrentTrackSegment->GetEnd().y - g_CurrentTrackSegment->GetStart().y; // Place on center of pad if off grid. dx0 = pt_cur_ch->m_PadStart->GetPosition().x - g_CurrentTrackSegment->GetStart().x; dy0 = pt_cur_ch->m_PadStart->GetPosition().y - g_CurrentTrackSegment->GetStart().y; // If aligned, change the origin point. if( abs( dx0 * dy1 ) == abs( dx1 * dy0 ) ) { g_CurrentTrackSegment->SetEnd( pt_cur_ch->m_PadStart->GetPosition() ); } else { TRACK* newTrack = (TRACK*)g_CurrentTrackSegment->Clone(); newTrack->SetEnd( pt_cur_ch->m_PadStart->GetPosition() ); newTrack->SetStart( g_CurrentTrackSegment->GetEnd() ); g_CurrentTrackList.PushBack( newTrack ); } g_FirstTrackSegment->start = pcbframe->GetBoard()->GetPad( g_FirstTrackSegment, ENDPOINT_START ); if( g_FirstTrackSegment->start ) g_FirstTrackSegment->SetState( BEGIN_ONPAD, true ); g_CurrentTrackSegment->end = pcbframe->GetBoard()->GetPad( g_CurrentTrackSegment, ENDPOINT_END ); if( g_CurrentTrackSegment->end ) g_CurrentTrackSegment->SetState( END_ONPAD, true ); // Out the new track on the matrix board for( TRACK* track = g_FirstTrackSegment; track; track = track->Next() ) { TraceSegmentPcb( track, HOLE, marge, WRITE_CELL ); TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } // Insert new segments in real board int netcode = g_FirstTrackSegment->GetNetCode(); TRACK* firstTrack = g_FirstTrackSegment; int newCount = g_CurrentTrackList.GetCount(); // Put entire new current segment list in BOARD TRACK* track; TRACK* insertBeforeMe = g_CurrentTrackSegment->GetBestInsertPoint( pcbframe->GetBoard() ); while( ( track = g_CurrentTrackList.PopFront() ) != NULL ) { ITEM_PICKER picker( track, UR_NEW ); s_ItemsListPicker.PushItem( picker ); pcbframe->GetBoard()->m_Track.Insert( track, insertBeforeMe ); } DrawTraces( panel, DC, firstTrack, newCount, GR_OR ); pcbframe->TestNetConnection( DC, netcode ); screen->SetModify(); }
void FOOTPRINT_WIZARD_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey ) { wxRealPoint gridSize; wxPoint oldpos; PCB_SCREEN* screen = GetScreen(); wxPoint pos = aPosition; wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED ); cmd.SetEventObject( this ); pos = GetNearestGridPosition( pos ); oldpos = GetCrossHairPosition(); gridSize = screen->GetGridSize(); switch( aHotKey ) { case WXK_F1: cmd.SetId( ID_POPUP_ZOOM_IN ); GetEventHandler()->ProcessEvent( cmd ); break; case WXK_F2: cmd.SetId( ID_POPUP_ZOOM_OUT ); GetEventHandler()->ProcessEvent( cmd ); break; case WXK_F3: cmd.SetId( ID_ZOOM_REDRAW ); GetEventHandler()->ProcessEvent( cmd ); break; case WXK_F4: cmd.SetId( ID_POPUP_ZOOM_CENTER ); GetEventHandler()->ProcessEvent( cmd ); break; case WXK_HOME: cmd.SetId( ID_ZOOM_PAGE ); GetEventHandler()->ProcessEvent( cmd ); break; case ' ': screen->m_O_Curseur = GetCrossHairPosition(); break; case WXK_NUMPAD8: // cursor moved up case WXK_UP: pos.y -= KiROUND( gridSize.y ); m_canvas->MoveCursor( pos ); break; case WXK_NUMPAD2: // cursor moved down case WXK_DOWN: pos.y += KiROUND( gridSize.y ); m_canvas->MoveCursor( pos ); break; case WXK_NUMPAD4: // cursor moved left case WXK_LEFT: pos.x -= KiROUND( gridSize.x ); m_canvas->MoveCursor( pos ); break; case WXK_NUMPAD6: // cursor moved right case WXK_RIGHT: pos.x += KiROUND( gridSize.x ); m_canvas->MoveCursor( pos ); break; } SetCrossHairPosition( pos ); if( oldpos != GetCrossHairPosition() ) { pos = GetCrossHairPosition(); SetCrossHairPosition( oldpos ); m_canvas->CrossHairOff( aDC ); SetCrossHairPosition( pos ); m_canvas->CrossHairOn( aDC ); if( m_canvas->IsMouseCaptured() ) { m_canvas->CallMouseCapture( aDC, aPosition, 0 ); } } UpdateStatusBar(); // Display new cursor coordinates }
/* * 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 ); }