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