KiCad PCB EDA Suite
worksheet_dataitem.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 1992-2013 Jean-Pierre Charras <jp.charras at wanadoo.fr>.
10  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
11  *
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, you may find one here:
25  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
26  * or you may search the http://www.gnu.org website for the version 2 license,
27  * or you may write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29  */
30 
31 
32 /*
33  * the class WORKSHEET_DATAITEM (and derived) defines
34  * a basic shape of a page layout ( frame references and title block )
35  * Basic shapes are line, rect and texts
36  * the WORKSHEET_DATAITEM coordinates units is the mm, and are relative to
37  * one of 4 page corners.
38  *
39  * These items cannot be drawn or plot "as this". they should be converted
40  * to a "draw list" (WS_DRAW_ITEM_BASE and derived items)
41 
42  * The list of these items is stored in a WORKSHEET_LAYOUT instance.
43  *
44  * When building the draw list:
45  * the WORKSHEET_LAYOUT is used to create a WS_DRAW_ITEM_LIST
46  * coordinates are converted to draw/plot coordinates.
47  * texts are expanded if they contain format symbols.
48  * Items with m_RepeatCount > 1 are created m_RepeatCount times
49  *
50  * the WORKSHEET_LAYOUT is created only once.
51  * the WS_DRAW_ITEM_LIST is created each time the page layout is plot/drawn
52  *
53  * the WORKSHEET_LAYOUT instance is created from a S expression which
54  * describes the page layout (can be the default page layout or a custom file).
55  */
56 
57 #include <fctsys.h>
58 #include <draw_graphic_text.h>
59 #include <eda_rect.h>
60 #include <worksheet.h>
61 #include <title_block.h>
63 #include <worksheet_dataitem.h>
64 
65 using KIGFX::COLOR4D;
66 
67 
68 // Static members of class WORKSHEET_DATAITEM:
76 COLOR4D WORKSHEET_DATAITEM::m_Color = COLOR4D( RED ); // the default color to draw items
77 COLOR4D WORKSHEET_DATAITEM::m_AltColor = COLOR4D( RED ); // an alternate color to draw items
78 COLOR4D WORKSHEET_DATAITEM::m_SelectedColor = COLOR4D( BROWN ); // the color to draw selected items
79 
80 
81 // The constructor:
83 {
84  m_type = aType;
85  m_flags = 0;
86  m_RepeatCount = 1;
87  m_IncrementLabel = 1;
88  m_LineWidth = 0;
89 }
90 
91 
92 // move item to aPosition
93 // starting point is moved to aPosition
94 // the Ending point is moved to a position which keeps the item size
95 // (if both coordinates have the same corner reference)
96 // MoveToUi and MoveTo takes the graphic position (i.e relative to the left top
97 // paper corner
99 {
100  DPOINT pos_mm;
101  pos_mm.x = aPosition.x / m_WSunits2Iu;
102  pos_mm.y = aPosition.y / m_WSunits2Iu;
103 
104  MoveTo( pos_mm );
105 }
106 
107 
109 {
110  DPOINT vector = aPosition - GetStartPos();
111  DPOINT endpos = vector + GetEndPos();
112 
113  MoveStartPointTo( aPosition );
114  MoveEndPointTo( endpos );
115 }
116 
117 
118 /* move the starting point of the item to a new position
119  * aPosition = the new position of the starting point, in mm
120  */
122 {
123  DPOINT position;
124 
125  // Calculate the position of the starting point
126  // relative to the reference corner
127  // aPosition is the position relative to the right top paper corner
128  switch( m_Pos.m_Anchor )
129  {
130  case RB_CORNER:
131  position = m_RB_Corner - aPosition;
132  break;
133 
134  case RT_CORNER:
135  position.x = m_RB_Corner.x - aPosition.x;
136  position.y = aPosition.y - m_LT_Corner.y;
137  break;
138 
139  case LB_CORNER:
140  position.x = aPosition.x - m_LT_Corner.x;
141  position.y = m_RB_Corner.y - aPosition.y;
142  break;
143 
144  case LT_CORNER:
145  position = aPosition - m_LT_Corner;
146  break;
147  }
148 
149  m_Pos.m_Pos = position;
150 }
151 
152 
153 /* move the starting point of the item to a new position
154  * aPosition = the new position of the starting point in graphic units
155  */
157 {
158  DPOINT pos_mm;
159  pos_mm.x = aPosition.x / m_WSunits2Iu;
160  pos_mm.y = aPosition.y / m_WSunits2Iu;
161 
162  MoveStartPointTo( pos_mm );
163 }
164 
165 
173 {
174  DPOINT position;
175 
176  // Calculate the position of the starting point
177  // relative to the reference corner
178  // aPosition is the position relative to the right top paper corner
179  switch( m_End.m_Anchor )
180  {
181  case RB_CORNER:
182  position = m_RB_Corner - aPosition;
183  break;
184 
185  case RT_CORNER:
186  position.x = m_RB_Corner.x - aPosition.x;
187  position.y = aPosition.y - m_LT_Corner.y;
188  break;
189 
190  case LB_CORNER:
191  position.x = aPosition.x - m_LT_Corner.x;
192  position.y = m_RB_Corner.y - aPosition.y;
193  break;
194 
195  case LT_CORNER:
196  position = aPosition - m_LT_Corner;
197  break;
198  }
199 
200  // Modify m_End only for items having 2 coordinates
201  switch( GetType() )
202  {
203  case WS_SEGMENT:
204  case WS_RECT:
205  m_End.m_Pos = position;
206  break;
207 
208  default:
209  break;
210  }
211 }
212 
213 
214 /* move the ending point of the item to a new position
215  * has meaning only for items defined by 2 points
216  * (segments and rectangles)
217  * aPosition = the new position of the ending point in graphic units
218  */
220 {
221  DPOINT pos_mm;
222  pos_mm.x = aPosition.x / m_WSunits2Iu;
223  pos_mm.y = aPosition.y / m_WSunits2Iu;
224 
225  MoveEndPointTo( pos_mm );
226 }
227 
228 
230 {
231  DPOINT pos;
232  pos.x = m_Pos.m_Pos.x + ( m_IncrementVector.x * ii );
233  pos.y = m_Pos.m_Pos.y + ( m_IncrementVector.y * ii );
234 
235  switch( m_Pos.m_Anchor )
236  {
237  case RB_CORNER: // right bottom corner
238  pos = m_RB_Corner - pos;
239  break;
240 
241  case RT_CORNER: // right top corner
242  pos.x = m_RB_Corner.x - pos.x;
243  pos.y = m_LT_Corner.y + pos.y;
244  break;
245 
246  case LB_CORNER: // left bottom corner
247  pos.x = m_LT_Corner.x + pos.x;
248  pos.y = m_RB_Corner.y - pos.y;
249  break;
250 
251  case LT_CORNER: // left top corner
252  pos = m_LT_Corner + pos;
253  break;
254  }
255 
256  return pos;
257 }
258 
259 
261 {
262  DPOINT pos = GetStartPos( ii );
263  pos = pos * m_WSunits2Iu;
264  return wxPoint( KiROUND( pos.x ), KiROUND( pos.y ) );
265 }
266 
267 
269 {
270  DPOINT pos;
271  pos.x = m_End.m_Pos.x + ( m_IncrementVector.x * ii );
272  pos.y = m_End.m_Pos.y + ( m_IncrementVector.y * ii );
273 
274  switch( m_End.m_Anchor )
275  {
276  case RB_CORNER: // right bottom corner
277  pos = m_RB_Corner - pos;
278  break;
279 
280  case RT_CORNER: // right top corner
281  pos.x = m_RB_Corner.x - pos.x;
282  pos.y = m_LT_Corner.y + pos.y;
283  break;
284 
285  case LB_CORNER: // left bottom corner
286  pos.x = m_LT_Corner.x + pos.x;
287  pos.y = m_RB_Corner.y - pos.y;
288  break;
289 
290  case LT_CORNER: // left top corner
291  pos = m_LT_Corner + pos;
292  break;
293  }
294 
295  return pos;
296 }
297 
298 
300 {
301  DPOINT pos = GetEndPos( ii );
302  pos = pos * m_WSunits2Iu;
303  return wxPoint( KiROUND( pos.x ), KiROUND( pos.y ) );
304 }
305 
306 
308 {
309  DPOINT pos = GetStartPos( ii );
310 
311  for( int kk = 0; kk < 1; kk++ )
312  {
313  if( m_RB_Corner.x < pos.x || m_LT_Corner.x > pos.x )
314  return false;
315 
316  if( m_RB_Corner.y < pos.y || m_LT_Corner.y > pos.y )
317  return false;
318 
319  pos = GetEndPos( ii );
320  }
321 
322  return true;
323 }
324 
325 
326 const wxString WORKSHEET_DATAITEM::GetClassName() const
327 {
328  wxString name;
329 
330  switch( GetType() )
331  {
332  case WS_TEXT: name = wxT( "Text" ); break;
333  case WS_SEGMENT: name = wxT( "Line" ); break;
334  case WS_RECT: name = wxT( "Rect" ); break;
335  case WS_POLYPOLYGON: name = wxT( "Poly" ); break;
336  case WS_BITMAP: name = wxT( "Bitmap" ); break;
337  }
338 
339  return name;
340 }
341 
342 
343 /* return 0 if the item has no specific option for page 1
344  * 1 if the item is only on page 1
345  * -1 if the item is not on page 1
346  */
348 {
350  return -1;
351 
352  if(( m_flags & PAGE1OPTION) == PAGE1OPTION_PAGE1ONLY )
353  return 1;
354 
355  return 0;
356 }
357 
358 
359 /* Set the option for page 1
360  * aChoice = 0 if the item has no specific option for page 1
361  * > 0 if the item is only on page 1
362  * < 0 if the item is not on page 1
363  */
365 {
367 
368  if( aChoice > 0 )
370 
371  else if( aChoice < 0 )
373 
374 }
375 
376 
379 {
380  m_Orient = 0.0;
381 }
382 
383 
385  int aRepeat ) const
386 {
387  DPOINT pos = m_Corners[aIdx];
388 
389  // Rotation:
390  RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
391  pos += GetStartPos( aRepeat );
392  return pos;
393 }
394 
395 
397 {
398  if( m_Corners.size() == 0 )
399  {
400  m_minCoord.x = m_maxCoord.x = 0.0;
401  m_minCoord.y = m_maxCoord.y = 0.0;
402  return;
403  }
404 
405  DPOINT pos;
406  pos = m_Corners[0];
407  RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
408  m_minCoord = m_maxCoord = pos;
409 
410  for( unsigned ii = 1; ii < m_Corners.size(); ii++ )
411  {
412  pos = m_Corners[ii];
413  RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
414 
415  if( m_minCoord.x > pos.x )
416  m_minCoord.x = pos.x;
417 
418  if( m_minCoord.y > pos.y )
419  m_minCoord.y = pos.y;
420 
421  if( m_maxCoord.x < pos.x )
422  m_maxCoord.x = pos.x;
423 
424  if( m_maxCoord.y < pos.y )
425  m_maxCoord.y = pos.y;
426  }
427 }
428 
429 
431 {
432  DPOINT pos = GetStartPos( ii );
433  pos += m_minCoord; // left top pos of bounding box
434 
435  if( m_LT_Corner.x > pos.x || m_LT_Corner.y > pos.y )
436  return false;
437 
438  pos = GetStartPos( ii );
439  pos += m_maxCoord; // rignt bottom pos of bounding box
440 
441  if( m_RB_Corner.x < pos.x || m_RB_Corner.y < pos.y )
442  return false;
443 
444  return true;
445 }
446 
447 
449  int aRepeat ) const
450 {
451  DPOINT pos = GetCornerPosition( aIdx, aRepeat );
452  pos = pos * m_WSunits2Iu;
453  return wxPoint( int(pos.x), int(pos.y) );
454 }
455 
456 
459 {
460  m_TextBase = aTextBase;
461  m_IncrementLabel = 1;
464  m_Orient = 0.0;
465  m_LineWidth = 0.0; // 0.0 means use default value
466 }
467 
468 
470 {
471  aGText->SetHorizJustify( m_Hjustify ) ;
472  aGText->SetVertJustify( m_Vjustify );
473  aGText->SetTextAngle( m_Orient * 10 ); // graphic text orient unit = 0.1 degree
474 }
475 
476 
478 {
479  int last = m_TextBase.Len() -1;
480 
481  wxChar lbchar = m_TextBase[last];
483  m_FullText.RemoveLast();
484 
485  if( lbchar >= '0' && lbchar <= '9' )
486  // A number is expected:
487  m_FullText << (int)( aIncr + lbchar - '0' );
488  else
489  m_FullText << (wxChar) ( aIncr + lbchar );
490 }
491 
492 
493 // Replace the '\''n' sequence by EOL
494 // and the sequence '\''\' by only one '\' in m_FullText
495 // if m_FullText is a multiline text (i.e.contains '\n') return true
497 {
498  bool multiline = false;
499 
500  for( unsigned ii = 0; ii < m_FullText.Len(); ii++ )
501  {
502  if( m_FullText[ii] == '\n' )
503  multiline = true;
504 
505  else if( m_FullText[ii] == '\\' )
506  {
507  if( ++ii >= m_FullText.Len() )
508  break;
509 
510  if( m_FullText[ii] == '\\' )
511  {
512  // a double \\ sequence is replaced by a single \ char
513  m_FullText.Remove(ii, 1);
514  ii--;
515  }
516  else if( m_FullText[ii] == 'n' )
517  {
518  // Replace the "\n" sequence by a EOL char
519  multiline = true;
520  m_FullText[ii] = '\n';
521  m_FullText.Remove(ii-1, 1);
522  ii--;
523  }
524  }
525  }
526 
527  return multiline;
528 }
529 
530 
532 {
534 
535  if( m_ConstrainedTextSize.x == 0 )
537 
538  if( m_ConstrainedTextSize.y == 0 )
540 
542  {
543  // to know the X and Y size of the line, we should use
544  // EDA_TEXT::GetTextBox()
545  // but this function uses integers
546  // So, to avoid truncations with our unit in mm, use microns.
547  wxSize size_micron;
548  #define FSCALE 1000.0
549  int linewidth = 0;
550  size_micron.x = KiROUND( m_ConstrainedTextSize.x * FSCALE );
551  size_micron.y = KiROUND( m_ConstrainedTextSize.y * FSCALE );
553  wxPoint(0,0),
554  size_micron,
555  linewidth, BLACK,
556  IsItalic(), IsBold() ) );
557  dummy.SetMultilineAllowed( true );
558  TransfertSetupToGraphicText( &dummy );
559 
560  EDA_RECT rect = dummy.GetTextBox();
561  DSIZE size;
562  size.x = rect.GetWidth() / FSCALE;
563  size.y = rect.GetHeight() / FSCALE;
564 
565  if( m_BoundingBoxSize.x && size.x > m_BoundingBoxSize.x )
567 
568  if( m_BoundingBoxSize.y && size.y > m_BoundingBoxSize.y )
570  }
571 }
572 
573 
574 /* set the pixel scale factor of the bitmap
575  * this factor depend on the application internal unit
576  * and the PPI bitmap factor
577  * the pixel scale factor should be initialized before drawing the bitmap
578  */
580 {
581  if( m_ImageBitmap )
582  {
583  // m_WSunits2Iu is the page layout unit to application internal unit
584  // i.e. the mm to to application internal unit
585  // however the bitmap definition is always known in pixels per inches
586  double scale = m_WSunits2Iu * 25.4 / m_ImageBitmap->GetPPI();
587  m_ImageBitmap->SetPixelScaleFactor( scale );
588  }
589 }
590 
591 
592 /* return the PPI of the bitmap
593  */
595 {
596  if( m_ImageBitmap )
597  return m_ImageBitmap->GetPPI() / m_ImageBitmap->GetScale();
598 
599  return 300;
600 }
601 
602 
603 /*adjust the PPI of the bitmap
604  */
605 void WORKSHEET_DATAITEM_BITMAP::SetPPI( int aBitmapPPI )
606 {
607  if( m_ImageBitmap )
608  m_ImageBitmap->SetScale( (double) m_ImageBitmap->GetPPI() / aBitmapPPI );
609 }
static DSIZE m_DefaultTextSize
void TransfertSetupToGraphicText(WS_DRAW_ITEM_TEXT *aGText)
transfert the text justification and orientation to aGText
static COLOR4D m_SelectedColor
EDA_TEXT_HJUSTIFY_T m_Hjustify
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:120
#define PAGE1OPTION_PAGE1ONLY
void SetBoundingBox()
calculate the bounding box of the set polygons
EDA_TEXT_VJUSTIFY_T m_Vjustify
static double m_WSunits2Iu
const DPOINT GetStartPos(int ii=0) const
Class VECTOR2 defines a general 2D-vector/point.
Definition: vector2d.h:61
int GetHeight() const
Definition: eda_rect.h:118
bool IsInsidePage(int ii) const override
void ClearFlags(int aMask)
static DPOINT m_LT_Corner
void MoveEndPointTo(DPOINT aPosition)
move the ending point of the item to a new position has meaning only for items defined by 2 points (s...
virtual bool IsInsidePage(int ii) const
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
WORKSHEET_DATAITEM(WS_ItemType aType)
const wxPoint GetStartPosUi(int ii=0) const
#define TB_DEFAULT_TEXTSIZE
void IncrementLabel(int aIncr)
Try to build text wihich is an increment of m_TextBase has meaning only if m_TextBase is a basic text...
void MoveStartPointTo(DPOINT aPosition)
move the starting point of the item to a new position
static COLOR4D m_Color
WORKSHEET_DATAITEM_TEXT(const wxString &aTextBase)
static DPOINT m_RB_Corner
void SetFlags(int aMask)
void MoveToUi(wxPoint aPosition)
move item to a new position
EDA_RECT GetTextBox(int aLine=-1, int aThickness=-1, bool aInvertY=false) const
Function GetTextBox useful in multiline texts to calculate the full text or a line area (for zones fi...
Definition: eda_text.cpp:103
void SetPixelScaleFactor()
set the pixel scale factor of the bitmap this factor depend on the application internal unit and the ...
#define PAGE1OPTION
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:207
void MoveTo(DPOINT aPosition)
move item to a new position
#define PAGE1OPTION_NOTONPAGE1
const wxPoint GetEndPosUi(int ii=0) const
description of graphic items and texts to build a title block
Definition: colors.h:60
static COLOR4D m_AltColor
void SetMultilineAllowed(bool aAllow)
Function SetMultiLineAllowed.
Definition: eda_text.h:200
void SetPPI(int aBitmapPPI)
adjust the PPI of the bitmap
void SetTextAngle(double aAngle)
const wxPoint GetCornerPositionUi(unsigned aIdx, int aRepeat=0) const
const DPOINT GetEndPos(int ii=0) const
static double m_DefaultTextThickness
static double m_DefaultLineWidth
const int scale
const char * name
Definition: DXF_plotter.cpp:61
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:206
void SetConstrainedTextSize()
Calculates m_ConstrainedTextSize from m_TextSize to keep the X size and the full Y size of the text s...
WS_ItemType GetType() const
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int GetWidth() const
Definition: eda_rect.h:117
classes and function to generate graphics to plt or draw titles blocks and frame references ...
void MoveEndPointToUi(wxPoint aPosition)
move the ending point of the item to a new position has meaning only for items defined by 2 points (s...
Definition: colors.h:45
void SetPage1Option(int aChoice)
Set the option for page 1.
void MoveStartPointToUi(wxPoint aPosition)
move the starting point of the item to a new position
bool ReplaceAntiSlashSequence()
Replace the &#39;\&#39;&#39;n&#39; sequence by EOL and the sequence &#39;\&#39;&#39;\&#39; by only one &#39;\&#39; inside m_FullText...
#define FSCALE
const wxString GetClassName() const
const DPOINT GetCornerPosition(unsigned aIdx, int aRepeat=0) const
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
Definition: colors.h:62