KiCad PCB EDA Suite
PS_plotter.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
31 #include <macros.h>
32 #include <math/util.h> // for KiROUND
33 #include <trigo.h>
34 
36 
37 
38 /* Forward declaration of the font width metrics
39  (yes extern! this is the way to forward declare variables */
40 extern const double hv_widths[256];
41 extern const double hvb_widths[256];
42 extern const double hvo_widths[256];
43 extern const double hvbo_widths[256];
44 
45 const double PSLIKE_PLOTTER::postscriptTextAscent = 0.718;
46 
47 
48 // return a id used to select a ps macro (see StartPlot() ) from a FILL_TYPE
49 // fill mode, for arc, rect, circle and poly draw primitives
50 static int getFillId( FILL_T aFill )
51 {
52  if( aFill == FILL_T::NO_FILL )
53  return 0;
54 
55  if( aFill == FILL_T::FILLED_SHAPE )
56  return 1;
57 
58  return 2;
59 }
60 
61 
63 {
64  if( m_colorMode )
65  {
66  if( m_negativeMode )
67  emitSetRGBColor( 1 - color.r, 1 - color.g, 1 - color.b );
68  else
69  emitSetRGBColor( color.r, color.g, color.b );
70  }
71  else
72  {
73  /* B/W Mode - Use BLACK or WHITE for all items
74  * note the 2 colors are used in B&W mode, mainly by Pcbnew to draw
75  * holes in white on pads in black
76  */
77  double k = 1; // White
78 
79  if( color != COLOR4D::WHITE )
80  k = 0;
81 
82  if( m_negativeMode )
83  emitSetRGBColor( 1 - k, 1 - k, 1 - k );
84  else
85  emitSetRGBColor( k, k, k );
86  }
87 }
88 
89 
90 void PSLIKE_PLOTTER::FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize,
91  double aPadOrient, OUTLINE_MODE aTraceMode, void* aData )
92 {
93  wxASSERT( m_outputFile );
94  int x0, y0, x1, y1, delta;
95  wxSize size( aSize );
96 
97  // The pad is reduced to an oval by dy > dx
98  if( size.x > size.y )
99  {
100  std::swap( size.x, size.y );
101  aPadOrient = AddAngles( aPadOrient, 900 );
102  }
103 
104  delta = size.y - size.x;
105  x0 = 0;
106  y0 = -delta / 2;
107  x1 = 0;
108  y1 = delta / 2;
109  RotatePoint( &x0, &y0, aPadOrient );
110  RotatePoint( &x1, &y1, aPadOrient );
111 
112  if( aTraceMode == FILLED )
113  ThickSegment( wxPoint( aPadPos.x + x0, aPadPos.y + y0 ),
114  wxPoint( aPadPos.x + x1, aPadPos.y + y1 ), size.x, aTraceMode, nullptr );
115  else
116  sketchOval( aPadPos, size, aPadOrient, -1 );
117 }
118 
119 
120 void PSLIKE_PLOTTER::FlashPadCircle( const wxPoint& aPadPos, int aDiameter,
121  OUTLINE_MODE aTraceMode, void* aData )
122 {
123  if( aTraceMode == FILLED )
124  {
125  Circle( aPadPos, aDiameter, FILL_T::FILLED_SHAPE, 0 );
126  }
127  else // Plot a ring:
128  {
130  Circle( aPadPos, aDiameter, FILL_T::NO_FILL, GetCurrentLineWidth() );
131  }
132 
134 }
135 
136 
137 void PSLIKE_PLOTTER::FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize,
138  double aPadOrient, OUTLINE_MODE aTraceMode, void* aData )
139 {
140  static std::vector< wxPoint > cornerList;
141  wxSize size( aSize );
142  cornerList.clear();
143 
144  if( aTraceMode == FILLED )
145  SetCurrentLineWidth( 0 );
146  else
148 
149  int dx = size.x / 2;
150  int dy = size.y / 2;
151 
152  wxPoint corner;
153  corner.x = aPadPos.x - dx;
154  corner.y = aPadPos.y + dy;
155  cornerList.push_back( corner );
156  corner.x = aPadPos.x - dx;
157  corner.y = aPadPos.y - dy;
158  cornerList.push_back( corner );
159  corner.x = aPadPos.x + dx;
160  corner.y = aPadPos.y - dy;
161  cornerList.push_back( corner );
162  corner.x = aPadPos.x + dx;
163  corner.y = aPadPos.y + dy,
164  cornerList.push_back( corner );
165 
166  for( unsigned ii = 0; ii < cornerList.size(); ii++ )
167  {
168  RotatePoint( &cornerList[ii], aPadPos, aPadOrient );
169  }
170 
171  cornerList.push_back( cornerList[0] );
172 
173  PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL,
175 }
176 
177 
178 void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
179  int aCornerRadius, double aOrient,
180  OUTLINE_MODE aTraceMode, void* aData )
181 {
182  wxSize size( aSize );
183 
184  if( aTraceMode == FILLED )
185  {
186  SetCurrentLineWidth( 0 );
187  }
188  else
189  {
191  }
192 
193 
194  SHAPE_POLY_SET outline;
195  TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, aCornerRadius,
196  0.0, 0, 0, GetPlotterArcHighDef(), ERROR_INSIDE );
197 
198  std::vector< wxPoint > cornerList;
199 
200  // TransformRoundRectToPolygon creates only one convex polygon
201  SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
202  cornerList.reserve( poly.PointCount() );
203 
204  for( int ii = 0; ii < poly.PointCount(); ++ii )
205  cornerList.emplace_back( poly.CPoint( ii ).x, poly.CPoint( ii ).y );
206 
207  // Close polygon
208  cornerList.push_back( cornerList[0] );
209 
210  PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL,
212 }
213 
214 
215 void PSLIKE_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
216  double aOrient, SHAPE_POLY_SET* aPolygons,
217  OUTLINE_MODE aTraceMode, void* aData )
218 {
219  wxSize size( aSize );
220 
221  if( aTraceMode == FILLED )
222  {
223  SetCurrentLineWidth( 0 );
224  }
225  else
226  {
228  }
229 
230 
231  std::vector< wxPoint > cornerList;
232 
233  for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt )
234  {
235  SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt );
236  cornerList.clear();
237 
238  for( int ii = 0; ii < poly.PointCount(); ++ii )
239  cornerList.emplace_back( poly.CPoint( ii ).x, poly.CPoint( ii ).y );
240 
241  // Close polygon
242  cornerList.push_back( cornerList[0] );
243 
244  PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL,
246  }
247 }
248 
249 
250 void PSLIKE_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
251  double aPadOrient, OUTLINE_MODE aTraceMode, void* aData )
252 {
253  static std::vector< wxPoint > cornerList;
254  cornerList.clear();
255 
256  for( int ii = 0; ii < 4; ii++ )
257  cornerList.push_back( aCorners[ii] );
258 
259  if( aTraceMode == FILLED )
260  {
261  SetCurrentLineWidth( 0 );
262  }
263  else
264  {
266  }
267 
268  for( int ii = 0; ii < 4; ii++ )
269  {
270  RotatePoint( &cornerList[ii], aPadOrient );
271  cornerList[ii] += aPadPos;
272  }
273 
274  cornerList.push_back( cornerList[0] );
275  PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL,
277 }
278 
279 
280 void PSLIKE_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, int aRadius, int aCornerCount,
281  double aOrient, OUTLINE_MODE aTraceMode, void* aData )
282 {
283  // Do nothing
284  wxASSERT( 0 );
285 }
286 
287 
288 std::string PSLIKE_PLOTTER::encodeStringForPlotter( const wxString& aUnicode )
289 {
290  // Write on a std::string a string escaped for postscript/PDF
291  std::string converted;
292 
293  converted += '(';
294 
295  for( unsigned i = 0; i < aUnicode.Len(); i++ )
296  {
297  // Laziness made me use stdio buffering yet another time...
298  wchar_t ch = aUnicode[i];
299 
300  if( ch < 256 )
301  {
302  switch (ch)
303  {
304  // The ~ shouldn't reach the outside
305  case '~':
306  break;
307 
308  // These characters must be escaped
309  case '(':
310  case ')':
311  case '\\':
312  converted += '\\';
314 
315  default:
316  converted += ch;
317  break;
318  }
319  }
320  }
321 
322  converted += ')';
323 
324  return converted;
325 }
326 
327 
328 int PSLIKE_PLOTTER::returnPostscriptTextWidth( const wxString& aText, int aXSize,
329  bool aItalic, bool aBold )
330 {
331  const double *width_table = aBold ? ( aItalic ? hvbo_widths : hvb_widths )
332  : ( aItalic ? hvo_widths : hv_widths );
333  double tally = 0;
334 
335  for( unsigned i = 0; i < aText.length(); i++ )
336  {
337  wchar_t AsciiCode = aText[i];
338 
339  // Skip the negation marks and untabled points.
340  if( AsciiCode != '~' && AsciiCode < 256 )
341  {
342  tally += width_table[AsciiCode];
343  }
344  }
345 
346  // Widths are proportional to height, but height is enlarged by a scaling factor.
347  return KiROUND( aXSize * tally / postscriptTextAscent );
348 }
349 
350 
351 void PSLIKE_PLOTTER::postscriptOverlinePositions( const wxString& aText, int aXSize,
352  bool aItalic, bool aBold,
353  std::vector<int> *pos_pairs )
354 {
355  /* XXX This function is *too* similar to returnPostscriptTextWidth.
356  Consider merging them... */
357  const double *width_table = aBold ? ( aItalic ? hvbo_widths : hvb_widths )
358  : ( aItalic ? hvo_widths : hv_widths );
359  double tally = 0;
360 
361  for( unsigned i = 0; i < aText.length(); i++ )
362  {
363  wchar_t AsciiCode = aText[i];
364 
365  // Skip the negation marks and untabled points
366  if( AsciiCode != '~' && AsciiCode < 256 )
367  {
368  tally += width_table[AsciiCode];
369  }
370  else
371  {
372  if( AsciiCode == '~' )
373  pos_pairs->push_back( KiROUND( aXSize * tally / postscriptTextAscent ) );
374  }
375  }
376 
377  // Special rule: we have to complete the last bar if the ~ aren't matched
378  if( pos_pairs->size() % 2 == 1 )
379  pos_pairs->push_back( KiROUND( aXSize * tally / postscriptTextAscent ) );
380 }
381 
382 
383 void PS_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
384  double aScale, bool aMirror )
385 {
386  wxASSERT( !m_outputFile );
387  m_plotMirror = aMirror;
388  m_plotOffset = aOffset;
389  m_plotScale = aScale;
390  m_IUsPerDecimil = aIusPerDecimil;
391  m_iuPerDeviceUnit = 1.0 / aIusPerDecimil;
392 
393  /* Compute the paper size in IUs */
395  m_paperSize.x *= 10.0 * aIusPerDecimil;
396  m_paperSize.y *= 10.0 * aIusPerDecimil;
397 }
398 
399 
400 void PSLIKE_PLOTTER::computeTextParameters( const wxPoint& aPos,
401  const wxString& aText,
402  int aOrient,
403  const wxSize& aSize,
404  bool aMirror,
405  enum EDA_TEXT_HJUSTIFY_T aH_justify,
406  enum EDA_TEXT_VJUSTIFY_T aV_justify,
407  int aWidth,
408  bool aItalic,
409  bool aBold,
410  double *wideningFactor,
411  double *ctm_a,
412  double *ctm_b,
413  double *ctm_c,
414  double *ctm_d,
415  double *ctm_e,
416  double *ctm_f,
417  double *heightFactor )
418 {
419  // Compute the starting position (compensated for alignment)
420  wxPoint start_pos = aPos;
421 
422  // This is an approximation of the text bounds (in IUs)
423  int tw = returnPostscriptTextWidth( aText, aSize.x, aItalic, aWidth );
424  int th = aSize.y;
425  int dx, dy;
426 
427  switch( aH_justify )
428  {
430  dx = -tw / 2;
431  break;
432 
434  dx = -tw;
435  break;
436 
438  dx = 0;
439  break;
440  }
441 
442  switch( aV_justify )
443  {
445  dy = th / 2;
446  break;
447 
449  dy = th;
450  break;
451 
453  dy = 0;
454  break;
455  }
456 
457  RotatePoint( &dx, &dy, aOrient );
458  RotatePoint( &tw, &th, aOrient );
459  start_pos.x += dx;
460  start_pos.y += dy;
461  DPOINT pos_dev = userToDeviceCoordinates( start_pos );
462  DPOINT sz_dev = userToDeviceSize( aSize );
463 
464  // Now returns the final values... the widening factor
465  *wideningFactor = sz_dev.x / sz_dev.y;
466 
467  // Mirrored texts must be plotted as mirrored!
468  if( m_plotMirror )
469  {
470  *wideningFactor = -*wideningFactor;
471  aOrient = -aOrient;
472  }
473 
474  // The CTM transformation matrix
475  double alpha = DECIDEG2RAD( aOrient );
476  double sinalpha = sin( alpha );
477  double cosalpha = cos( alpha );
478 
479  *ctm_a = cosalpha;
480  *ctm_b = sinalpha;
481  *ctm_c = -sinalpha;
482  *ctm_d = cosalpha;
483  *ctm_e = pos_dev.x;
484  *ctm_f = pos_dev.y;
485 
486  // This is because the letters are less than 1 unit high
487  *heightFactor = sz_dev.y / postscriptTextAscent;
488 }
489 
490 
491 void PS_PLOTTER::SetCurrentLineWidth( int aWidth, void* aData )
492 {
493  wxASSERT( m_outputFile );
494 
495  if( aWidth == DO_NOT_SET_LINE_WIDTH )
496  return;
497  else if( aWidth == USE_DEFAULT_LINE_WIDTH )
499  else if( aWidth == 0 )
500  aWidth = 1;
501 
502  wxASSERT_MSG( aWidth > 0, "Plotter called to set negative pen width" );
503 
504  if( aWidth != GetCurrentLineWidth() )
505  fprintf( m_outputFile, "%g setlinewidth\n", userToDeviceSize( aWidth ) );
506 
507  m_currentPenWidth = aWidth;
508 }
509 
510 
511 void PS_PLOTTER::emitSetRGBColor( double r, double g, double b )
512 {
513  wxASSERT( m_outputFile );
514 
515  // XXX why %.3g ? shouldn't %g suffice? who cares...
516  fprintf( m_outputFile, "%.3g %.3g %.3g setrgbcolor\n", r, g, b );
517 }
518 
519 
521 {
522  switch( dashed )
523  {
525  fprintf( m_outputFile, "[%d %d] 0 setdash\n",
526  (int) GetDashMarkLenIU(), (int) GetDashGapLenIU() );
527  break;
528  case PLOT_DASH_TYPE::DOT:
529  fprintf( m_outputFile, "[%d %d] 0 setdash\n",
530  (int) GetDotMarkLenIU(), (int) GetDashGapLenIU() );
531  break;
533  fprintf( m_outputFile, "[%d %d %d %d] 0 setdash\n",
534  (int) GetDashMarkLenIU(), (int) GetDashGapLenIU(),
535  (int) GetDotMarkLenIU(), (int) GetDashGapLenIU() );
536  break;
537  default:
538  fputs( "solidline\n", m_outputFile );
539  }
540 }
541 
542 
543 void PS_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
544 {
545  DPOINT p1_dev = userToDeviceCoordinates( p1 );
546  DPOINT p2_dev = userToDeviceCoordinates( p2 );
547 
548  SetCurrentLineWidth( width );
549  fprintf( m_outputFile, "%g %g %g %g rect%d\n", p1_dev.x, p1_dev.y,
550  p2_dev.x - p1_dev.x, p2_dev.y - p1_dev.y, getFillId( fill ) );
551 }
552 
553 
554 void PS_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_T fill, int width )
555 {
556  wxASSERT( m_outputFile );
557  DPOINT pos_dev = userToDeviceCoordinates( pos );
558  double radius = userToDeviceSize( diametre / 2.0 );
559 
560  SetCurrentLineWidth( width );
561  fprintf( m_outputFile, "%g %g %g cir%d\n", pos_dev.x, pos_dev.y, radius, getFillId( fill ) );
562 }
563 
564 
565 void PS_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
566  FILL_T fill, int width )
567 {
568  wxASSERT( m_outputFile );
569 
570  if( radius <= 0 )
571  return;
572 
573  if( StAngle > EndAngle )
574  std::swap( StAngle, EndAngle );
575 
576  SetCurrentLineWidth( width );
577 
578  // Calculate start point.
579  DPOINT centre_dev = userToDeviceCoordinates( centre );
580  double radius_dev = userToDeviceSize( radius );
581 
582  if( m_plotMirror )
583  {
585  {
586  StAngle = 1800.0 -StAngle;
587  EndAngle = 1800.0 -EndAngle;
588  std::swap( StAngle, EndAngle );
589  }
590  else
591  {
592  StAngle = -StAngle;
593  EndAngle = -EndAngle;
594  }
595  }
596 
597  fprintf( m_outputFile, "%g %g %g %g %g arc%d\n", centre_dev.x, centre_dev.y,
598  radius_dev, StAngle / 10.0, EndAngle / 10.0, getFillId( fill ) );
599 }
600 
601 
602 void PS_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
603  int aWidth, void * aData )
604 {
605  if( aCornerList.size() <= 1 )
606  return;
607 
608  SetCurrentLineWidth( aWidth );
609 
610  DPOINT pos = userToDeviceCoordinates( aCornerList[0] );
611  fprintf( m_outputFile, "newpath\n%g %g moveto\n", pos.x, pos.y );
612 
613  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
614  {
615  pos = userToDeviceCoordinates( aCornerList[ii] );
616  fprintf( m_outputFile, "%g %g lineto\n", pos.x, pos.y );
617  }
618 
619  // Close/(fill) the path
620  fprintf( m_outputFile, "poly%d\n", getFillId( aFill ) );
621 }
622 
623 
624 void PS_PLOTTER::PlotImage( const wxImage& aImage, const wxPoint& aPos, double aScaleFactor )
625 {
626  wxSize pix_size; // size of the bitmap in pixels
627  pix_size.x = aImage.GetWidth();
628  pix_size.y = aImage.GetHeight();
629  DPOINT drawsize( aScaleFactor * pix_size.x,
630  aScaleFactor * pix_size.y ); // requested size of image
631 
632  // calculate the bottom left corner position of bitmap
633  wxPoint start = aPos;
634  start.x -= drawsize.x / 2; // left
635  start.y += drawsize.y / 2; // bottom (Y axis reversed)
636 
637  // calculate the top right corner position of bitmap
638  wxPoint end;
639  end.x = start.x + drawsize.x;
640  end.y = start.y - drawsize.y;
641 
642  fprintf( m_outputFile, "/origstate save def\n" );
643  fprintf( m_outputFile, "/pix %d string def\n", pix_size.x );
644 
645  // Locate lower-left corner of image
646  DPOINT start_dev = userToDeviceCoordinates( start );
647  fprintf( m_outputFile, "%g %g translate\n", start_dev.x, start_dev.y );
648 
649  // Map image size to device
650  DPOINT end_dev = userToDeviceCoordinates( end );
651  fprintf( m_outputFile, "%g %g scale\n",
652  std::abs(end_dev.x - start_dev.x), std::abs(end_dev.y - start_dev.y));
653 
654  // Dimensions of source image (in pixels
655  fprintf( m_outputFile, "%d %d 8", pix_size.x, pix_size.y );
656 
657  // Map unit square to source
658  fprintf( m_outputFile, " [%d 0 0 %d 0 %d]\n", pix_size.x, -pix_size.y , pix_size.y);
659 
660  // include image data in ps file
661  fprintf( m_outputFile, "{currentfile pix readhexstring pop}\n" );
662 
663  if( m_colorMode )
664  fputs( "false 3 colorimage\n", m_outputFile );
665  else
666  fputs( "image\n", m_outputFile );
667 
668  // Single data source, 3 colors, Output RGB data (hexadecimal)
669  // (or the same downscaled to gray)
670  int jj = 0;
671 
672  for( int yy = 0; yy < pix_size.y; yy ++ )
673  {
674  for( int xx = 0; xx < pix_size.x; xx++, jj++ )
675  {
676  if( jj >= 16 )
677  {
678  jj = 0;
679  fprintf( m_outputFile, "\n");
680  }
681 
682  int red, green, blue;
683  red = aImage.GetRed( xx, yy) & 0xFF;
684  green = aImage.GetGreen( xx, yy) & 0xFF;
685  blue = aImage.GetBlue( xx, yy) & 0xFF;
686 
687  // PS doesn't support alpha, so premultiply against white background
688  if( aImage.HasAlpha() )
689  {
690  unsigned char alpha = aImage.GetAlpha( xx, yy ) & 0xFF;
691 
692  if( alpha < 0xFF )
693  {
694  float a = 1.0 - ( (float) alpha / 255.0 );
695  red = ( int )( red + ( a * 0xFF ) ) & 0xFF;
696  green = ( int )( green + ( a * 0xFF ) ) & 0xFF;
697  blue = ( int )( blue + ( a * 0xFF ) ) & 0xFF;
698  }
699  }
700 
701  if( aImage.HasMask() )
702  {
703  if( red == aImage.GetMaskRed() && green == aImage.GetMaskGreen()
704  && blue == aImage.GetMaskBlue() )
705  {
706  red = 0xFF;
707  green = 0xFF;
708  blue = 0xFF;
709  }
710  }
711 
712  if( m_colorMode )
713  {
714  fprintf( m_outputFile, "%2.2X%2.2X%2.2X", red, green, blue );
715  }
716  else
717  {
718  // Greyscale conversion (CIE 1931)
719  unsigned char grey = KiROUND( red * 0.2126 + green * 0.7152 + blue * 0.0722 );
720 
721  fprintf( m_outputFile, "%2.2X", grey );
722  }
723  }
724  }
725 
726  fprintf( m_outputFile, "\n");
727  fprintf( m_outputFile, "origstate restore\n" );
728 }
729 
730 
731 void PS_PLOTTER::PenTo( const wxPoint& pos, char plume )
732 {
733  wxASSERT( m_outputFile );
734 
735  if( plume == 'Z' )
736  {
737  if( m_penState != 'Z' )
738  {
739  fputs( "stroke\n", m_outputFile );
740  m_penState = 'Z';
741  m_penLastpos.x = -1;
742  m_penLastpos.y = -1;
743  }
744 
745  return;
746  }
747 
748  if( m_penState == 'Z' )
749  {
750  fputs( "newpath\n", m_outputFile );
751  }
752 
753  if( m_penState != plume || pos != m_penLastpos )
754  {
755  DPOINT pos_dev = userToDeviceCoordinates( pos );
756  fprintf( m_outputFile, "%g %g %sto\n",
757  pos_dev.x, pos_dev.y,
758  ( plume=='D' ) ? "line" : "move" );
759  }
760 
761  m_penState = plume;
762  m_penLastpos = pos;
763 }
764 
765 
767 {
768  wxASSERT( m_outputFile );
769  wxString msg;
770 
771  static const char* PSMacro[] =
772  {
773  "%%BeginProlog\n",
774  "/line { newpath moveto lineto stroke } bind def\n",
775  "/cir0 { newpath 0 360 arc stroke } bind def\n",
776  "/cir1 { newpath 0 360 arc gsave fill grestore stroke } bind def\n",
777  "/cir2 { newpath 0 360 arc gsave fill grestore stroke } bind def\n",
778  "/arc0 { newpath arc stroke } bind def\n",
779  "/arc1 { newpath 4 index 4 index moveto arc closepath gsave fill\n",
780  " grestore stroke } bind def\n",
781  "/arc2 { newpath 4 index 4 index moveto arc closepath gsave fill\n",
782  " grestore stroke } bind def\n",
783  "/poly0 { stroke } bind def\n",
784  "/poly1 { closepath gsave fill grestore stroke } bind def\n",
785  "/poly2 { closepath gsave fill grestore stroke } bind def\n",
786  "/rect0 { rectstroke } bind def\n",
787  "/rect1 { rectfill } bind def\n",
788  "/rect2 { rectfill } bind def\n",
789  "/linemode0 { 0 setlinecap 0 setlinejoin 0 setlinewidth } bind def\n",
790  "/linemode1 { 1 setlinecap 1 setlinejoin } bind def\n",
791  "/dashedline { [200] 100 setdash } bind def\n",
792  "/solidline { [] 0 setdash } bind def\n",
793 
794  // This is for 'hidden' text (search anchors for PDF)
795  "/phantomshow { moveto\n",
796  " /KicadFont findfont 0.000001 scalefont setfont\n",
797  " show } bind def\n",
798 
799  // This is for regular postscript text
800  "/textshow { gsave\n",
801  " findfont exch scalefont setfont concat 1 scale 0 0 moveto show\n",
802  " } bind def\n",
803 
804  // Utility for getting Latin1 encoded fonts
805  "/reencodefont {\n",
806  " findfont dup length dict begin\n",
807  " { 1 index /FID ne\n",
808  " { def }\n",
809  " { pop pop } ifelse\n",
810  " } forall\n",
811  " /Encoding ISOLatin1Encoding def\n",
812  " currentdict\n",
813  " end } bind def\n"
814 
815  // Remap AdobeStandard fonts to Latin1
816  "/KicadFont /Helvetica reencodefont definefont pop\n",
817  "/KicadFont-Bold /Helvetica-Bold reencodefont definefont pop\n",
818  "/KicadFont-Oblique /Helvetica-Oblique reencodefont definefont pop\n",
819  "/KicadFont-BoldOblique /Helvetica-BoldOblique reencodefont definefont pop\n",
820  "%%EndProlog\n",
821  nullptr
822  };
823 
824  time_t time1970 = time( nullptr );
825 
826  fputs( "%!PS-Adobe-3.0\n", m_outputFile ); // Print header
827 
828  fprintf( m_outputFile, "%%%%Creator: %s\n", TO_UTF8( m_creator ) );
829 
830  /* A "newline" character ("\n") is not included in the following string,
831  because it is provided by the ctime() function. */
832  fprintf( m_outputFile, "%%%%CreationDate: %s", ctime( &time1970 ) );
833  fprintf( m_outputFile, "%%%%Title: %s\n", encodeStringForPlotter( m_title ).c_str() );
834  fprintf( m_outputFile, "%%%%Pages: 1\n" );
835  fprintf( m_outputFile, "%%%%PageOrder: Ascend\n" );
836 
837  // Print boundary box in 1/72 pixels per inch, box is in mils
838  const double BIGPTsPERMIL = 0.072;
839 
840  /* The coordinates of the lower left corner of the boundary
841  box need to be "rounded down", but the coordinates of its
842  upper right corner need to be "rounded up" instead. */
843  wxSize psPaperSize = m_pageInfo.GetSizeMils();
844 
845  if( !m_pageInfo.IsPortrait() )
846  psPaperSize.Set( m_pageInfo.GetHeightMils(), m_pageInfo.GetWidthMils() );
847 
848  fprintf( m_outputFile, "%%%%BoundingBox: 0 0 %d %d\n",
849  (int) ceil( psPaperSize.x * BIGPTsPERMIL ),
850  (int) ceil( psPaperSize.y * BIGPTsPERMIL ) );
851 
852  // Specify the size of the sheet and the name associated with that size.
853  // (If the "User size" option has been selected for the sheet size,
854  // identify the sheet size as "Custom" (rather than as "User"), but
855  // otherwise use the name assigned by KiCad for each sheet size.)
856  //
857  // (The Document Structuring Convention also supports sheet weight,
858  // sheet color, and sheet type properties being specified within a
859  // %%DocumentMedia comment, but they are not being specified here;
860  // a zero and two null strings are subsequently provided instead.)
861  //
862  // (NOTE: m_Size.y is *supposed* to be listed before m_Size.x;
863  // the order in which they are specified is not wrong!)
864  // Also note pageSize is given in mils, not in internal units and must be
865  // converted to internal units.
866 
867  if( m_pageInfo.IsCustom() )
868  {
869  fprintf( m_outputFile, "%%%%DocumentMedia: Custom %d %d 0 () ()\n",
870  KiROUND( psPaperSize.x * BIGPTsPERMIL ),
871  KiROUND( psPaperSize.y * BIGPTsPERMIL ) );
872  }
873  else // a standard paper size
874  {
875  fprintf( m_outputFile, "%%%%DocumentMedia: %s %d %d 0 () ()\n",
877  KiROUND( psPaperSize.x * BIGPTsPERMIL ),
878  KiROUND( psPaperSize.y * BIGPTsPERMIL ) );
879  }
880 
881  if( m_pageInfo.IsPortrait() )
882  fprintf( m_outputFile, "%%%%Orientation: Portrait\n" );
883  else
884  fprintf( m_outputFile, "%%%%Orientation: Landscape\n" );
885 
886  fprintf( m_outputFile, "%%%%EndComments\n" );
887 
888  // Now specify various other details.
889 
890  for( int ii = 0; PSMacro[ii] != nullptr; ii++ )
891  {
892  fputs( PSMacro[ii], m_outputFile );
893  }
894 
895  // The following string has been specified here (rather than within
896  // PSMacro[]) to highlight that it has been provided to ensure that the
897  // contents of the postscript file comply with the details specified
898  // within the Document Structuring Convention.
899  fputs( "%%Page: 1 1\n"
900  "%%BeginPageSetup\n"
901  "gsave\n"
902  "0.0072 0.0072 scale\n" // Configure postscript for decimils coordinates
903  "linemode1\n", m_outputFile );
904 
905 
906  // Rototranslate the coordinate to achieve the landscape layout
907  if( !m_pageInfo.IsPortrait() )
908  fprintf( m_outputFile, "%d 0 translate 90 rotate\n", 10 * psPaperSize.x );
909 
910  // Apply the user fine scale adjustments
911  if( plotScaleAdjX != 1.0 || plotScaleAdjY != 1.0 )
912  fprintf( m_outputFile, "%g %g scale\n", plotScaleAdjX, plotScaleAdjY );
913 
914  // Set default line width
915  fprintf( m_outputFile, "%g setlinewidth\n",
917  fputs( "%%EndPageSetup\n", m_outputFile );
918 
919  return true;
920 }
921 
922 
924 {
925  wxASSERT( m_outputFile );
926  fputs( "showpage\n"
927  "grestore\n"
928  "%%EOF\n", m_outputFile );
929  fclose( m_outputFile );
930  m_outputFile = nullptr;
931 
932  return true;
933 }
934 
935 
936 
937 void PS_PLOTTER::Text( const wxPoint& aPos,
938  const COLOR4D& aColor,
939  const wxString& aText,
940  double aOrient,
941  const wxSize& aSize,
942  enum EDA_TEXT_HJUSTIFY_T aH_justify,
943  enum EDA_TEXT_VJUSTIFY_T aV_justify,
944  int aWidth,
945  bool aItalic,
946  bool aBold,
947  bool aMultilineAllowed,
948  void* aData )
949 {
950  SetCurrentLineWidth( aWidth );
951  SetColor( aColor );
952 
953  // Draw the hidden postscript text (if requested)
955  {
956  std::string ps_test = encodeStringForPlotter( aText );
957  DPOINT pos_dev = userToDeviceCoordinates( aPos );
958  fprintf( m_outputFile, "%s %g %g phantomshow\n", ps_test.c_str(), pos_dev.x, pos_dev.y );
959  }
960 
961  PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth,
962  aItalic, aBold, aMultilineAllowed );
963 }
964 
965 
969 const double hv_widths[256] = {
970  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
971  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
972  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
973  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
974  0.278, 0.278, 0.355, 0.556, 0.556, 0.889, 0.667, 0.191,
975  0.333, 0.333, 0.389, 0.584, 0.278, 0.333, 0.278, 0.278,
976  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556,
977  0.556, 0.556, 0.278, 0.278, 0.584, 0.584, 0.584, 0.556,
978  1.015, 0.667, 0.667, 0.722, 0.722, 0.667, 0.611, 0.778,
979  0.722, 0.278, 0.500, 0.667, 0.556, 0.833, 0.722, 0.778,
980  0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944,
981  0.667, 0.667, 0.611, 0.278, 0.278, 0.278, 0.469, 0.556,
982  0.333, 0.556, 0.556, 0.500, 0.556, 0.556, 0.278, 0.556,
983  0.556, 0.222, 0.222, 0.500, 0.222, 0.833, 0.556, 0.556,
984  0.556, 0.556, 0.333, 0.500, 0.278, 0.556, 0.500, 0.722,
985  0.500, 0.500, 0.500, 0.334, 0.260, 0.334, 0.584, 0.278,
986  0.278, 0.278, 0.222, 0.556, 0.333, 1.000, 0.556, 0.556,
987  0.333, 1.000, 0.667, 0.333, 1.000, 0.278, 0.278, 0.278,
988  0.278, 0.222, 0.222, 0.333, 0.333, 0.350, 0.556, 1.000,
989  0.333, 1.000, 0.500, 0.333, 0.944, 0.278, 0.278, 0.667,
990  0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.260, 0.556,
991  0.333, 0.737, 0.370, 0.556, 0.584, 0.333, 0.737, 0.333,
992  0.400, 0.584, 0.333, 0.333, 0.333, 0.556, 0.537, 0.278,
993  0.333, 0.333, 0.365, 0.556, 0.834, 0.834, 0.834, 0.611,
994  0.667, 0.667, 0.667, 0.667, 0.667, 0.667, 1.000, 0.722,
995  0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278,
996  0.722, 0.722, 0.778, 0.778, 0.778, 0.778, 0.778, 0.584,
997  0.778, 0.722, 0.722, 0.722, 0.722, 0.667, 0.667, 0.611,
998  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.889, 0.500,
999  0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278,
1000  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.584,
1001  0.611, 0.556, 0.556, 0.556, 0.556, 0.500, 0.556, 0.500
1002 };
1003 
1004 
1008 const double hvb_widths[256] = {
1009  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1010  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1011  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1012  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1013  0.278, 0.333, 0.474, 0.556, 0.556, 0.889, 0.722, 0.238,
1014  0.333, 0.333, 0.389, 0.584, 0.278, 0.333, 0.278, 0.278,
1015  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556,
1016  0.556, 0.556, 0.333, 0.333, 0.584, 0.584, 0.584, 0.611,
1017  0.975, 0.722, 0.722, 0.722, 0.722, 0.667, 0.611, 0.778,
1018  0.722, 0.278, 0.556, 0.722, 0.611, 0.833, 0.722, 0.778,
1019  0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944,
1020  0.667, 0.667, 0.611, 0.333, 0.278, 0.333, 0.584, 0.556,
1021  0.333, 0.556, 0.611, 0.556, 0.611, 0.556, 0.333, 0.611,
1022  0.611, 0.278, 0.278, 0.556, 0.278, 0.889, 0.611, 0.611,
1023  0.611, 0.611, 0.389, 0.556, 0.333, 0.611, 0.556, 0.778,
1024  0.556, 0.556, 0.500, 0.389, 0.280, 0.389, 0.584, 0.278,
1025  0.278, 0.278, 0.278, 0.556, 0.500, 1.000, 0.556, 0.556,
1026  0.333, 1.000, 0.667, 0.333, 1.000, 0.278, 0.278, 0.278,
1027  0.278, 0.278, 0.278, 0.500, 0.500, 0.350, 0.556, 1.000,
1028  0.333, 1.000, 0.556, 0.333, 0.944, 0.278, 0.278, 0.667,
1029  0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.280, 0.556,
1030  0.333, 0.737, 0.370, 0.556, 0.584, 0.333, 0.737, 0.333,
1031  0.400, 0.584, 0.333, 0.333, 0.333, 0.611, 0.556, 0.278,
1032  0.333, 0.333, 0.365, 0.556, 0.834, 0.834, 0.834, 0.611,
1033  0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 1.000, 0.722,
1034  0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278,
1035  0.722, 0.722, 0.778, 0.778, 0.778, 0.778, 0.778, 0.584,
1036  0.778, 0.722, 0.722, 0.722, 0.722, 0.667, 0.667, 0.611,
1037  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.889, 0.556,
1038  0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278,
1039  0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.584,
1040  0.611, 0.611, 0.611, 0.611, 0.611, 0.556, 0.611, 0.556
1041 };
1042 
1043 
1047 const double hvo_widths[256] = {
1048  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1049  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1050  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1051  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1052  0.278, 0.278, 0.355, 0.556, 0.556, 0.889, 0.667, 0.191,
1053  0.333, 0.333, 0.389, 0.584, 0.278, 0.333, 0.278, 0.278,
1054  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556,
1055  0.556, 0.556, 0.278, 0.278, 0.584, 0.584, 0.584, 0.556,
1056  1.015, 0.667, 0.667, 0.722, 0.722, 0.667, 0.611, 0.778,
1057  0.722, 0.278, 0.500, 0.667, 0.556, 0.833, 0.722, 0.778,
1058  0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944,
1059  0.667, 0.667, 0.611, 0.278, 0.278, 0.278, 0.469, 0.556,
1060  0.333, 0.556, 0.556, 0.500, 0.556, 0.556, 0.278, 0.556,
1061  0.556, 0.222, 0.222, 0.500, 0.222, 0.833, 0.556, 0.556,
1062  0.556, 0.556, 0.333, 0.500, 0.278, 0.556, 0.500, 0.722,
1063  0.500, 0.500, 0.500, 0.334, 0.260, 0.334, 0.584, 0.278,
1064  0.278, 0.278, 0.222, 0.556, 0.333, 1.000, 0.556, 0.556,
1065  0.333, 1.000, 0.667, 0.333, 1.000, 0.278, 0.278, 0.278,
1066  0.278, 0.222, 0.222, 0.333, 0.333, 0.350, 0.556, 1.000,
1067  0.333, 1.000, 0.500, 0.333, 0.944, 0.278, 0.278, 0.667,
1068  0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.260, 0.556,
1069  0.333, 0.737, 0.370, 0.556, 0.584, 0.333, 0.737, 0.333,
1070  0.400, 0.584, 0.333, 0.333, 0.333, 0.556, 0.537, 0.278,
1071  0.333, 0.333, 0.365, 0.556, 0.834, 0.834, 0.834, 0.611,
1072  0.667, 0.667, 0.667, 0.667, 0.667, 0.667, 1.000, 0.722,
1073  0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278,
1074  0.722, 0.722, 0.778, 0.778, 0.778, 0.778, 0.778, 0.584,
1075  0.778, 0.722, 0.722, 0.722, 0.722, 0.667, 0.667, 0.611,
1076  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.889, 0.500,
1077  0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278,
1078  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.584,
1079  0.611, 0.556, 0.556, 0.556, 0.556, 0.500, 0.556, 0.500
1080 };
1081 
1082 
1086 const double hvbo_widths[256] = {
1087  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1088  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1089  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1090  0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278, 0.278,
1091  0.278, 0.333, 0.474, 0.556, 0.556, 0.889, 0.722, 0.238,
1092  0.333, 0.333, 0.389, 0.584, 0.278, 0.333, 0.278, 0.278,
1093  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556,
1094  0.556, 0.556, 0.333, 0.333, 0.584, 0.584, 0.584, 0.611,
1095  0.975, 0.722, 0.722, 0.722, 0.722, 0.667, 0.611, 0.778,
1096  0.722, 0.278, 0.556, 0.722, 0.611, 0.833, 0.722, 0.778,
1097  0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944,
1098  0.667, 0.667, 0.611, 0.333, 0.278, 0.333, 0.584, 0.556,
1099  0.333, 0.556, 0.611, 0.556, 0.611, 0.556, 0.333, 0.611,
1100  0.611, 0.278, 0.278, 0.556, 0.278, 0.889, 0.611, 0.611,
1101  0.611, 0.611, 0.389, 0.556, 0.333, 0.611, 0.556, 0.778,
1102  0.556, 0.556, 0.500, 0.389, 0.280, 0.389, 0.584, 0.278,
1103  0.278, 0.278, 0.278, 0.556, 0.500, 1.000, 0.556, 0.556,
1104  0.333, 1.000, 0.667, 0.333, 1.000, 0.278, 0.278, 0.278,
1105  0.278, 0.278, 0.278, 0.500, 0.500, 0.350, 0.556, 1.000,
1106  0.333, 1.000, 0.556, 0.333, 0.944, 0.278, 0.278, 0.667,
1107  0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.280, 0.556,
1108  0.333, 0.737, 0.370, 0.556, 0.584, 0.333, 0.737, 0.333,
1109  0.400, 0.584, 0.333, 0.333, 0.333, 0.611, 0.556, 0.278,
1110  0.333, 0.333, 0.365, 0.556, 0.834, 0.834, 0.834, 0.611,
1111  0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 1.000, 0.722,
1112  0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278,
1113  0.722, 0.722, 0.778, 0.778, 0.778, 0.778, 0.778, 0.584,
1114  0.778, 0.722, 0.722, 0.722, 0.722, 0.667, 0.667, 0.611,
1115  0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.889, 0.556,
1116  0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278,
1117  0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.584,
1118  0.611, 0.611, 0.611, 0.611, 0.611, 0.556, 0.611, 0.556
1119 };
const double hvb_widths[256]
Character widths for Helvetica-Bold.
const double hv_widths[256]
Character widths for Helvetica.
Definition: PS_plotter.cpp:969
virtual void SetViewport(const wxPoint &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
Set the plot offset and scaling for the current plot.
Definition: PS_plotter.cpp:383
OUTLINE_MODE
Definition: outline_mode.h:24
double GetDotMarkLenIU() const
Definition: plotter.cpp:133
EDA_TEXT_HJUSTIFY_T
Definition: eda_text.h:82
int OutlineCount() const
Return the number of vertices in a given outline/hole.
virtual void emitSetRGBColor(double r, double g, double b) override
Virtual primitive for emitting the setrgbcolor operator.
Definition: PS_plotter.cpp:511
int GetHeightMils() const
Definition: page_info.h:133
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=nullptr)=0
Draw a polygon ( filled or not ).
virtual void PenTo(const wxPoint &pos, char plume) override
Moveto/lineto primitive, moves the 'pen' to the specified direction.
Definition: PS_plotter.cpp:731
int color
Definition: DXF_plotter.cpp:57
virtual bool EndPlot() override
Definition: PS_plotter.cpp:923
FILE * m_outputFile
Output file.
Definition: plotter.h:590
double m_iuPerDeviceUnit
Definition: plotter.h:581
virtual void FlashPadRect(const wxPoint &aPadPos, const wxSize &aSize, double aPadOrient, OUTLINE_MODE aTraceMode, void *aData) override
Definition: PS_plotter.cpp:137
virtual void Text(const wxPoint &aPos, const COLOR4D &aColor, const wxString &aText, double aOrient, const wxSize &aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed=false, void *aData=nullptr) override
Draw text with the plotter.
Definition: PS_plotter.cpp:937
virtual void SetCurrentLineWidth(int width, void *aData=nullptr) override
Set the current line width (in IUs) for the next plot.
Definition: PS_plotter.cpp:491
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
const wxString & GetType() const
Definition: page_info.h:94
const double hvo_widths[256]
Character widths for Helvetica-Oblique.
bool IsCustom() const
Definition: page_info.cpp:180
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
PLOT_TEXT_MODE m_textMode
How to draw text.
double m_IUsPerDecimil
Definition: plotter.h:579
static int getFillId(FILL_T aFill)
Definition: PS_plotter.cpp:50
int PointCount() const
Return the number of points (vertices) in this line chain.
virtual std::string encodeStringForPlotter(const wxString &aUnicode)
convert a wxString unicode string to a char string compatible with the accepted string plotter format...
Definition: PS_plotter.cpp:288
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, OUTLINE_MODE tracemode, void *aData)
Definition: plotter.cpp:519
FILL_T
Definition: eda_shape.h:53
This file contains miscellaneous commonly used macros and functions.
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle with rounded corners and/or chamfered corners to a polygon.
virtual void FlashRegularPolygon(const wxPoint &aShapePos, int aDiameter, int aCornerCount, double aOrient, OUTLINE_MODE aTraceMode, void *aData) override
Flash a regular polygon.
Definition: PS_plotter.cpp:280
double GetDashGapLenIU() const
Definition: plotter.cpp:145
double m_plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
Definition: plotter.h:573
virtual int GetCurrentLineWidth() const
Definition: plotter.h:168
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
virtual bool StartPlot() override
The code within this function (and the CloseFilePS function) creates postscript files whose contents ...
Definition: PS_plotter.cpp:766
virtual void FlashPadCircle(const wxPoint &aPadPos, int aDiameter, OUTLINE_MODE aTraceMode, void *aData) override
Definition: PS_plotter.cpp:120
static const int USE_DEFAULT_LINE_WIDTH
Definition: plotter.h:126
virtual void SetColor(const COLOR4D &color) override
The SetColor implementation is split with the subclasses: The PSLIKE computes the rgb values,...
Definition: PS_plotter.cpp:62
virtual void FlashPadTrapez(const wxPoint &aPadPos, const wxPoint *aCorners, double aPadOrient, OUTLINE_MODE aTraceMode, void *aData) override
Flash a trapezoidal pad.
Definition: PS_plotter.cpp:250
bool m_plotMirror
Definition: plotter.h:584
bool m_colorMode
Definition: plotter.h:593
int m_currentPenWidth
Definition: plotter.h:595
T AddAngles(T a1, T2 a2)
Add two angles (keeping the result normalized). T2 is here.
Definition: trigo.h:341
virtual void emitSetRGBColor(double r, double g, double b)=0
Virtual primitive for emitting the setrgbcolor operator.
Represent a set of closed polygons.
int returnPostscriptTextWidth(const wxString &aText, int aXSize, bool aItalic, bool aBold)
Sister function for the GraphicTextWidth in drawtxt.cpp Does the same processing (i....
Definition: PS_plotter.cpp:328
SHAPE_LINE_CHAIN & Outline(int aIndex)
wxString m_title
Definition: plotter.h:601
virtual void Arc(const wxPoint &centre, double StAngle, double EndAngle, int rayon, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH) override
Generic fallback: arc rendered as a polyline.
Definition: PS_plotter.cpp:565
wxPoint m_penLastpos
Definition: plotter.h:597
virtual void Circle(const wxPoint &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH) override
Definition: PS_plotter.cpp:554
RENDER_SETTINGS * m_renderSettings
Definition: plotter.h:607
const wxSize & GetSizeMils() const
Definition: page_info.h:135
virtual DPOINT userToDeviceSize(const wxSize &size)
Modify size according to the plotter scale factors (wxSize version, returns a DPOINT).
Definition: plotter.cpp:117
bool m_negativeMode
Definition: plotter.h:594
E_SERIE r
Definition: eserie.cpp:41
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=nullptr) override
Draw a polygon ( filled or not ).
Definition: PS_plotter.cpp:602
PLOT_DASH_TYPE
Dashed line types.
Definition: plotter.h:104
static const double postscriptTextAscent
Height of the postscript font (from the AFM)
Plotting engines similar to ps (PostScript, Gerber, svg)
EDA_TEXT_VJUSTIFY_T
Definition: eda_text.h:89
Definition: color4d.h:48
virtual DPOINT userToDeviceCoordinates(const wxPoint &aCoordinate)
Modify coordinates according to the orientation, scale factor, and offsets trace.
Definition: plotter.cpp:92
virtual void PlotImage(const wxImage &aImage, const wxPoint &aPos, double aScaleFactor) override
PostScript-likes at the moment are the only plot engines supporting bitmaps.
Definition: PS_plotter.cpp:624
wxPoint m_plotOffset
Definition: plotter.h:583
const double hvbo_widths[256]
Character widths for Helvetica-BoldOblique.
virtual void FlashPadRoundRect(const wxPoint &aPadPos, const wxSize &aSize, int aCornerRadius, double aOrient, OUTLINE_MODE aTraceMode, void *aData) override
Definition: PS_plotter.cpp:178
bool IsPortrait() const
Definition: page_info.h:117
virtual void Rect(const wxPoint &p1, const wxPoint &p2, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH) override
Definition: PS_plotter.cpp:543
PAGE_INFO m_pageInfo
Definition: plotter.h:602
double GetDashMarkLenIU() const
Definition: plotter.cpp:139
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
double plotScaleAdjX
Fine user scale adjust ( = 1.0 if no correction)
virtual void FlashPadCustom(const wxPoint &aPadPos, const wxSize &aSize, double aOrient, SHAPE_POLY_SET *aPolygons, OUTLINE_MODE aTraceMode, void *aData) override
Definition: PS_plotter.cpp:215
double DECIDEG2RAD(double deg)
Definition: trigo.h:233
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:73
int GetPlotterArcHighDef() const
Definition: plotter.h:228
char m_penState
Definition: plotter.h:596
void postscriptOverlinePositions(const wxString &aText, int aXSize, bool aItalic, bool aBold, std::vector< int > *pos_pairs)
Computes the x coordinates for the overlining in a string of text.
Definition: PS_plotter.cpp:351
int GetDefaultPenWidth() const
virtual void Text(const wxPoint &aPos, const COLOR4D &aColor, const wxString &aText, double aOrient, const wxSize &aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed=false, void *aData=nullptr)
Draw text with the plotter.
Definition: gr_text.cpp:219
constexpr int delta
void computeTextParameters(const wxPoint &aPos, const wxString &aText, int aOrient, const wxSize &aSize, bool aMirror, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, double *wideningFactor, double *ctm_a, double *ctm_b, double *ctm_c, double *ctm_d, double *ctm_e, double *ctm_f, double *heightFactor)
This is the core for postscript/PDF text alignment.
Definition: PS_plotter.cpp:400
static const int DO_NOT_SET_LINE_WIDTH
Definition: plotter.h:125
wxSize m_paperSize
Definition: plotter.h:603
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
void sketchOval(const wxPoint &pos, const wxSize &size, double orient, int width)
Definition: plotter.cpp:475
virtual void Circle(const wxPoint &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
int GetWidthMils() const
Definition: page_info.h:130
bool m_mirrorIsHorizontal
Definition: plotter.h:586
virtual void FlashPadOval(const wxPoint &aPadPos, const wxSize &aSize, double aPadOrient, OUTLINE_MODE aTraceMode, void *aData) override
Definition: PS_plotter.cpp:90
wxString m_creator
Definition: plotter.h:599
virtual void SetDash(PLOT_DASH_TYPE dashed) override
PostScript supports dashed lines.
Definition: PS_plotter.cpp:520
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103