const EDA_RECT SCH_TEXT::GetBoundingBox() const { // We must pass the effective text thickness to GetTextBox // when calculating the bounding box int linewidth = GetThickness() == 0 ? GetDefaultLineThickness() : GetThickness(); linewidth = Clamp_Text_PenSize( linewidth, GetTextSize(), IsBold() ); EDA_RECT rect = GetTextBox( -1, linewidth ); if( GetTextAngle() != 0 ) // Rotate rect { wxPoint pos = rect.GetOrigin(); wxPoint end = rect.GetEnd(); RotatePoint( &pos, GetTextPos(), GetTextAngle() ); RotatePoint( &end, GetTextPos(), GetTextAngle() ); rect.SetOrigin( pos ); rect.SetEnd( end ); } rect.Normalize(); return rect; }
const EDA_RECT TEXTE_PCB::GetBoundingBox() const { EDA_RECT rect = GetTextBox( -1, -1 ); if( GetTextAngle() ) rect = rect.GetBoundingBoxRotated( GetTextPos(), GetTextAngle() ); return rect; }
void SCH_TEXT::Plot( PLOTTER* aPlotter ) { static std::vector <wxPoint> Poly; COLOR4D color = GetLayerColor( GetLayer() ); int tmp = GetThickness(); int thickness = GetPenSize(); // Two thicknesses are set here: // The first is for EDA_TEXT, which controls the interline spacing based on text thickness // The second is for the output that sets the actual stroke size SetThickness( thickness ); aPlotter->SetCurrentLineWidth( thickness ); if( IsMultilineAllowed() ) { std::vector<wxPoint> positions; wxArrayString strings_list; wxStringSplit( GetShownText(), strings_list, '\n' ); positions.reserve( strings_list.Count() ); GetPositionsOfLinesOfMultilineText(positions, (int) strings_list.Count() ); for( unsigned ii = 0; ii < strings_list.Count(); ii++ ) { wxPoint textpos = positions[ii] + GetSchematicTextOffset(); wxString& txt = strings_list.Item( ii ); aPlotter->Text( textpos, color, txt, GetTextAngle(), GetTextSize(), GetHorizJustify(), GetVertJustify(), thickness, IsItalic(), IsBold() ); } } else { wxPoint textpos = GetTextPos() + GetSchematicTextOffset(); aPlotter->Text( textpos, color, GetShownText(), GetTextAngle(), GetTextSize(), GetHorizJustify(), GetVertJustify(), thickness, IsItalic(), IsBold() ); } // Draw graphic symbol for global or hierarchical labels CreateGraphicShape( Poly, GetTextPos() ); aPlotter->SetCurrentLineWidth( GetPenSize() ); if( Poly.size() ) aPlotter->PlotPoly( Poly, NO_FILL ); SetThickness( tmp ); }
bool LIB_FIELD::HitTest( const wxPoint& aPosition, int aAccuracy ) const { // Because HitTest is mainly used to select the field return false if it is void if( IsVoid() ) return false; // Build a temporary copy of the text for hit testing EDA_TEXT tmp_text( *this ); // Reference designator text has one or 2 additional character (displays // U? or U?A) if( m_id == REFERENCE ) { wxString extended_text = tmp_text.GetText(); extended_text.Append('?'); const LIB_PART* parent = static_cast<const LIB_PART*>( m_Parent ); if ( parent && ( parent->GetUnitCount() > 1 ) ) extended_text.Append('A'); tmp_text.SetText( extended_text ); } tmp_text.SetTextPos( DefaultTransform.TransformCoordinate( GetTextPos() ) ); /* The text orientation may need to be flipped if the * transformation matrix causes xy axes to be flipped. * this simple algo works only for schematic matrix (rot 90 or/and mirror) */ bool t1 = ( DefaultTransform.x1 != 0 ) ^ ( GetTextAngle() != 0 ); tmp_text.SetTextAngle( t1 ? TEXT_ANGLE_HORIZ : TEXT_ANGLE_VERT ); return tmp_text.TextHitTest( aPosition, aAccuracy ); }
void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( SHAPE_POLY_SET* aCornerBuffer, int aClearanceValue ) const { // Oh dear. When in UTF-8 mode, wxString puts string iterators in a linked list, and // that linked list is not thread-safe. std::lock_guard<std::mutex> guard( m_mutex ); if( GetText().Length() == 0 ) return; wxPoint corners[4]; // Buffer of polygon corners EDA_RECT rect = GetTextBox( -1 ); rect.Inflate( aClearanceValue ); corners[0].x = rect.GetOrigin().x; corners[0].y = rect.GetOrigin().y; corners[1].y = corners[0].y; corners[1].x = rect.GetRight(); corners[2].x = corners[1].x; corners[2].y = rect.GetBottom(); corners[3].y = corners[2].y; corners[3].x = corners[0].x; aCornerBuffer->NewOutline(); for( int ii = 0; ii < 4; ii++ ) { // Rotate polygon RotatePoint( &corners[ii].x, &corners[ii].y, GetTextPos().x, GetTextPos().y, GetTextAngle() ); aCornerBuffer->Append( corners[ii].x, corners[ii].y ); } }
void TEXTE_PCB::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >& aList ) { wxString msg; wxCHECK_RET( m_Parent != NULL, wxT( "TEXTE_PCB::GetMsgPanelInfo() m_Parent is NULL." ) ); if( m_Parent->Type() == PCB_DIMENSION_T ) aList.push_back( MSG_PANEL_ITEM( _( "Dimension" ), GetShownText(), DARKGREEN ) ); else aList.push_back( MSG_PANEL_ITEM( _( "PCB Text" ), GetShownText(), DARKGREEN ) ); aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), BLUE ) ); if( !IsMirrored() ) aList.push_back( MSG_PANEL_ITEM( _( "Mirror" ), _( "No" ), DARKGREEN ) ); else aList.push_back( MSG_PANEL_ITEM( _( "Mirror" ), _( "Yes" ), DARKGREEN ) ); msg.Printf( wxT( "%.1f" ), GetTextAngle() / 10.0 ); aList.push_back( MSG_PANEL_ITEM( _( "Angle" ), msg, DARKGREEN ) ); msg = MessageTextFromValue( aUnits, GetThickness() ); aList.push_back( MSG_PANEL_ITEM( _( "Thickness" ), msg, MAGENTA ) ); msg = MessageTextFromValue( aUnits, GetTextWidth() ); aList.push_back( MSG_PANEL_ITEM( _( "Width" ), msg, RED ) ); msg = MessageTextFromValue( aUnits, GetTextHeight() ); aList.push_back( MSG_PANEL_ITEM( _( "Height" ), msg, RED ) ); }
void LIB_TEXT::Plot( PLOTTER* plotter, const wxPoint& offset, bool fill, const TRANSFORM& aTransform ) { wxASSERT( plotter != NULL ); EDA_RECT bBox = GetBoundingBox(); // convert coordinates from draw Y axis to libedit Y axis bBox.RevertYAxis(); wxPoint txtpos = bBox.Centre(); /* The text orientation may need to be flipped if the * transformation matrix causes xy axes to be flipped. */ int t1 = ( aTransform.x1 != 0 ) ^ ( GetTextAngle() != 0 ); wxPoint pos = aTransform.TransformCoordinate( txtpos ) + offset; // Get color COLOR4D color; if( plotter->GetColorMode() ) // Used normal color or selected color color = IsSelected() ? GetItemSelectedColor() : GetDefaultColor(); else color = COLOR4D::BLACK; plotter->Text( pos, color, GetShownText(), t1 ? TEXT_ANGLE_HORIZ : TEXT_ANGLE_VERT, GetTextSize(), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, GetPenSize(), IsItalic(), IsBold() ); }
void LIB_FIELD::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, const TRANSFORM& aTransform ) { if( IsVoid() ) return; /* Calculate the text orientation, according to the component * orientation/mirror */ int orient = (int) GetTextAngle(); if( aTransform.y1 ) // Rotate component 90 deg. { if( orient == TEXT_ANGLE_HORIZ ) orient = TEXT_ANGLE_VERT; else orient = TEXT_ANGLE_HORIZ; } EDA_RECT BoundaryBox = GetBoundingBox(); BoundaryBox.RevertYAxis(); EDA_TEXT_HJUSTIFY_T hjustify = GR_TEXT_HJUSTIFY_CENTER; EDA_TEXT_VJUSTIFY_T vjustify = GR_TEXT_VJUSTIFY_CENTER; wxPoint textpos = aTransform.TransformCoordinate( BoundaryBox.Centre() ) + aOffset; aPlotter->Text( textpos, GetDefaultColor(), GetShownText(), orient, GetTextSize(), hjustify, vjustify, GetPenSize(), IsItalic(), IsBold() ); }
void TEXTE_PCB::Rotate( const wxPoint& aRotCentre, double aAngle ) { wxPoint pt = GetTextPos(); RotatePoint( &pt, aRotCentre, aAngle ); SetTextPos( pt ); SetTextAngle( GetTextAngle() + aAngle ); }
const EDA_RECT SCH_FIELD::GetBoundingBox() const { SCH_COMPONENT* parentComponent = (SCH_COMPONENT*) m_Parent; int linewidth = GetThickness() == 0 ? GetDefaultLineThickness() : GetThickness(); // We must pass the effective text thickness to GetTextBox // when calculating the bounding box linewidth = Clamp_Text_PenSize( linewidth, GetTextSize(), IsBold() ); // 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 = GetTextPos() - origin; wxPoint begin = rect.GetOrigin() - origin; wxPoint end = rect.GetEnd() - origin; RotatePoint( &begin, pos, GetTextAngle() ); RotatePoint( &end, pos, GetTextAngle() ); // Due to the Y axis direction, we must mirror the bounding box, // relative to the text position: MIRROR( begin.y, pos.y ); MIRROR( 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_TEXT::Rotate( const wxPoint& center, bool aRotateCCW ) { int rot_angle = aRotateCCW ? -900 : 900; wxPoint pt = GetTextPos(); RotatePoint( &pt, center, rot_angle ); SetTextPos( pt ); SetTextAngle( GetTextAngle() != 0.0 ? 0 : 900 ); }
void LIB_TEXT::Rotate() { if( InEditMode() ) { m_rotate = true; } else { SetTextAngle( GetTextAngle() == TEXT_ANGLE_VERT ? TEXT_ANGLE_HORIZ : TEXT_ANGLE_VERT ); } }
void TEXTE_MODULE::Flip( const wxPoint& aCentre ) { // flipping the footprint is relative to the X axis SetTextY( ::Mirror( GetTextPos().y, aCentre.y ) ); SetTextAngle( -GetTextAngle() ); SetLayer( FlipLayer( GetLayer() ) ); SetMirrored( IsBackLayer( GetLayer() ) ); SetLocalCoord(); }
void TEXTE_MODULE::Rotate( const wxPoint& aRotCentre, double aAngle ) { // Used in footprint edition // Note also in module editor, m_Pos0 = m_Pos wxPoint pt = GetTextPos(); RotatePoint( &pt, aRotCentre, aAngle ); SetTextPos( pt ); SetTextAngle( GetTextAngle() + aAngle ); SetLocalCoord(); }
void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError ) const { wxSize size = GetTextSize(); if( IsMirrored() ) size.x = -size.x; prms.m_cornerBuffer = &aCornerBuffer; prms.m_textWidth = GetThickness() + ( 2 * aClearanceValue ); prms.m_error = aError; COLOR4D color = COLOR4D::BLACK; // not actually used, but needed by DrawGraphicText if( IsMultilineAllowed() ) { wxArrayString strings_list; wxStringSplit( GetShownText(), strings_list, '\n' ); std::vector<wxPoint> positions; positions.reserve( strings_list.Count() ); GetPositionsOfLinesOfMultilineText( positions, strings_list.Count() ); for( unsigned ii = 0; ii < strings_list.Count(); ii++ ) { wxString txt = strings_list.Item( ii ); DrawGraphicText( NULL, NULL, positions[ii], color, txt, GetTextAngle(), size, GetHorizJustify(), GetVertJustify(), GetThickness(), IsItalic(), true, addTextSegmToPoly, &prms ); } } else { DrawGraphicText( NULL, NULL, GetTextPos(), color, GetShownText(), GetTextAngle(), size, GetHorizJustify(), GetVertJustify(), GetThickness(), IsItalic(), true, addTextSegmToPoly, &prms ); } }
const EDA_RECT SCH_LABEL::GetBoundingBox() const { int linewidth = GetThickness() == 0 ? GetDefaultLineThickness() : GetThickness(); EDA_RECT rect = GetTextBox( -1, linewidth ); if( GetTextAngle() != 0.0 ) { // Rotate rect wxPoint pos = rect.GetOrigin(); wxPoint end = rect.GetEnd(); RotatePoint( &pos, GetTextPos(), GetTextAngle() ); RotatePoint( &end, GetTextPos(), GetTextAngle() ); rect.SetOrigin( pos ); rect.SetEnd( end ); rect.Normalize(); } return rect; }
void QtArc2D::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ) { if (event->button() & Qt::LeftButton && pending_db_save_) { // if there is a pending db save, do the save now (this happens at the end of a drag event) SetTextLocation(GetTextRadius(),GetTextAngle()); pending_db_save_ = false; } // let the base class do it's thing QGraphicsItem::mouseReleaseEvent(event); }
const EDA_RECT LIB_TEXT::GetBoundingBox() const { /* Y coordinates for LIB_ITEMS are bottom to top, so we must invert the Y position when * calling GetTextBox() that works using top to bottom Y axis orientation. */ EDA_RECT rect = GetTextBox( -1, -1, true ); rect.RevertYAxis(); // We are using now a bottom to top Y axis. wxPoint orig = rect.GetOrigin(); wxPoint end = rect.GetEnd(); RotatePoint( &orig, GetTextPos(), -GetTextAngle() ); RotatePoint( &end, GetTextPos(), -GetTextAngle() ); rect.SetOrigin( orig ); rect.SetEnd( end ); // We are using now a top to bottom Y axis: rect.RevertYAxis(); return rect; }
void SCH_FIELD::Plot( PLOTTER* aPlotter ) { SCH_COMPONENT* parent = ( SCH_COMPONENT* ) GetParent(); wxCHECK_RET( parent != NULL && parent->Type() == SCH_COMPONENT_T, wxT( "Cannot plot field with invalid parent." ) ); COLOR4D color = GetLayerColor( GetLayer() ); if( !IsVisible() ) return; if( IsVoid() ) return; /* Calculate the text orientation, according to the component * orientation/mirror */ int orient = GetTextAngle(); if( parent->GetTransform().y1 ) // Rotate component 90 deg. { 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 BoundaryBox = GetBoundingBox(); EDA_TEXT_HJUSTIFY_T hjustify = GR_TEXT_HJUSTIFY_CENTER; EDA_TEXT_VJUSTIFY_T vjustify = GR_TEXT_VJUSTIFY_CENTER; wxPoint textpos = BoundaryBox.Centre(); int thickness = GetPenSize(); aPlotter->Text( textpos, color, GetFullyQualifiedText(), orient, GetTextSize(), hjustify, vjustify, thickness, IsItalic(), IsBold() ); }
bool LIB_TEXT::HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const { if( aThreshold < 0 ) aThreshold = 0; EDA_TEXT tmp_text( *this ); tmp_text.SetTextPos( aTransform.TransformCoordinate( GetTextPos() ) ); /* The text orientation may need to be flipped if the * transformation matrix causes xy axes to be flipped. * this simple algo works only for schematic matrix (rot 90 or/and mirror) */ bool t1 = ( aTransform.x1 != 0 ) ^ ( GetTextAngle() != 0 ); tmp_text.SetTextAngle( t1 ? TEXT_ANGLE_HORIZ : TEXT_ANGLE_VERT ); return tmp_text.TextHitTest( aPosition ); }
bool SCH_FIELD::Save( FILE* aFile ) const { char hjustify = 'C'; if( GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT ) hjustify = 'L'; else if( GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT ) hjustify = 'R'; char vjustify = 'C'; if( GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM ) vjustify = 'B'; else if( GetVertJustify() == GR_TEXT_VJUSTIFY_TOP ) vjustify = 'T'; if( fprintf( aFile, "F %d %s %c %-3d %-3d %-3d %4.4X %c %c%c%c", m_id, EscapedUTF8( m_Text ).c_str(), // wraps in quotes too GetTextAngle() == TEXT_ANGLE_HORIZ ? 'H' : 'V', GetTextPos().x, GetTextPos().y, GetTextWidth(), !IsVisible(), hjustify, vjustify, IsItalic() ? 'I' : 'N', IsBold() ? 'B' : 'N' ) == EOF ) { return false; } // Save field name, if the name is user definable if( m_id >= FIELD1 ) { if( fprintf( aFile, " %s", EscapedUTF8( m_name ).c_str() ) == EOF ) { return false; } } if( fprintf( aFile, "\n" ) == EOF ) { return false; } return true; }
void LIB_FIELD::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, void* aData, const TRANSFORM& aTransform ) { wxPoint text_pos; COLOR4D color = IsVisible() ? GetDefaultColor() : GetInvisibleItemColor(); int linewidth = GetPenSize(); text_pos = aTransform.TransformCoordinate( GetTextPos() ) + aOffset; wxString text; if( aData ) text = *(wxString*)aData; else text = m_Text; EDA_RECT* clipbox = aPanel? aPanel->GetClipBox() : NULL; DrawGraphicText( clipbox, aDC, text_pos, color, text, GetTextAngle(), GetTextSize(), GetHorizJustify(), GetVertJustify(), linewidth, IsItalic(), IsBold() ); }
void LIB_TEXT::calcEdit( const wxPoint& aPosition ) { if( m_rotate ) { SetTextAngle( GetTextAngle() == TEXT_ANGLE_VERT ? TEXT_ANGLE_HORIZ : TEXT_ANGLE_VERT ); m_rotate = false; } if( m_updateText ) { std::swap( m_Text, m_savedText ); m_updateText = false; } if( m_Flags == IS_NEW ) { SetEraseLastDrawItem(); SetTextPos( aPosition ); } else if( m_Flags == IS_MOVED ) { Move( m_initialPos + aPosition - m_initialCursorPos ); } }
double TEXTE_MODULE::GetDrawRotation() const { MODULE* module = (MODULE*) m_Parent; double rotation = GetTextAngle(); if( module ) rotation += module->GetOrientation(); if( m_unlocked ) { NORMALIZE_ANGLE_POS( rotation ); } else { // Keep angle between -90 .. 90 deg. Otherwise the text is not easy to read while( rotation > 900 ) rotation -= 1800; while( rotation < -900 ) rotation += 1800; } return rotation; }
void QtArc2D::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * /* widget */) { double level_of_detail = QStyleOptionGraphicsItem::levelOfDetailFromTransform(painter->worldTransform()); DisplayProperties current_properties; // @fixme the way radius_properties is defined in the following if statement block will prevent the user from changing the display properties of the radius dimension or the points at run time since the DisplayProperties constructor is used to set these properties DisplayProperties radius_properties; if(option->state & QStyle::State_MouseOver && IsSelectable()) { current_properties = GetMouseHoverProperties(); radius_properties = DisplayProperties(HoverAnnotation); } else if (option->state & QStyle::State_Selected) { current_properties = GetSelectedProperties(); radius_properties = DisplayProperties(SelectedAnnotation); } else { current_properties = GetProperties(); radius_properties = DisplayProperties(Annotation); } double leader_gap = current_properties.GetLeaderGap()/level_of_detail; double leader_extension = current_properties.GetLeaderExtension()/level_of_detail; double leader_extension_angle = ((leader_extension/GetRadius()->GetValue())*(180.0/mmcPI))/level_of_detail; double leader_gap_angle = ((leader_gap/GetRadius()->GetValue())*(180.0/mmcPI))/level_of_detail; double radius = GetRadius()->GetValue(); QRectF rect(QPointF(GetSCenter()->GetValue()-radius,-GetTCenter()->GetValue()-radius), QPointF(GetSCenter()->GetValue()+radius,-GetTCenter()->GetValue()+radius)); double angle1 = GetTheta1()->GetValue()*((180.0)/(mmcPI)); double angle2 = GetTheta2()->GetValue()*((180.0)/(mmcPI)); double text_angle = GetTextAngle()*((180.0)/(mmcPI)); // put angle1 and angle2 into a preditable form // angle2 > angle1 and angle2 - angle1 < 360.0 if(angle1 > angle2) { double temp; temp = angle1; angle1 = angle2; angle2 = temp; } if(angle2-angle1 >= 360.0) angle2 = angle2 - floor((angle2-angle1)/(360.0))*360.0; if(text_angle-angle1 >= 360.0) text_angle = text_angle - floor((text_angle-angle1)/(360.0))*360.0; else if(angle2 - text_angle >= 360.0) text_angle = text_angle + floor((angle2-text_angle)/(360.0))*360.0; // create the radius dimension if necessary // Only display the radius if it is not a free parameter // If it is a free parameter, it is not really a constraint and should not be displayed as such if( ! radius_->IsFree()) { painter->setPen(radius_properties.GetPen(level_of_detail)); painter->setBrush(radius_properties.GetBrush()); QPolygonF radius_arrow = GetArrowPolygon(s_center_->GetValue(),-t_center_->GetValue(),s_center_->GetValue()+radius_->GetValue()*cos(GetTextAngle()), -(t_center_->GetValue()+radius_->GetValue()*sin(GetTextAngle())), 15.0/level_of_detail,12.0/level_of_detail); painter->drawPolygon(radius_arrow); // extend arc to radius arrow if radius arrow is outside the arc if(text_angle < angle1) { painter->drawArc(rect,(text_angle-leader_extension_angle)*16.0, ((angle1-leader_gap_angle)-(text_angle-leader_extension_angle))*16.0); } else if(text_angle > angle2) { painter->drawArc(rect,(angle2+leader_gap_angle)*16.0,((text_angle+leader_extension_angle)-(angle2+leader_gap_angle))*16.0); } // draw a line from the arc center point to the text location in case the text is outside of the arc painter->drawLine(QPointF(s_center_->GetValue(),-t_center_->GetValue()), QPointF(s_center_->GetValue()+GetTextRadius()*cos(GetTextAngle()),-(t_center_->GetValue()+GetTextRadius()*sin(GetTextAngle())))); // create the line edit widget graphics item if(radius_widget_ == 0) { // @fixme need to make sure the following dyname_cast won't create a pointer that is need used even if this shared_ptr class is freed from memory radius_widget_ = new QtArc2DWidget(shared_from_this(),dynamic_cast<QGraphicsItem*>(const_cast<QtArc2D*>(this))); } radius_widget_->UpdateGeometry(level_of_detail); } painter->setPen(current_properties.GetPen(level_of_detail)); painter->setBrush(current_properties.GetBrush()); // paint the actual arc QPainterPath arc_selection_path; painter->drawPath(GetArcAndSelectionPath(GetSCenter()->GetValue(), -GetTCenter()->GetValue(), radius, angle1*(mmcPI/180.0), angle2*(mmcPI/180.0), arc_selection_path, level_of_detail)); current_shape_ = arc_selection_path; }
void LIB_FIELD::Rotate() { SetTextAngle( GetTextAngle() == TEXT_ANGLE_VERT ? TEXT_ANGLE_HORIZ : TEXT_ANGLE_VERT ); }
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 QtAngleLine2D::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * /* widget */) { // @fixme need to handle the case where one of the lines has zero length (make sure there are no divide by zeros) double level_of_detail = QStyleOptionGraphicsItem::levelOfDetailFromTransform(painter->worldTransform()); DisplayProperties current_properties; if(option->state & QStyle::State_MouseOver && IsSelectable()) { current_properties = GetMouseHoverProperties(); } else if (option->state & QStyle::State_Selected) { current_properties = GetSelectedProperties(); } else { current_properties = GetProperties(); } painter->setPen(current_properties.GetPen(level_of_detail)); painter->setBrush(current_properties.GetBrush()); double leader_gap = current_properties.GetLeaderGap()/level_of_detail; double leader_extension = current_properties.GetLeaderExtension()/level_of_detail; // first determine the intersection point of the two lines double x1 = GetLine1()->GetPoint1()->GetSValue(); double x2 = GetLine1()->GetPoint2()->GetSValue(); double x3 = GetLine2()->GetPoint1()->GetSValue(); double x4 = GetLine2()->GetPoint2()->GetSValue(); double y1 = GetLine1()->GetPoint1()->GetTValue(); double y2 = GetLine1()->GetPoint2()->GetTValue(); double y3 = GetLine2()->GetPoint1()->GetTValue(); double y4 = GetLine2()->GetPoint2()->GetTValue(); double denominator = (x1-x2)*(y3-y4)-(x3-x4)*(y1-y2); double text_x, text_y; double x_center, y_center; bool lines_parallel = false; double arrow_tip_x1; double arrow_tip_x2; double arrow_tip_y1; double arrow_tip_y2; if(denominator == 0.0) { // Lines are parallel lines_parallel = true; text_x = text_s_->GetValue(); text_y = text_t_->GetValue(); } else { // lines do intersect // finish calculating the intersection point double temp1 = x1*y2-y1*x2; double temp2 = x3*y4-x4*y3; x_center = (temp1*(x3-x4)-temp2*(x1-x2))/denominator; y_center = (temp1*(y3-y4)-temp2*(y1-y2))/denominator; text_x = x_center + GetTextRadius()*cos(GetTextAngle()); text_y = y_center + GetTextRadius()*sin(GetTextAngle()); } if(!lines_parallel) { // normal case where lines are not parallel double line1_theta = atan2(y2-y1, x2-x1); double line2_theta = atan2(y4-y3, x4-x3); if(line2_theta < line1_theta) line2_theta += 2.0*mmcPI; double theta; bool theta_is_interior; if(line2_theta - line1_theta > mmcPI) { theta_is_interior = false; theta = line2_theta - line1_theta - mmcPI; } else { theta_is_interior = true; theta = line2_theta - line1_theta; } double alpha1 = line1_theta; double alpha2 = alpha1 + theta; double alpha3 = alpha1 + mmcPI; double alpha4 = alpha1 + mmcPI + theta; double alpha5 = alpha1 + 2.0*mmcPI; double text_theta = GetTextAngle(); // determine which sector the text is nearest too // first increment text_theta so that it is greater then alpha1 and less then alpha5 if(text_theta < alpha1) { while (text_theta < alpha1) text_theta += 2.0*mmcPI; } else if (text_theta > alpha5) { while (text_theta > alpha5) text_theta -= 2.0*mmcPI; } double arrow_arc_theta1; double arrow_arc_theta2; if(IsInteriorAngle() && theta_is_interior || !IsInteriorAngle() && !theta_is_interior) { // either sector 1 or sector 3 for an interior angle double sector_1_delta = fabs((alpha1+alpha2)*0.5-text_theta); double sector_3_delta = fabs((alpha3+alpha4)*0.5-text_theta); if(sector_1_delta < sector_3_delta) { arrow_arc_theta1 = alpha1; arrow_arc_theta2 = alpha2; } else { arrow_arc_theta1 = alpha3; arrow_arc_theta2 = alpha4; } // theta1 correspnds to line1 arrow_tip_x1 = x_center + GetTextRadius()*cos(arrow_arc_theta1); arrow_tip_y1 = y_center + GetTextRadius()*sin(arrow_arc_theta1); arrow_tip_x2 = x_center + GetTextRadius()*cos(arrow_arc_theta2); arrow_tip_y2 = y_center + GetTextRadius()*sin(arrow_arc_theta2); } else { // either sector 2 or sector 4 for an exterior angle double sector_2_delta = fabs((alpha2+alpha3)*0.5-text_theta); double sector_4_delta = fabs((alpha4+alpha5)*0.5-text_theta); if(sector_2_delta < sector_4_delta) { arrow_arc_theta1 = alpha2; arrow_arc_theta2 = alpha3; } else { arrow_arc_theta1 = alpha4; arrow_arc_theta2 = alpha5; } // theta1 correspnds to line2 arrow_tip_x2 = x_center + GetTextRadius()*cos(arrow_arc_theta1); arrow_tip_y2 = y_center + GetTextRadius()*sin(arrow_arc_theta1); arrow_tip_x1 = x_center + GetTextRadius()*cos(arrow_arc_theta2); arrow_tip_y1 = y_center + GetTextRadius()*sin(arrow_arc_theta2); } // display the arrow arc QPainterPath selection_path; QPainterPath arrow_arc = GetArcArrowPathAndSelectionPath(x_center, -y_center, GetTextRadius(),arrow_arc_theta1,arrow_arc_theta2,15.0/level_of_detail,12.0/level_of_detail,selection_path,level_of_detail); painter->drawPath(arrow_arc); current_shape_ = selection_path; // draw an additional arc to the text if text is outside of the arrow arc QRectF rect(QPointF(x_center-GetTextRadius(),-y_center-GetTextRadius()), QPointF(x_center+GetTextRadius(),-y_center+GetTextRadius())); if(text_theta < arrow_arc_theta1) painter->drawArc(rect,(text_theta)*(180.0/mmcPI)*16.0,(arrow_arc_theta1-text_theta)*(180.0/mmcPI)*16.0); else if (text_theta > arrow_arc_theta2) painter->drawArc(rect,(arrow_arc_theta2)*(180.0/mmcPI)*16.0,((text_theta)-(arrow_arc_theta2))*(180.0/mmcPI)*16.0); // display the editable text // create the line edit widget graphics item if(angle_widget_ == 0) { // @fixme need to make sure the following dyname_cast won't create a pointer that is need used even if this shared_ptr class is freed from memory angle_widget_ = new QtAngleLine2DWidget(shared_from_this(),dynamic_cast<QGraphicsItem*>(const_cast<QtAngleLine2D*>(this))); } angle_widget_->UpdateGeometry(text_x, text_y, level_of_detail); // create leader for line1 if necessary double delta1, delta2; double line1_length = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); delta1 = sqrt((arrow_tip_x1-x1)*(arrow_tip_x1-x1)+(arrow_tip_y1-y1)*(arrow_tip_y1-y1)); delta2 = sqrt((arrow_tip_x1-x2)*(arrow_tip_x1-x2)+(arrow_tip_y1-y2)*(arrow_tip_y1-y2)); if(delta1 > line1_length && delta1 > delta2) { double direction_x = arrow_tip_x1-x1; double direction_y = arrow_tip_y1-y1; double direction_length = sqrt(direction_x*direction_x + direction_y*direction_y); direction_x = direction_x / direction_length; direction_y = direction_y / direction_length; painter->drawLine(QPointF(x2+leader_gap*direction_x,-(y2+leader_gap*direction_y)), QPointF(x1+(delta1+leader_extension)*direction_x,-(y1+(delta1+leader_extension)*direction_y))); } else if (delta2 > line1_length) { double direction_x = arrow_tip_x1-x2; double direction_y = arrow_tip_y1-y2; double direction_length = sqrt(direction_x*direction_x + direction_y*direction_y); direction_x = direction_x / direction_length; direction_y = direction_y / direction_length; painter->drawLine(QPointF(x1+leader_gap*direction_x,-(y1+leader_gap*direction_y)), QPointF(x2+(delta2+leader_extension)*direction_x,-(y2+(delta2+leader_extension)*direction_y))); } // create leader for line2 if necessary double line2_length = sqrt((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4)); delta1 = sqrt((arrow_tip_x2-x3)*(arrow_tip_x2-x3)+(arrow_tip_y2-y3)*(arrow_tip_y2-y3)); delta2 = sqrt((arrow_tip_x2-x4)*(arrow_tip_x2-x4)+(arrow_tip_y2-y4)*(arrow_tip_y2-y4)); if(delta1 > line2_length && delta1 > delta2) { double direction_x = arrow_tip_x2-x3; double direction_y = arrow_tip_y2-y3; double direction_length = sqrt(direction_x*direction_x + direction_y*direction_y); direction_x = direction_x / direction_length; direction_y = direction_y / direction_length; painter->drawLine(QPointF(x4+leader_gap*direction_x,-(y4+leader_gap*direction_y)), QPointF(x3+(delta1+leader_extension)*direction_x,-(y3+(delta1+leader_extension)*direction_y))); } else if (delta2 > line2_length) { double direction_x = arrow_tip_x2-x4; double direction_y = arrow_tip_y2-y4; double direction_length = sqrt(direction_x*direction_x + direction_y*direction_y); direction_x = direction_x / direction_length; direction_y = direction_y / direction_length; painter->drawLine(QPointF(x3+leader_gap*direction_x,-(y3+leader_gap*direction_y)), QPointF(x4+(delta2+leader_extension)*direction_x,-(y4+(delta2+leader_extension)*direction_y))); } } else { // the case where the lines are parallel // display an arrow to the center point of each of the lines QPainterPath selection_path; QPolygonF arrow1 = GetArrowPolygonAndSelectionPath(text_x, -text_y, 0.5*(x1+x2), -0.5*(y1+y2),15.0/level_of_detail,12.0/level_of_detail,selection_path,level_of_detail); painter->drawPolygon(arrow1); current_shape_ = selection_path; QPolygonF arrow2 = GetArrowPolygonAndSelectionPath(text_x, -text_y, 0.5*(x3+x4), -0.5*(y3+y4),15.0/level_of_detail,12.0/level_of_detail,selection_path,level_of_detail); painter->drawPolygon(arrow2); current_shape_.addPath(selection_path); // display the editable text // create the line edit widget graphics item if(angle_widget_ == 0) { // @fixme need to make sure the following dyname_cast won't create a pointer that is need used even if this shared_ptr class is freed from memory angle_widget_ = new QtAngleLine2DWidget(shared_from_this(),dynamic_cast<QGraphicsItem*>(const_cast<QtAngleLine2D*>(this))); } angle_widget_->UpdateGeometry(text_x, text_y, level_of_detail); } // if(!lines_parallel) }
void SCH_FIELD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor ) { int orient; COLOR4D color; wxPoint textpos; SCH_COMPONENT* parentComponent = (SCH_COMPONENT*) m_Parent; int lineWidth = GetThickness(); if( lineWidth == 0 ) // Use default values for pen size { if( IsBold() ) lineWidth = GetPenSizeForBold( GetTextWidth() ); else lineWidth = GetDefaultLineThickness(); } // Clip pen size for small texts: lineWidth = Clamp_Text_PenSize( lineWidth, GetTextSize(), IsBold() ); if( ( !IsVisible() && !m_forceVisible) || IsVoid() ) return; GRSetDrawMode( aDC, aDrawMode ); // Calculate the text orientation according to the component orientation. orient = GetTextAngle(); if( parentComponent->GetTransform().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 boundaryBox = GetBoundingBox(); textpos = boundaryBox.Centre() + aOffset; if( m_forceVisible ) { color = COLOR4D( DARKGRAY ); } else { if( m_id == REFERENCE ) color = GetLayerColor( LAYER_REFERENCEPART ); else if( m_id == VALUE ) color = GetLayerColor( LAYER_VALUEPART ); else color = GetLayerColor( LAYER_FIELDS ); } EDA_RECT* clipbox = aPanel ? aPanel->GetClipBox() : NULL; DrawGraphicText( clipbox, aDC, textpos, color, GetFullyQualifiedText(), orient, GetTextSize(), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, lineWidth, IsItalic(), IsBold() ); // While moving: don't loose visual contact to which component this label belongs. if ( IsWireImage() ) { const wxPoint origin = parentComponent->GetPosition(); textpos = GetTextPos() - origin; textpos = parentComponent->GetScreenCoord( textpos ); textpos += parentComponent->GetPosition(); GRLine( clipbox, aDC, origin, textpos, 2, DARKGRAY ); } /* Enable this to draw the bounding box around the text field to validate * the bounding box calculations. */ #if 0 // Draw boundary box: GRRect( aPanel->GetClipBox(), aDC, boundaryBox, 0, BROWN ); // Draw the text anchor point /* Calculate the text position, according to the component * orientation/mirror */ textpos = m_Pos - parentComponent->GetPosition(); textpos = parentComponent->GetScreenCoord( textpos ); textpos += parentComponent->GetPosition(); const int len = 10; GRLine( clipbox, aDC, textpos.x - len, textpos.y, textpos.x + len, textpos.y, 0, BLUE ); GRLine( clipbox, aDC, textpos.x, textpos.y - len, textpos.x, textpos.y + len, 0, BLUE ); #endif }