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