/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013 CERN * @author Tomasz Wlostowski * @author Maciej Suminski * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KiGfx; PCB_RENDER_SETTINGS::PCB_RENDER_SETTINGS() { Update(); } void PCB_RENDER_SETTINGS::ImportLegacyColors( COLORS_DESIGN_SETTINGS* aSettings ) { for( int i = 0; i < LAYER_COUNT; i++ ) { m_layerColors[i] = m_legacyColorMap[aSettings->GetLayerColor( i )]; } for( int i = 0; i < END_PCB_VISIBLE_LIST; i++ ) { m_itemColors[i] = m_legacyColorMap[aSettings->GetItemColor( i )]; } m_itemColors[VIA_HOLES_VISIBLE] = COLOR4D( 0.5f, 0.4f, 0.0f, 1.0f ); m_itemColors[PAD_HOLES_VISIBLE] = COLOR4D( 0.0f, 0.5f, 0.5f, 1.0f ); m_itemColors[VIAS_VISIBLE] = COLOR4D( 0.7f, 0.7f, 0.7f, 1.0f ); m_itemColors[PADS_VISIBLE] = COLOR4D( 0.7f, 0.7f, 0.7f, 1.0f ); Update(); } void PCB_RENDER_SETTINGS::Update() { // Calculate darkened/highlighted variants of layer colors for( int i = 0; i < LAYER_COUNT; i++ ) { m_layerColors[i].a = m_layerOpacity; m_layerColorsHi[i] = m_layerColors[i].Highlighted( m_highlightFactor ); m_layerColorsDark[i] = m_layerColors[i].Darkened( 1.0 - m_highlightFactor ); m_layerColorsSel[i] = m_layerColors[i].Highlighted( m_selectFactor ); } for( int i = 0; i < END_PCB_VISIBLE_LIST; i++ ) { m_itemColors[i].a = m_layerOpacity; m_itemColorsHi[i] = m_itemColors[i].Highlighted( m_highlightFactor ); m_itemColorsDark[i] = m_itemColors[i].Darkened( 1.0 - m_highlightFactor ); m_itemColorsSel[i] = m_itemColors[i].Highlighted( m_selectFactor ); } m_hiContrastColor = COLOR4D( m_hiContrastFactor, m_hiContrastFactor, m_highlightFactor, m_layerOpacity ); } PCB_PAINTER::PCB_PAINTER( GAL* aGal ) : PAINTER( aGal ) { } const COLOR4D& PCB_PAINTER::getLayerColor( int aLayer, int aNetCode ) const { // For item layers (vias, texts, and so on) if( aLayer >= LAYER_COUNT ) return getItemColor( aLayer - LAYER_COUNT, aNetCode ); if( m_pcbSettings->m_hiContrastEnabled && m_pcbSettings->m_activeLayer != aLayer ) { return m_pcbSettings->m_hiContrastColor; } else if( m_pcbSettings->m_highlightEnabled ) { if( aNetCode == m_pcbSettings->m_highlightNetcode ) { return m_pcbSettings->m_layerColorsHi[aLayer]; } else { return m_pcbSettings->m_layerColorsDark[aLayer]; } } else { return m_pcbSettings->m_layerColors[aLayer]; } } const COLOR4D& PCB_PAINTER::getItemColor( int aItemType, int aNetCode ) const { // if(aNetCode == m_settings->m_hiContrastEnabled) // return m_settings->m_itemColorsHi[ aItemType ]; if( m_pcbSettings->m_highlightEnabled ) { if( aNetCode == m_pcbSettings->m_highlightNetcode ) { return m_pcbSettings->m_itemColorsHi[aItemType]; } else { return m_pcbSettings->m_itemColorsDark[aItemType]; } } else { return m_pcbSettings->m_itemColors[aItemType]; } } bool PCB_PAINTER::Draw( const EDA_ITEM* aItem, int aLayer ) { // the "cast" applied in here clarifies which overloaded draw() is called switch( aItem->Type() ) { case PCB_ZONE_T: case PCB_TRACE_T: draw( (TRACK*) aItem ); break; case PCB_VIA_T: draw( (SEGVIA*) aItem, aLayer ); break; case PCB_PAD_T: draw( (D_PAD*) aItem, aLayer ); break; case PCB_LINE_T: case PCB_MODULE_EDGE_T: draw( (DRAWSEGMENT*) aItem ); break; case PCB_TEXT_T: draw( (TEXTE_PCB*) aItem ); break; case PCB_MODULE_TEXT_T: draw( (TEXTE_MODULE*) aItem, aLayer ); break; case PCB_ZONE_AREA_T: draw( (ZONE_CONTAINER*) aItem ); break; default: // Painter does not know how to draw the object return false; break; } return true; } void PCB_PAINTER::draw( const TRACK* aTrack ) { VECTOR2D start( aTrack->GetStart() ); VECTOR2D end( aTrack->GetEnd() ); COLOR4D strokeColor = getLayerColor( aTrack->GetLayer(), aTrack->GetNet() ); m_gal->SetLineCap( LINE_CAP_ROUND ); m_gal->SetLineJoin( LINE_JOIN_ROUND ); m_gal->SetLineWidth( aTrack->GetWidth() ); m_gal->SetStrokeColor( strokeColor ); m_gal->DrawLine( start, end ); } void PCB_PAINTER::draw( const SEGVIA* aVia, int aLayer ) { VECTOR2D center( aVia->GetStart() ); double radius; COLOR4D fillColor; // Choose drawing settings depending on if we are drawing via's pad or hole if( aLayer == ITEM_GAL_LAYER( VIAS_VISIBLE ) ) { radius = aVia->GetWidth() / 2.0f; } else if( aLayer == ITEM_GAL_LAYER( VIA_HOLES_VISIBLE ) ) { radius = aVia->GetDrillValue() / 2.0f; } else return; fillColor = getLayerColor( aLayer, aVia->GetNet() ); m_gal->SetIsStroke( false ); m_gal->SetIsFill( true ); m_gal->SetFillColor( fillColor ); m_gal->DrawCircle( center, radius ); } void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) { COLOR4D fillColor; VECTOR2D size; PAD_SHAPE_T shape; double m, n; m_gal->Save(); m_gal->Translate( VECTOR2D( aPad->GetPosition() ) ); m_gal->Rotate( -aPad->GetOrientation() * M_PI / 1800.0 ); // orientation is in tenths of degree // Choose drawing settings depending on if we are drawing a pad itself or a hole if( aLayer == ITEM_GAL_LAYER( PAD_HOLES_VISIBLE ) ) { // Drawing hole size = VECTOR2D( aPad->GetDrillSize() ) / 2.0f; shape = aPad->GetDrillShape(); } else { // Drawing every kind of pad m_gal->Translate( VECTOR2D( aPad->GetOffset() ) ); size = VECTOR2D( aPad->GetSize() ) / 2.0f; shape = aPad->GetShape(); } fillColor = getLayerColor( aLayer, aPad->GetNet() ); m_gal->SetIsFill( true ); m_gal->SetIsStroke( false ); m_gal->SetFillColor( fillColor ); switch( shape ) { case PAD_OVAL: if( size.y >= size.x ) { m = ( size.y - size.x ); n = size.x; m_gal->DrawCircle( VECTOR2D( 0, -m ), n ); m_gal->DrawCircle( VECTOR2D( 0, m ), n ); m_gal->DrawRectangle( VECTOR2D( -n, -m ), VECTOR2D( n, m ) ); } else { m = ( size.x - size.y ); n = size.y; m_gal->DrawCircle( VECTOR2D( -m, 0 ), n ); m_gal->DrawCircle( VECTOR2D( m, 0 ), n ); m_gal->DrawRectangle( VECTOR2D( -m, -n ), VECTOR2D( m, n ) ); } break; case PAD_RECT: case PAD_TRAPEZOID: m_gal->DrawRectangle( VECTOR2D( -size.x, -size.y ), VECTOR2D( size.x, size.y ) ); break; case PAD_CIRCLE: m_gal->DrawCircle( VECTOR2D( 0.0, 0.0 ), size.x ); break; case PAD_OCTAGON: // it is not used anywhere, neither you can set it using pcbnew.. case PAD_NONE: break; } m_gal->Restore(); } void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment ) { COLOR4D strokeColor = getLayerColor( aSegment->GetLayer(), 0 ); std::deque pointsList; m_gal->SetIsFill( false ); m_gal->SetIsStroke( true ); m_gal->SetStrokeColor( strokeColor ); m_gal->SetLineWidth( aSegment->GetWidth() ); m_gal->SetLineCap( LINE_CAP_ROUND ); m_gal->SetLineJoin( LINE_JOIN_ROUND ); switch( aSegment->GetShape() ) { case S_SEGMENT: m_gal->DrawLine( VECTOR2D( aSegment->GetStart() ), VECTOR2D( aSegment->GetEnd() ) ); break; case S_RECT: m_gal->SetLineCap( LINE_CAP_SQUARED ); m_gal->SetLineJoin( LINE_JOIN_BEVEL ); m_gal->DrawLine( VECTOR2D( aSegment->GetStart() ), VECTOR2D( aSegment->GetEnd() ) ); break; case S_ARC: m_gal->DrawArc( VECTOR2D( aSegment->GetCenter() ), aSegment->GetRadius(), aSegment->GetArcAngleStart() * M_PI / 1800.0, ( aSegment->GetArcAngleStart() + aSegment->GetAngle() ) * M_PI / 1800.0 ); break; case S_CIRCLE: m_gal->DrawCircle( VECTOR2D( aSegment->GetCenter() ), aSegment->GetRadius() ); break; case S_POLYGON: std::copy( aSegment->GetPolyPoints().begin(), aSegment->GetPolyPoints().end(), std::back_inserter( pointsList ) ); m_gal->DrawPolygon( pointsList ); break; case S_CURVE: m_gal->DrawCurve( VECTOR2D( aSegment->GetStart() ), VECTOR2D( aSegment->GetBezControl1() ), VECTOR2D( aSegment->GetBezControl2() ), VECTOR2D( aSegment->GetEnd() ) ); break; case S_LAST: break; } } void PCB_PAINTER::draw( const TEXTE_PCB* aText ) { COLOR4D strokeColor = getLayerColor( aText->GetLayer(), 0 ); VECTOR2D position( aText->GetTextPosition().x, aText->GetTextPosition().y ); double orientation = aText->GetOrientation() * M_PI / 1800.0; m_gal->SetStrokeColor( strokeColor ); m_gal->SetLineWidth( aText->GetThickness() ); m_stroke_font->LoadAttributes( aText ); m_stroke_font->Draw( std::string( aText->GetText().mb_str() ), position, orientation ); } void PCB_PAINTER::draw( const TEXTE_MODULE* aText, int aLayer ) { COLOR4D strokeColor = getLayerColor( aLayer, 0 ); m_gal->SetStrokeColor( strokeColor ); m_gal->SetLineWidth( aText->GetThickness() ); m_stroke_font->LoadAttributes( aText ); m_stroke_font->Draw( std::string( aText->GetText().mb_str() ), VECTOR2D( aText->GetTextPosition().x, aText->GetTextPosition().y), aText->GetDrawRotation() * M_PI / 1800.0 ); } void PCB_PAINTER::draw( const ZONE_CONTAINER* aContainer ) { COLOR4D fillColor = getLayerColor( aContainer->GetLayer(), aContainer->GetNet() ); std::vector::iterator polyIterator; std::vector polyPoints = aContainer->GetFilledPolysList(); std::deque corners; m_gal->SetLineCap( LINE_CAP_ROUND ); m_gal->SetLineJoin( LINE_JOIN_ROUND ); m_gal->SetFillColor( fillColor ); m_gal->SetStrokeColor( fillColor ); m_gal->SetIsFill( aContainer->IsFilled() ); m_gal->SetIsStroke( true ); m_gal->SetLineWidth( aContainer->GetThermalReliefCopperBridge() / 2.0 ); // FIXME implement hatch mode for( polyIterator = polyPoints.begin(); polyIterator != polyPoints.end(); polyIterator++ ) { // Find out all of polygons and then draw them if( !polyIterator->end_contour ) { corners.push_back( VECTOR2D( *polyIterator ) ); } else { m_gal->DrawPolygon( corners ); m_gal->DrawPolyline( corners ); corners.clear(); } } }