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