EDA_RECT SCH_FIELD::GetBoundingBox() const { SCH_COMPONENT* parentComponent = (SCH_COMPONENT*) m_Parent; int linewidth = ( m_Thickness == 0 ) ? GetDefaultLineThickness() : m_Thickness; // We must pass the effective text thickness to GetTextBox // when calculating the bounding box linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); // Calculate the text bounding box: EDA_RECT rect; // set USE_TEXT_JUSTIFY_INITIAL_BEHAVIOR to 0 to use // a justification relative to the text itself // i.e. justification relative to an horizontal text // or to 1 to keep the initial behavior #if (USE_TEXT_JUSTIFY_INITIAL_BEHAVIOR == 1 ) if( m_Orient == TEXT_ORIENT_VERT ) { // For vertical texts, exchange the horizontal and the vertical justification // The idea is to keep the justification always left or top for instance, // no matter the text orientation SCH_FIELD text( *this ); // Make a local copy to swap justifications // because GetBoundingBox() is const int tmp = (int)text.m_VJustify; NEGATE( tmp ); text.m_VJustify = (EDA_TEXT_VJUSTIFY_T)text.m_HJustify; text.m_HJustify = (EDA_TEXT_HJUSTIFY_T)tmp; rect = text.GetTextBox( -1, linewidth ); } else #endif rect = GetTextBox( -1, linewidth ); // Calculate the bounding box position relative to the component: wxPoint origin = parentComponent->GetPosition(); wxPoint pos = m_Pos - origin; wxPoint begin = rect.GetOrigin() - origin; wxPoint end = rect.GetEnd() - origin; RotatePoint( &begin, pos, m_Orient ); RotatePoint( &end, pos, m_Orient ); // Due to the Y axis direction, we must mirror the bounding box, // relative to the text position: begin.y -= pos.y; end.y -= pos.y; NEGATE( begin.y ); NEGATE( end.y ); begin.y += pos.y; end.y += pos.y; // Now, apply the component transform (mirror/rot) begin = parentComponent->GetTransform().TransformCoordinate( begin ); end = parentComponent->GetTransform().TransformCoordinate( end ); rect.SetOrigin( begin); rect.SetEnd( end); rect.Move( origin ); rect.Normalize(); return rect; }
/* Test if the module can be placed on the board. * Returns the value TstRectangle(). * Module is known by its bounding box */ int TstModuleOnBoard( BOARD* Pcb, MODULE* aModule, bool TstOtherSide ) { int side = TOP; int otherside = BOTTOM; if( aModule->GetLayer() == B_Cu ) { side = BOTTOM; otherside = TOP; } EDA_RECT fpBBox = aModule->GetFootprintRect(); fpBBox.Move( -g_Offset_Module ); int diag = TstRectangle( Pcb, fpBBox, side ); if( diag != FREE_CELL ) return diag; if( TstOtherSide ) { diag = TstRectangle( Pcb, fpBBox, otherside ); if( diag != FREE_CELL ) return diag; } int marge = ( RoutingMatrix.m_GridRouting * aModule->GetPadCount() ) / GAIN; fpBBox.Inflate( marge ); return CalculateKeepOutArea( fpBBox, side ); }
const EDA_RECT SCH_BITMAP::GetBoundingBox() const { EDA_RECT rect = m_image->GetBoundingBox(); rect.Move( m_pos ); return rect; }
void LIB_POLYLINE::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, EDA_COLOR_T aColor, GR_DRAWMODE aDrawMode, void* aData, const TRANSFORM& aTransform ) { wxPoint pos1; EDA_COLOR_T color = GetLayerColor( LAYER_DEVICE ); wxPoint* buffer = NULL; if( aColor < 0 ) // Used normal color or selected color { if( IsSelected() ) color = GetItemSelectedColor(); } else { color = aColor; } buffer = new wxPoint[ m_PolyPoints.size() ]; for( unsigned ii = 0; ii < m_PolyPoints.size(); ii++ ) { buffer[ii] = aTransform.TransformCoordinate( m_PolyPoints[ii] ) + aOffset; } FILL_T fill = aData ? NO_FILL : m_Fill; if( aColor >= 0 ) fill = NO_FILL; GRSetDrawMode( aDC, aDrawMode ); EDA_RECT* const clipbox = aPanel? aPanel->GetClipBox() : NULL; if( fill == FILLED_WITH_BG_BODYCOLOR ) GRPoly( clipbox, aDC, m_PolyPoints.size(), buffer, 1, GetPenSize(), (m_Flags & IS_MOVED) ? color : GetLayerColor( LAYER_DEVICE_BACKGROUND ), GetLayerColor( LAYER_DEVICE_BACKGROUND ) ); else if( fill == FILLED_SHAPE ) GRPoly( clipbox, aDC, m_PolyPoints.size(), buffer, 1, GetPenSize(), color, color ); else GRPoly( clipbox, aDC, m_PolyPoints.size(), buffer, 0, GetPenSize(), color, color ); delete[] buffer; /* Set to one (1) to draw bounding box around polyline to validate * bounding box calculation. */ #if 0 EDA_RECT bBox = GetBoundingBox(); bBox.RevertYAxis(); bBox = aTransform.TransformCoordinate( bBox ); bBox.Move( aOffset ); GRRect( clipbox, aDC, bBox, 0, LIGHTMAGENTA ); #endif }
void LIB_FIELD::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, EDA_COLOR_T aColor, GR_DRAWMODE aDrawMode, void* aData, const TRANSFORM& aTransform ) { wxPoint text_pos; int color; int linewidth = GetPenSize(); if( m_Bold ) linewidth = GetPenSizeForBold( m_Size.x ); else linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); if( ( m_Attributs & TEXT_NO_VISIBLE ) && ( aColor < 0 ) ) { color = GetInvisibleItemColor(); } else if( IsSelected() && ( aColor < 0 ) ) { color = GetItemSelectedColor(); } else { color = aColor; } if( color < 0 ) color = GetDefaultColor(); text_pos = aTransform.TransformCoordinate( m_Pos ) + aOffset; wxString text; if( aData ) text = *(wxString*)aData; else text = m_Text; GRSetDrawMode( aDC, aDrawMode ); EDA_RECT* clipbox = aPanel? aPanel->GetClipBox() : NULL; DrawGraphicText( clipbox, aDC, text_pos, (EDA_COLOR_T) color, text, m_Orient, m_Size, m_HJustify, m_VJustify, linewidth, m_Italic, m_Bold ); /* Set to one (1) to draw bounding box around field text to validate * bounding box calculation. */ #if 0 EDA_RECT bBox = GetBoundingBox(); EDA_RECT grBox; grBox.SetOrigin( aTransform.TransformCoordinate( bBox.GetOrigin() ) ); grBox.SetEnd( aTransform.TransformCoordinate( bBox.GetEnd() ) ); grBox.Move( aOffset ); GRRect( clipbox, aDC, grBox, 0, LIGHTMAGENTA ); #endif }
void LIB_RECTANGLE::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, EDA_COLOR_T aColor, GR_DRAWMODE aDrawMode, void* aData, const TRANSFORM& aTransform ) { wxPoint pos1, pos2; EDA_COLOR_T color = GetLayerColor( LAYER_DEVICE ); if( aColor < 0 ) // Used normal color or selected color { if( IsSelected() ) color = GetItemSelectedColor(); } else { color = aColor; } pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset; pos2 = aTransform.TransformCoordinate( m_End ) + aOffset; FILL_T fill = aData ? NO_FILL : m_Fill; if( aColor >= 0 ) fill = NO_FILL; GRSetDrawMode( aDC, aDrawMode ); EDA_RECT* const clipbox = aPanel? aPanel->GetClipBox() : NULL; if( fill == FILLED_WITH_BG_BODYCOLOR && !aData ) GRFilledRect( clipbox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, GetPenSize( ), (m_Flags & IS_MOVED) ? color : GetLayerColor( LAYER_DEVICE_BACKGROUND ), GetLayerColor( LAYER_DEVICE_BACKGROUND ) ); else if( m_Fill == FILLED_SHAPE && !aData ) GRFilledRect( clipbox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, GetPenSize(), color, color ); else GRRect( clipbox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, GetPenSize(), color ); /* Set to one (1) to draw bounding box around rectangle to validate * bounding box calculation. */ #if 0 EDA_RECT bBox = GetBoundingBox(); bBox.RevertYAxis(); bBox = aTransform.TransformCoordinate( bBox ); bBox.Move( aOffset ); GRRect( clipbox, aDC, bBox, 0, LIGHTMAGENTA ); #endif }
const EDA_RECT SCH_FIELD::GetBoundingBox() const { SCH_COMPONENT* parentComponent = (SCH_COMPONENT*) m_Parent; int linewidth = ( m_Thickness == 0 ) ? GetDefaultLineThickness() : m_Thickness; // We must pass the effective text thickness to GetTextBox // when calculating the bounding box linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); // Calculate the text bounding box: EDA_RECT rect; if( m_id == REFERENCE ) // multi units have one letter or more added to reference { SCH_FIELD text( *this ); // Make a local copy to change text // because GetBoundingBox() is const text.SetText( GetFullyQualifiedText() ); rect = text.GetTextBox( -1, linewidth ); } else rect = GetTextBox( -1, linewidth ); // Calculate the bounding box position relative to the component: wxPoint origin = parentComponent->GetPosition(); wxPoint pos = m_Pos - origin; wxPoint begin = rect.GetOrigin() - origin; wxPoint end = rect.GetEnd() - origin; RotatePoint( &begin, pos, m_Orient ); RotatePoint( &end, pos, m_Orient ); // Due to the Y axis direction, we must mirror the bounding box, // relative to the text position: begin.y -= pos.y; end.y -= pos.y; NEGATE( begin.y ); NEGATE( end.y ); begin.y += pos.y; end.y += pos.y; // Now, apply the component transform (mirror/rot) begin = parentComponent->GetTransform().TransformCoordinate( begin ); end = parentComponent->GetTransform().TransformCoordinate( end ); rect.SetOrigin( begin); rect.SetEnd( end); rect.Move( origin ); rect.Normalize(); return rect; }
void LIB_CIRCLE::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, COLOR4D aColor, GR_DRAWMODE aDrawMode, void* aData, const TRANSFORM& aTransform ) { wxPoint pos1; COLOR4D color = GetLayerColor( LAYER_DEVICE ); if( aColor == COLOR4D::UNSPECIFIED ) // Used normal color or selected color { if( IsSelected() ) color = GetItemSelectedColor(); } else { color = aColor; } pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset; GRSetDrawMode( aDC, aDrawMode ); FILL_T fill = aData ? NO_FILL : m_Fill; if( aColor != COLOR4D::UNSPECIFIED ) fill = NO_FILL; EDA_RECT* const clipbox = aPanel? aPanel->GetClipBox() : NULL; if( fill == FILLED_WITH_BG_BODYCOLOR ) GRFilledCircle( clipbox, aDC, pos1.x, pos1.y, m_Radius, GetPenSize(), (m_Flags & IS_MOVED) ? color : GetLayerColor( LAYER_DEVICE_BACKGROUND ), GetLayerColor( LAYER_DEVICE_BACKGROUND ) ); else if( fill == FILLED_SHAPE ) GRFilledCircle( clipbox, aDC, pos1.x, pos1.y, m_Radius, 0, color, color ); else GRCircle( clipbox, aDC, pos1.x, pos1.y, m_Radius, GetPenSize(), color ); /* Set to one (1) to draw bounding box around circle to validate bounding * box calculation. */ #if 0 EDA_RECT bBox = GetBoundingBox(); bBox.RevertYAxis(); bBox = aTransform.TransformCoordinate( bBox ); bBox.Move( aOffset ); GRRect( clipbox, aDC, bBox, 0, LIGHTMAGENTA ); #endif }
int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aDC ) { int error = 1; wxPoint LastPosOK; double min_cost, curr_cost, Score; bool TstOtherSide; DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)aFrame->GetDisplayOptions(); BOARD* brd = aFrame->GetBoard(); aModule->CalculateBoundingBox(); bool showRats = displ_opts->m_Show_Module_Ratsnest; displ_opts->m_Show_Module_Ratsnest = false; brd->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK; aFrame->SetMsgPanel( aModule ); LastPosOK = RoutingMatrix.m_BrdBox.GetOrigin(); wxPoint mod_pos = aModule->GetPosition(); EDA_RECT fpBBox = aModule->GetFootprintRect(); // Move fpBBox to have the footprint position at (0,0) fpBBox.Move( -mod_pos ); wxPoint fpBBoxOrg = fpBBox.GetOrigin(); // Calculate the limit of the footprint position, relative // to the routing matrix area wxPoint xylimit = RoutingMatrix.m_BrdBox.GetEnd() - fpBBox.GetEnd(); wxPoint initialPos = RoutingMatrix.m_BrdBox.GetOrigin() - fpBBoxOrg; // Stay on grid. initialPos.x -= initialPos.x % RoutingMatrix.m_GridRouting; initialPos.y -= initialPos.y % RoutingMatrix.m_GridRouting; CurrPosition = initialPos; // Undraw the current footprint aModule->DrawOutlinesWhenMoving( aFrame->GetCanvas(), aDC, wxPoint( 0, 0 ) ); g_Offset_Module = mod_pos - CurrPosition; /* Examine pads, and set TstOtherSide to true if a footprint * has at least 1 pad through. */ TstOtherSide = false; if( RoutingMatrix.m_RoutingLayersCount > 1 ) { LSET other( aModule->GetLayer() == B_Cu ? F_Cu : B_Cu ); for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() ) { if( !( pad->GetLayerSet() & other ).any() ) continue; TstOtherSide = true; break; } } // Draw the initial bounding box position EDA_COLOR_T color = BROWN; fpBBox.SetOrigin( fpBBoxOrg + CurrPosition ); draw_FootprintRect(aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color); min_cost = -1.0; aFrame->SetStatusText( wxT( "Score ??, pos ??" ) ); for( ; CurrPosition.x < xylimit.x; CurrPosition.x += RoutingMatrix.m_GridRouting ) { wxYield(); if( aFrame->GetCanvas()->GetAbortRequest() ) { if( IsOK( aFrame, _( "OK to abort?" ) ) ) { displ_opts->m_Show_Module_Ratsnest = showRats; return ESC; } else aFrame->GetCanvas()->SetAbortRequest( false ); } CurrPosition.y = initialPos.y; for( ; CurrPosition.y < xylimit.y; CurrPosition.y += RoutingMatrix.m_GridRouting ) { // Erase traces. draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color ); fpBBox.SetOrigin( fpBBoxOrg + CurrPosition ); g_Offset_Module = mod_pos - CurrPosition; int keepOutCost = TstModuleOnBoard( brd, aModule, TstOtherSide ); // Draw at new place color = keepOutCost >= 0 ? BROWN : RED; draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color ); if( keepOutCost >= 0 ) // i.e. if the module can be put here { error = 0; aFrame->build_ratsnest_module( aModule ); curr_cost = compute_Ratsnest_PlaceModule( brd ); Score = curr_cost + keepOutCost; if( (min_cost >= Score ) || (min_cost < 0 ) ) { LastPosOK = CurrPosition; min_cost = Score; wxString msg; msg.Printf( wxT( "Score %g, pos %s, %s" ), min_cost, GetChars( ::CoordinateToString( LastPosOK.x ) ), GetChars( ::CoordinateToString( LastPosOK.y ) ) ); aFrame->SetStatusText( msg ); } } } } // erasing the last traces GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN ); displ_opts->m_Show_Module_Ratsnest = showRats; // Regeneration of the modified variable. CurrPosition = LastPosOK; brd->m_Status_Pcb &= ~( RATSNEST_ITEM_LOCAL_OK | LISTE_PAD_OK ); MinCout = min_cost; return error; }
EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const { EDA_RECT rect; wxPoint pos; wxArrayString strings; wxString text = GetShownText(); int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness; int linecount = 1; if( m_MultilineAllowed ) { wxStringSplit( text, strings, '\n' ); if ( strings.GetCount() ) // GetCount() == 0 for void strings { if( aLine >= 0 && (aLine < (int)strings.GetCount()) ) text = strings.Item( aLine ); else text = strings.Item( 0 ); linecount = strings.GetCount(); } } // calculate the H and V size int dx = LenSize( text ); int dy = GetInterline( aThickness ); // Creates bounding box (rectangle) for an horizontal text wxSize textsize = wxSize( dx, dy ); if( aInvertY ) rect.SetOrigin( m_Pos.x, -m_Pos.y ); else rect.SetOrigin( m_Pos ); // extra dy interval for letters like j and y and ] int extra_dy = dy - m_Size.y; rect.Move( wxPoint( 0, -extra_dy / 2 ) ); // move origin by the half extra interval // for multiline texts and aLine < 0, merge all rectangles if( m_MultilineAllowed && aLine < 0 ) { for( unsigned ii = 1; ii < strings.GetCount(); ii++ ) { text = strings.Item( ii ); dx = LenSize( text ); textsize.x = std::max( textsize.x, dx ); textsize.y += dy; } } rect.SetSize( textsize ); /* Now, calculate the rect origin, according to text justification * At this point the rectangle origin is the text origin (m_Pos). * This is true only for left and top text justified texts (using top to bottom Y axis * orientation). and must be recalculated for others justifications * also, note the V justification is relative to the first line */ switch( m_HJustify ) { case GR_TEXT_HJUSTIFY_LEFT: if( m_Mirror ) rect.SetX( rect.GetX() - rect.GetWidth() ); break; case GR_TEXT_HJUSTIFY_CENTER: rect.SetX( rect.GetX() - (rect.GetWidth() / 2) ); break; case GR_TEXT_HJUSTIFY_RIGHT: if( !m_Mirror ) rect.SetX( rect.GetX() - rect.GetWidth() ); break; } dy = m_Size.y + thickness; switch( m_VJustify ) { case GR_TEXT_VJUSTIFY_TOP: break; case GR_TEXT_VJUSTIFY_CENTER: rect.SetY( rect.GetY() - ( dy / 2) ); break; case GR_TEXT_VJUSTIFY_BOTTOM: rect.SetY( rect.GetY() - dy ); break; } if( linecount > 1 ) { int yoffset; linecount -= 1; switch( m_VJustify ) { case GR_TEXT_VJUSTIFY_TOP: break; case GR_TEXT_VJUSTIFY_CENTER: yoffset = linecount * GetInterline() / 2; rect.SetY( rect.GetY() - yoffset ); break; case GR_TEXT_VJUSTIFY_BOTTOM: yoffset = linecount * GetInterline( aThickness ); rect.SetY( rect.GetY() - yoffset ); break; } } rect.Inflate( thickness / 2 ); rect.Normalize(); // Make h and v sizes always >= 0 return rect; }
void BOARD_PRINTOUT_CONTROLLER::DrawPage() { wxPoint offset; double userscale; EDA_RECT boardBoundingBox; EDA_RECT drawRect; wxDC* dc = GetDC(); BASE_SCREEN* screen = m_Parent->GetScreen(); bool printMirror = m_PrintParams.m_PrintMirror; wxSize pageSizeIU = m_Parent->GetPageSizeIU(); wxBusyCursor dummy; #if defined (PCBNEW) BOARD * brd = ((PCB_BASE_FRAME*) m_Parent)->GetBoard(); boardBoundingBox = brd->ComputeBoundingBox(); wxString titleblockFilename = brd->GetFileName(); #elif defined (GERBVIEW) boardBoundingBox = ((GERBVIEW_FRAME*) m_Parent)->GetGerberLayoutBoundingBox(); wxString titleblockFilename; // TODO see if we uses the gerber file name #else #error BOARD_PRINTOUT_CONTROLLER::DrawPage() works only for PCBNEW or GERBVIEW #endif // Use the page size as the drawing area when the board is shown or the user scale // is less than 1. if( m_PrintParams.PrintBorderAndTitleBlock() ) boardBoundingBox = EDA_RECT( wxPoint( 0, 0 ), pageSizeIU ); wxLogTrace( tracePrinting, wxT( "Drawing bounding box: x=%d, y=%d, w=%d, h=%d" ), boardBoundingBox.GetX(), boardBoundingBox.GetY(), boardBoundingBox.GetWidth(), boardBoundingBox.GetHeight() ); // Compute the PCB size in internal units userscale = m_PrintParams.m_PrintScale; if( m_PrintParams.m_PrintScale == 0 ) // fit in page option { if(boardBoundingBox.GetWidth() && boardBoundingBox.GetHeight()) { int margin = Millimeter2iu( 10.0 ); // add a margin around the drawings double scaleX = (double)(pageSizeIU.x - (2 * margin)) / boardBoundingBox.GetWidth(); double scaleY = (double)(pageSizeIU.y - (2 * margin)) / boardBoundingBox.GetHeight(); userscale = (scaleX < scaleY) ? scaleX : scaleY; } else userscale = 1.0; } wxSize scaledPageSize = pageSizeIU; drawRect.SetSize( scaledPageSize ); scaledPageSize.x = wxRound( scaledPageSize.x / userscale ); scaledPageSize.y = wxRound( scaledPageSize.y / userscale ); if( m_PrintParams.m_PageSetupData ) { wxLogTrace( tracePrinting, wxT( "Fit size to page margins: x=%d, y=%d" ), scaledPageSize.x, scaledPageSize.y ); // Always scale to the size of the paper. FitThisSizeToPageMargins( scaledPageSize, *m_PrintParams.m_PageSetupData ); } // Compute Accurate scale 1 if( m_PrintParams.m_PrintScale == 1.0 ) { // We want a 1:1 scale, regardless the page setup // like page size, margin ... MapScreenSizeToPaper(); // set best scale and offset (scale is not used) int w, h; GetPPIPrinter( &w, &h ); double accurate_Xscale = (double) w / (IU_PER_MILS*1000); double accurate_Yscale = (double) h / (IU_PER_MILS*1000); 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 *= (double)PlotAreaSize.x / w; accurate_Yscale *= (double)PlotAreaSize.y / h; } // Fine scale adjust accurate_Xscale *= m_PrintParams.m_XScaleAdjust; accurate_Yscale *= m_PrintParams.m_YScaleAdjust; // Set print scale for 1:1 exact scale dc->SetUserScale( accurate_Xscale, accurate_Yscale ); } // Get the final size of the DC in pixels wxSize PlotAreaSizeInPixels; dc->GetSize( &PlotAreaSizeInPixels.x, &PlotAreaSizeInPixels.y ); wxLogTrace( tracePrinting, wxT( "Plot area in pixels: x=%d, y=%d" ), PlotAreaSizeInPixels.x, PlotAreaSizeInPixels.y ); double scalex, scaley; dc->GetUserScale( &scalex, &scaley ); wxLogTrace( tracePrinting, wxT( "DC user scale: x=%g, y=%g" ), scalex, scaley ); wxSize PlotAreaSizeInUserUnits; PlotAreaSizeInUserUnits.x = KiROUND( PlotAreaSizeInPixels.x / scalex ); PlotAreaSizeInUserUnits.y = KiROUND( PlotAreaSizeInPixels.y / scaley ); wxLogTrace( tracePrinting, wxT( "Scaled plot area in user units: x=%d, y=%d" ), PlotAreaSizeInUserUnits.x, PlotAreaSizeInUserUnits.y ); // 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 to the center of the page: if( m_Parent->IsType( MODULE_EDITOR_FRAME_TYPE ) ) { boardBoundingBox.Move( wxPoint( pageSizeIU.x/2, pageSizeIU.y/2 ) ); } // In some cases the plot origin is the centre of the board outline rather than the center // of the selected paper size. if( m_PrintParams.CenterOnBoardOutline() ) { // Here we are only drawing the board and it's contents. drawRect = boardBoundingBox; offset.x += wxRound( (double) -scaledPageSize.x / 2.0 ); offset.y += wxRound( (double) -scaledPageSize.y / 2.0 ); wxPoint center = boardBoundingBox.Centre(); if( printMirror ) { // Calculate the mirrored center of the board. center.x = m_Parent->GetPageSizeIU().x - boardBoundingBox.Centre().x; } offset += center; } GRResetPenAndBrush( dc ); 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 ) ) ); screen->m_IsPrinting = true; EDA_COLOR_T bg_color = g_DrawBgColor; // Print frame reference, if reqquested, before if( m_PrintParams.m_Print_Black_and_White ) GRForceBlackPen( true ); if( m_PrintParams.PrintBorderAndTitleBlock() ) m_Parent->DrawWorkSheet( dc, screen, m_PrintParams.m_PenDefaultSize, IU_PER_MILS, titleblockFilename ); if( printMirror ) { // To plot mirror, we reverse the x axis, and modify the plot x origin dc->SetAxisOrientation( false, false); /* Plot offset x is moved by the x 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 X axis is reversed, therefore the plotting area * is the x coordinate values from - PlotAreaSize.x to 0 */ int x_dc_offset = PlotAreaSizeInPixels.x; x_dc_offset = KiROUND( x_dc_offset * userscale ); dc->SetDeviceOrigin( x_dc_offset, 0 ); wxLogTrace( tracePrinting, wxT( "Device origin: x=%d, y=%d" ), x_dc_offset, 0 ); panel->SetClipBox( EDA_RECT( wxPoint( -MAX_VALUE/2, -MAX_VALUE/2 ), panel->GetClipBox()->GetSize() ) ); } // screen->m_DrawOrg = offset; dc->SetLogicalOrigin( offset.x, offset.y ); wxLogTrace( tracePrinting, wxT( "Logical origin: x=%d, y=%d" ), offset.x, offset.y ); #if defined(wxUSE_LOG_TRACE) && defined( DEBUG ) wxRect paperRect = GetPaperRectPixels(); wxLogTrace( tracePrinting, wxT( "Paper rectangle: left=%d, top=%d, " "right=%d, bottom=%d" ), paperRect.GetLeft(), paperRect.GetTop(), paperRect.GetRight(), paperRect.GetBottom() ); int devLeft = dc->LogicalToDeviceX( drawRect.GetX() ); int devTop = dc->LogicalToDeviceY( drawRect.GetY() ); int devRight = dc->LogicalToDeviceX( drawRect.GetRight() ); int devBottom = dc->LogicalToDeviceY( drawRect.GetBottom() ); wxLogTrace( tracePrinting, wxT( "Final device rectangle: left=%d, top=%d, " "right=%d, bottom=%d\n" ), devLeft, devTop, devRight, devBottom ); #endif 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 background * 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 ); } else GRForceBlackPen( true ); #if defined (GERBVIEW) // In B&W mode, do not force black pen for Gerbview // because negative objects need a white pen, not a black pen // B&W mode is handled in print page GRForceBlackPen( false ); #endif m_Parent->PrintPage( dc, m_PrintParams.m_PrintMaskLayer, printMirror, &m_PrintParams ); g_DrawBgColor = bg_color; screen->m_IsPrinting = false; panel->SetClipBox( tmp ); GRForceBlackPen( false ); }
void LIB_TEXT::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, COLOR4D aColor, GR_DRAWMODE aDrawMode, void* aData, const TRANSFORM& aTransform ) { COLOR4D color = GetDefaultColor(); if( aColor == COLOR4D::UNSPECIFIED ) // Used normal color or selected color { if( IsSelected() ) color = GetItemSelectedColor(); } else { color = aColor; } GRSetDrawMode( aDC, aDrawMode ); /* Calculate the text orientation, according to the component * orientation/mirror (needed when draw text in schematic) */ int orient = GetTextAngle(); if( aTransform.y1 ) // Rotate component 90 degrees. { if( orient == TEXT_ANGLE_HORIZ ) orient = TEXT_ANGLE_VERT; else orient = TEXT_ANGLE_HORIZ; } /* Calculate the text justification, according to the component * orientation/mirror this is a bit complicated due to cumulative * calculations: * - numerous cases (mirrored or not, rotation) * - the DrawGraphicText function recalculate also H and H justifications * according to the text orientation. * - When a component is mirrored, the text is not mirrored and * justifications are complicated to calculate * so the more easily way is to use no justifications ( Centered text ) * and use GetBoundaryBox to know the text coordinate considered as centered */ EDA_RECT bBox = GetBoundingBox(); // convert coordinates from draw Y axis to libedit Y axis: bBox.RevertYAxis(); wxPoint txtpos = bBox.Centre(); // Calculate pos according to mirror/rotation. txtpos = aTransform.TransformCoordinate( txtpos ) + aOffset; EDA_RECT* clipbox = aPanel? aPanel->GetClipBox() : NULL; DrawGraphicText( clipbox, aDC, txtpos, color, GetShownText(), orient, GetTextSize(), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, GetPenSize(), IsItalic(), IsBold() ); /* Enable this to draw the bounding box around the text field to validate * the bounding box calculations. */ #if 0 // bBox already uses libedit Y axis. bBox = aTransform.TransformCoordinate( bBox ); bBox.Move( aOffset ); GRRect( clipbox, aDC, bBox, 0, LIGHTMAGENTA ); #endif }
void LIB_TEXT::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform ) { int color = GetDefaultColor(); if( aColor < 0 ) // Used normal color or selected color { if( IsSelected() ) color = g_ItemSelectetColor; } else { color = aColor; } GRSetDrawMode( aDC, aDrawMode ); /* Calculate the text orientation, according to the component * orientation/mirror (needed when draw text in schematic) */ int orient = m_Orient; if( aTransform.y1 ) // Rotate component 90 degrees. { if( orient == TEXT_ORIENT_HORIZ ) orient = TEXT_ORIENT_VERT; else orient = TEXT_ORIENT_HORIZ; } /* Calculate the text justification, according to the component * orientation/mirror this is a bit complicated due to cumulative * calculations: * - numerous cases (mirrored or not, rotation) * - the DrawGraphicText function recalculate also H and H justifications * according to the text orientation. * - When a component is mirrored, the text is not mirrored and * justifications are complicated to calculate * so the more easily way is to use no justifications ( Centered text ) * and use GetBoundaryBox to know the text coordinate considered as centered */ EDA_RECT bBox = GetBoundingBox(); wxPoint txtpos = bBox.Centre(); // Calculate pos accordint to mirror/rotation. txtpos = aTransform.TransformCoordinate( txtpos ) + aOffset; DrawGraphicText( aPanel, aDC, txtpos, (EDA_Colors) color, m_Text, orient, m_Size, GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, GetPenSize(), m_Italic, m_Bold ); /* Enable this to draw the bounding box around the text field to validate * the bounding box calculations. */ #if 0 EDA_RECT grBox; grBox.SetOrigin( aTransform.TransformCoordinate( bBox.GetOrigin() ) ); grBox.SetEnd( aTransform.TransformCoordinate( bBox.GetEnd() ) ); grBox.Move( aOffset ); GRRect( aPanel->GetClipBox(), aDC, grBox, 0, LIGHTMAGENTA ); #endif }
void LIB_ARC::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, COLOR4D aColor, GR_DRAWMODE aDrawMode, void* aData, const TRANSFORM& aTransform ) { // Don't draw the arc until the end point is selected. Only the edit indicators // get drawn at this time. if( IsNew() && m_lastEditState == 1 ) return; wxPoint pos1, pos2, posc; COLOR4D color = GetLayerColor( LAYER_DEVICE ); if( aColor == COLOR4D::UNSPECIFIED ) // Used normal color or selected color { if( IsSelected() ) color = GetItemSelectedColor(); } else { color = aColor; } pos1 = aTransform.TransformCoordinate( m_ArcEnd ) + aOffset; pos2 = aTransform.TransformCoordinate( m_ArcStart ) + aOffset; posc = aTransform.TransformCoordinate( m_Pos ) + aOffset; int pt1 = m_t1; int pt2 = m_t2; bool swap = aTransform.MapAngles( &pt1, &pt2 ); if( swap ) { std::swap( pos1.x, pos2.x ); std::swap( pos1.y, pos2.y ); } GRSetDrawMode( aDC, aDrawMode ); FILL_T fill = aData ? NO_FILL : m_Fill; if( aColor != COLOR4D::UNSPECIFIED ) fill = NO_FILL; EDA_RECT* const clipbox = aPanel? aPanel->GetClipBox() : NULL; if( fill == FILLED_WITH_BG_BODYCOLOR ) { GRFilledArc( clipbox, aDC, posc.x, posc.y, pt1, pt2, m_Radius, GetPenSize( ), (m_Flags & IS_MOVED) ? color : GetLayerColor( LAYER_DEVICE_BACKGROUND ), GetLayerColor( LAYER_DEVICE_BACKGROUND ) ); } else if( fill == FILLED_SHAPE && !aData ) { GRFilledArc( clipbox, aDC, posc.x, posc.y, pt1, pt2, m_Radius, color, color ); } else { #ifdef DRAW_ARC_WITH_ANGLE GRArc( clipbox, aDC, posc.x, posc.y, pt1, pt2, m_Radius, GetPenSize(), color ); #else GRArc1( clipbox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, posc.x, posc.y, GetPenSize(), color ); #endif } /* Set to one (1) to draw bounding box around arc to validate bounding box * calculation. */ #if 0 EDA_RECT bBox = GetBoundingBox(); bBox.RevertYAxis(); bBox = aTransform.TransformCoordinate( bBox ); bBox.Move( aOffset ); GRRect( clipbox, aDC, bBox, 0, LIGHTMAGENTA ); #endif }
/* * 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 ); }