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