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