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