github.com/unidoc/unipdf/v3@v3.55.0/contentstream/draw/draw.go (about)

     1  //
     2  // Copyright 2020 FoxyUtils ehf. All rights reserved.
     3  //
     4  // This is a commercial product and requires a license to operate.
     5  // A trial license can be obtained at https://unidoc.io
     6  //
     7  // DO NOT EDIT: generated by unitwist Go source code obfuscator.
     8  //
     9  // Use of this source code is governed by the UniDoc End User License Agreement
    10  // terms that can be accessed at https://unidoc.io/eula/
    11  
    12  // Package draw has handy features for defining paths which can be used to draw content on a PDF page.  Handles
    13  // defining paths as points, vector calculations and conversion to PDF content stream data which can be used in
    14  // page content streams and XObject forms and thus also in annotation appearance streams.
    15  //
    16  // Also defines utility functions for drawing common shapes such as rectangles, lines and circles (ovals).
    17  package draw ;import (_gf "fmt";_gg "github.com/unidoc/unipdf/v3/contentstream";_c "github.com/unidoc/unipdf/v3/core";_e "github.com/unidoc/unipdf/v3/internal/transform";_gfc "github.com/unidoc/unipdf/v3/model";_g "math";);
    18  
    19  // DrawPathWithCreator makes the path with the content creator.
    20  // Adds the PDF commands to draw the path to the creator instance.
    21  func DrawPathWithCreator (path Path ,creator *_gg .ContentCreator ){for _gfd ,_ebb :=range path .Points {if _gfd ==0{creator .Add_m (_ebb .X ,_ebb .Y );}else {creator .Add_l (_ebb .X ,_ebb .Y );};};};
    22  
    23  // Offset shifts the Bezier path with the specified offsets.
    24  func (_da CubicBezierPath )Offset (offX ,offY float64 )CubicBezierPath {for _gb ,_cf :=range _da .Curves {_da .Curves [_gb ]=_cf .AddOffsetXY (offX ,offY );};return _da ;};
    25  
    26  // Circle represents a circle shape with fill and border properties that can be drawn to a PDF content stream.
    27  type Circle struct{X float64 ;Y float64 ;Width float64 ;Height float64 ;FillEnabled bool ;FillColor _gfc .PdfColor ;BorderEnabled bool ;BorderWidth float64 ;BorderColor _gfc .PdfColor ;Opacity float64 ;};
    28  
    29  // Add shifts the coordinates of the point with dx, dy and returns the result.
    30  func (_fda Point )Add (dx ,dy float64 )Point {_fda .X +=dx ;_fda .Y +=dy ;return _fda };
    31  
    32  // GetBoundingBox returns the bounding box of the path.
    33  func (_aac Path )GetBoundingBox ()BoundingBox {_eg :=BoundingBox {};_ddg :=0.0;_cef :=0.0;_fd :=0.0;_gdc :=0.0;for _ag ,_fca :=range _aac .Points {if _ag ==0{_ddg =_fca .X ;_cef =_fca .X ;_fd =_fca .Y ;_gdc =_fca .Y ;continue ;};if _fca .X < _ddg {_ddg =_fca .X ;
    34  };if _fca .X > _cef {_cef =_fca .X ;};if _fca .Y < _fd {_fd =_fca .Y ;};if _fca .Y > _gdc {_gdc =_fca .Y ;};};_eg .X =_ddg ;_eg .Y =_fd ;_eg .Width =_cef -_ddg ;_eg .Height =_gdc -_fd ;return _eg ;};
    35  
    36  // Path consists of straight line connections between each point defined in an array of points.
    37  type Path struct{Points []Point ;};
    38  
    39  // AppendPoint adds the specified point to the path.
    40  func (_fc Path )AppendPoint (point Point )Path {_fc .Points =append (_fc .Points ,point );return _fc };
    41  
    42  // Add adds the specified vector to the current one and returns the result.
    43  func (_cfc Vector )Add (other Vector )Vector {_cfc .Dx +=other .Dx ;_cfc .Dy +=other .Dy ;return _cfc };
    44  
    45  // AppendCurve appends the specified Bezier curve to the path.
    46  func (_dc CubicBezierPath )AppendCurve (curve CubicBezierCurve )CubicBezierPath {_dc .Curves =append (_dc .Curves ,curve );return _dc ;};
    47  
    48  // ToPdfRectangle returns the bounding box as a PDF rectangle.
    49  func (_cc BoundingBox )ToPdfRectangle ()*_gfc .PdfRectangle {return &_gfc .PdfRectangle {Llx :_cc .X ,Lly :_cc .Y ,Urx :_cc .X +_cc .Width ,Ury :_cc .Y +_cc .Height };};
    50  
    51  // LineStyle refers to how the line will be created.
    52  type LineStyle int ;
    53  
    54  // GetBounds returns the bounding box of the Bezier curve.
    55  func (_ggg CubicBezierCurve )GetBounds ()_gfc .PdfRectangle {_ee :=_ggg .P0 .X ;_b :=_ggg .P0 .X ;_af :=_ggg .P0 .Y ;_ed :=_ggg .P0 .Y ;for _bf :=0.0;_bf <=1.0;_bf +=0.001{Rx :=_ggg .P0 .X *_g .Pow (1-_bf ,3)+_ggg .P1 .X *3*_bf *_g .Pow (1-_bf ,2)+_ggg .P2 .X *3*_g .Pow (_bf ,2)*(1-_bf )+_ggg .P3 .X *_g .Pow (_bf ,3);
    56  Ry :=_ggg .P0 .Y *_g .Pow (1-_bf ,3)+_ggg .P1 .Y *3*_bf *_g .Pow (1-_bf ,2)+_ggg .P2 .Y *3*_g .Pow (_bf ,2)*(1-_bf )+_ggg .P3 .Y *_g .Pow (_bf ,3);if Rx < _ee {_ee =Rx ;};if Rx > _b {_b =Rx ;};if Ry < _af {_af =Ry ;};if Ry > _ed {_ed =Ry ;};};_df :=_gfc .PdfRectangle {};
    57  _df .Llx =_ee ;_df .Lly =_af ;_df .Urx =_b ;_df .Ury =_ed ;return _df ;};
    58  
    59  // Offset shifts the path with the specified offsets.
    60  func (_bfa Path )Offset (offX ,offY float64 )Path {for _cde ,_cdb :=range _bfa .Points {_bfa .Points [_cde ]=_cdb .Add (offX ,offY );};return _bfa ;};
    61  
    62  // Line defines a line shape between point 1 (X1,Y1) and point 2 (X2,Y2).  The line ending styles can be none (regular line),
    63  // or arrows at either end.  The line also has a specified width, color and opacity.
    64  type Line struct{X1 float64 ;Y1 float64 ;X2 float64 ;Y2 float64 ;LineColor _gfc .PdfColor ;Opacity float64 ;LineWidth float64 ;LineEndingStyle1 LineEndingStyle ;LineEndingStyle2 LineEndingStyle ;LineStyle LineStyle ;};
    65  
    66  // Draw draws the polyline. A graphics state name can be specified for
    67  // setting the polyline properties (e.g. setting the opacity). Otherwise leave
    68  // empty (""). Returns the content stream as a byte array and the polyline
    69  // bounding box.
    70  func (_fdg Polyline )Draw (gsName string )([]byte ,*_gfc .PdfRectangle ,error ){if _fdg .LineColor ==nil {_fdg .LineColor =_gfc .NewPdfColorDeviceRGB (0,0,0);};_aea :=NewPath ();for _ ,_fcbd :=range _fdg .Points {_aea =_aea .AppendPoint (_fcbd );};_ccgd :=_gg .NewContentCreator ();
    71  _ccgd .Add_q ().SetStrokingColor (_fdg .LineColor ).Add_w (_fdg .LineWidth );if len (gsName )> 1{_ccgd .Add_gs (_c .PdfObjectName (gsName ));};DrawPathWithCreator (_aea ,_ccgd );_ccgd .Add_S ();_ccgd .Add_Q ();return _ccgd .Bytes (),_aea .GetBoundingBox ().ToPdfRectangle (),nil ;
    72  };
    73  
    74  // Copy returns a clone of the Bezier path.
    75  func (_bb CubicBezierPath )Copy ()CubicBezierPath {_db :=CubicBezierPath {};_db .Curves =append (_db .Curves ,_bb .Curves ...);return _db ;};func (_gbd Point )String ()string {return _gf .Sprintf ("(\u0025\u002e\u0031\u0066\u002c\u0025\u002e\u0031\u0066\u0029",_gbd .X ,_gbd .Y );
    76  };
    77  
    78  // AddVector adds vector to a point.
    79  func (_ac Point )AddVector (v Vector )Point {_ac .X +=v .Dx ;_ac .Y +=v .Dy ;return _ac };
    80  
    81  // NewPoint returns a new point with the coordinates x, y.
    82  func NewPoint (x ,y float64 )Point {return Point {X :x ,Y :y }};
    83  
    84  // NewVectorPolar returns a new vector calculated from the specified
    85  // magnitude and angle.
    86  func NewVectorPolar (length float64 ,theta float64 )Vector {_ffb :=Vector {};_ffb .Dx =length *_g .Cos (theta );_ffb .Dy =length *_g .Sin (theta );return _ffb ;};
    87  
    88  // AddOffsetXY adds X,Y offset to all points on a curve.
    89  func (_d CubicBezierCurve )AddOffsetXY (offX ,offY float64 )CubicBezierCurve {_d .P0 .X +=offX ;_d .P1 .X +=offX ;_d .P2 .X +=offX ;_d .P3 .X +=offX ;_d .P0 .Y +=offY ;_d .P1 .Y +=offY ;_d .P2 .Y +=offY ;_d .P3 .Y +=offY ;return _d ;};
    90  
    91  // Copy returns a clone of the path.
    92  func (_dd Path )Copy ()Path {_ce :=Path {};_ce .Points =append (_ce .Points ,_dd .Points ...);return _ce ;};
    93  
    94  // GetPointNumber returns the path point at the index specified by number.
    95  // The index is 1-based.
    96  func (_cdf Path )GetPointNumber (number int )Point {if number < 1||number > len (_cdf .Points ){return Point {};};return _cdf .Points [number -1];};
    97  
    98  // DrawBezierPathWithCreator makes the bezier path with the content creator.
    99  // Adds the PDF commands to draw the path to the creator instance.
   100  func DrawBezierPathWithCreator (bpath CubicBezierPath ,creator *_gg .ContentCreator ){for _dcg ,_bde :=range bpath .Curves {if _dcg ==0{creator .Add_m (_bde .P0 .X ,_bde .P0 .Y );};creator .Add_c (_bde .P1 .X ,_bde .P1 .Y ,_bde .P2 .X ,_bde .P2 .Y ,_bde .P3 .X ,_bde .P3 .Y );
   101  };};
   102  
   103  // NewVector returns a new vector with the direction specified by dx and dy.
   104  func NewVector (dx ,dy float64 )Vector {_dcbf :=Vector {};_dcbf .Dx =dx ;_dcbf .Dy =dy ;return _dcbf };
   105  
   106  // LineEndingStyle defines the line ending style for lines.
   107  // The currently supported line ending styles are None, Arrow (ClosedArrow) and Butt.
   108  type LineEndingStyle int ;
   109  
   110  // Rotate returns a new Point at `p` rotated by `theta` degrees.
   111  func (_aab Point )Rotate (theta float64 )Point {_ad :=_e .NewPoint (_aab .X ,_aab .Y ).Rotate (theta );return NewPoint (_ad .X ,_ad .Y );};
   112  
   113  // Draw draws the composite Bezier curve. A graphics state name can be
   114  // specified for setting the curve properties (e.g. setting the opacity).
   115  // Otherwise leave empty (""). Returns the content stream as a byte array and
   116  // the curve bounding box.
   117  func (_ade PolyBezierCurve )Draw (gsName string )([]byte ,*_gfc .PdfRectangle ,error ){if _ade .BorderColor ==nil {_ade .BorderColor =_gfc .NewPdfColorDeviceRGB (0,0,0);};_dfg :=NewCubicBezierPath ();for _ ,_fe :=range _ade .Curves {_dfg =_dfg .AppendCurve (_fe );
   118  };_gaf :=_gg .NewContentCreator ();_gaf .Add_q ();_ade .FillEnabled =_ade .FillEnabled &&_ade .FillColor !=nil ;if _ade .FillEnabled {_gaf .SetNonStrokingColor (_ade .FillColor );};_gaf .SetStrokingColor (_ade .BorderColor );_gaf .Add_w (_ade .BorderWidth );
   119  if len (gsName )> 1{_gaf .Add_gs (_c .PdfObjectName (gsName ));};for _cg ,_bg :=range _dfg .Curves {if _cg ==0{_gaf .Add_m (_bg .P0 .X ,_bg .P0 .Y );}else {_gaf .Add_l (_bg .P0 .X ,_bg .P0 .Y );};_gaf .Add_c (_bg .P1 .X ,_bg .P1 .Y ,_bg .P2 .X ,_bg .P2 .Y ,_bg .P3 .X ,_bg .P3 .Y );
   120  };if _ade .FillEnabled {_gaf .Add_h ();_gaf .Add_B ();}else {_gaf .Add_S ();};_gaf .Add_Q ();return _gaf .Bytes (),_dfg .GetBoundingBox ().ToPdfRectangle (),nil ;};
   121  
   122  // Draw draws the composite curve polygon. A graphics state name can be
   123  // specified for setting the curve properties (e.g. setting the opacity).
   124  // Otherwise leave empty (""). Returns the content stream as a byte array
   125  // and the bounding box of the polygon.
   126  func (_fg CurvePolygon )Draw (gsName string )([]byte ,*_gfc .PdfRectangle ,error ){_aba :=_gg .NewContentCreator ();_aba .Add_q ();_fg .FillEnabled =_fg .FillEnabled &&_fg .FillColor !=nil ;if _fg .FillEnabled {_aba .SetNonStrokingColor (_fg .FillColor );
   127  };_fg .BorderEnabled =_fg .BorderEnabled &&_fg .BorderColor !=nil ;if _fg .BorderEnabled {_aba .SetStrokingColor (_fg .BorderColor );_aba .Add_w (_fg .BorderWidth );};if len (gsName )> 1{_aba .Add_gs (_c .PdfObjectName (gsName ));};_eec :=NewCubicBezierPath ();
   128  for _ ,_gae :=range _fg .Rings {for _aaf ,_gbf :=range _gae {if _aaf ==0{_aba .Add_m (_gbf .P0 .X ,_gbf .P0 .Y );}else {_aba .Add_l (_gbf .P0 .X ,_gbf .P0 .Y );};_aba .Add_c (_gbf .P1 .X ,_gbf .P1 .Y ,_gbf .P2 .X ,_gbf .P2 .Y ,_gbf .P3 .X ,_gbf .P3 .Y );
   129  _eec =_eec .AppendCurve (_gbf );};_aba .Add_h ();};if _fg .FillEnabled &&_fg .BorderEnabled {_aba .Add_B ();}else if _fg .FillEnabled {_aba .Add_f ();}else if _fg .BorderEnabled {_aba .Add_S ();};_aba .Add_Q ();return _aba .Bytes (),_eec .GetBoundingBox ().ToPdfRectangle (),nil ;
   130  };
   131  
   132  // Rectangle is a shape with a specified Width and Height and a lower left corner at (X,Y) that can be
   133  // drawn to a PDF content stream.  The rectangle can optionally have a border and a filling color.
   134  // The Width/Height includes the border (if any specified), i.e. is positioned inside.
   135  type Rectangle struct{
   136  
   137  // Position and size properties.
   138  X float64 ;Y float64 ;Width float64 ;Height float64 ;
   139  
   140  // Fill properties.
   141  FillEnabled bool ;FillColor _gfc .PdfColor ;
   142  
   143  // Border properties.
   144  BorderEnabled bool ;BorderColor _gfc .PdfColor ;BorderWidth float64 ;BorderRadiusTopLeft float64 ;BorderRadiusTopRight float64 ;BorderRadiusBottomLeft float64 ;BorderRadiusBottomRight float64 ;
   145  
   146  // Shape opacity (0-1 interval).
   147  Opacity float64 ;};
   148  
   149  // CubicBezierPath represents a collection of cubic Bezier curves.
   150  type CubicBezierPath struct{Curves []CubicBezierCurve ;};const (LineEndingStyleNone LineEndingStyle =0;LineEndingStyleArrow LineEndingStyle =1;LineEndingStyleButt LineEndingStyle =2;);
   151  
   152  // Length returns the number of points in the path.
   153  func (_eeg Path )Length ()int {return len (_eeg .Points )};
   154  
   155  // Draw draws the basic line to PDF. Generates the content stream which can be used in page contents or appearance
   156  // stream of annotation. Returns the stream content, XForm bounding box (local), bounding box and an error if
   157  // one occurred.
   158  func (_gga BasicLine )Draw (gsName string )([]byte ,*_gfc .PdfRectangle ,error ){_gbg :=NewPath ();_gbg =_gbg .AppendPoint (NewPoint (_gga .X1 ,_gga .Y1 ));_gbg =_gbg .AppendPoint (NewPoint (_gga .X2 ,_gga .Y2 ));_dda :=_gg .NewContentCreator ();_dda .Add_q ().Add_w (_gga .LineWidth ).SetStrokingColor (_gga .LineColor );
   159  if _gga .LineStyle ==LineStyleDashed {if _gga .DashArray ==nil {_gga .DashArray =[]int64 {1,1};};_dda .Add_d (_gga .DashArray ,_gga .DashPhase );};if len (gsName )> 1{_dda .Add_gs (_c .PdfObjectName (gsName ));};DrawPathWithCreator (_gbg ,_dda );_dda .Add_S ().Add_Q ();
   160  return _dda .Bytes (),_gbg .GetBoundingBox ().ToPdfRectangle (),nil ;};
   161  
   162  // Draw draws the line to PDF contentstream. Generates the content stream which can be used in page contents or
   163  // appearance stream of annotation. Returns the stream content, XForm bounding box (local), bounding box and an error
   164  // if one occurred.
   165  func (_bfg Line )Draw (gsName string )([]byte ,*_gfc .PdfRectangle ,error ){_ebc ,_gag :=_bfg .X1 ,_bfg .X2 ;_adef ,_cb :=_bfg .Y1 ,_bfg .Y2 ;_fbg :=_cb -_adef ;_gfb :=_gag -_ebc ;_feb :=_g .Atan2 (_fbg ,_gfb );L :=_g .Sqrt (_g .Pow (_gfb ,2.0)+_g .Pow (_fbg ,2.0));
   166  _gee :=_bfg .LineWidth ;_ebf :=_g .Pi ;_beg :=1.0;if _gfb < 0{_beg *=-1.0;};if _fbg < 0{_beg *=-1.0;};VsX :=_beg *(-_gee /2*_g .Cos (_feb +_ebf /2));VsY :=_beg *(-_gee /2*_g .Sin (_feb +_ebf /2)+_gee *_g .Sin (_feb +_ebf /2));V1X :=VsX +_gee /2*_g .Cos (_feb +_ebf /2);
   167  V1Y :=VsY +_gee /2*_g .Sin (_feb +_ebf /2);V2X :=VsX +_gee /2*_g .Cos (_feb +_ebf /2)+L *_g .Cos (_feb );V2Y :=VsY +_gee /2*_g .Sin (_feb +_ebf /2)+L *_g .Sin (_feb );V3X :=VsX +_gee /2*_g .Cos (_feb +_ebf /2)+L *_g .Cos (_feb )+_gee *_g .Cos (_feb -_ebf /2);
   168  V3Y :=VsY +_gee /2*_g .Sin (_feb +_ebf /2)+L *_g .Sin (_feb )+_gee *_g .Sin (_feb -_ebf /2);V4X :=VsX +_gee /2*_g .Cos (_feb -_ebf /2);V4Y :=VsY +_gee /2*_g .Sin (_feb -_ebf /2);_ea :=NewPath ();_ea =_ea .AppendPoint (NewPoint (V1X ,V1Y ));_ea =_ea .AppendPoint (NewPoint (V2X ,V2Y ));
   169  _ea =_ea .AppendPoint (NewPoint (V3X ,V3Y ));_ea =_ea .AppendPoint (NewPoint (V4X ,V4Y ));_cgf :=_bfg .LineEndingStyle1 ;_bdga :=_bfg .LineEndingStyle2 ;_gaef :=3*_gee ;_fgb :=3*_gee ;_baa :=(_fgb -_gee )/2;if _bdga ==LineEndingStyleArrow {_aff :=_ea .GetPointNumber (2);
   170  _ff :=NewVectorPolar (_gaef ,_feb +_ebf );_cdc :=_aff .AddVector (_ff );_bfb :=NewVectorPolar (_fgb /2,_feb +_ebf /2);_gggd :=NewVectorPolar (_gaef ,_feb );_eee :=NewVectorPolar (_baa ,_feb +_ebf /2);_dcf :=_cdc .AddVector (_eee );_abae :=_gggd .Add (_bfb .Flip ());
   171  _aabd :=_dcf .AddVector (_abae );_bgg :=_bfb .Scale (2).Flip ().Add (_abae .Flip ());_adb :=_aabd .AddVector (_bgg );_dad :=_cdc .AddVector (NewVectorPolar (_gee ,_feb -_ebf /2));_dcc :=NewPath ();_dcc =_dcc .AppendPoint (_ea .GetPointNumber (1));_dcc =_dcc .AppendPoint (_cdc );
   172  _dcc =_dcc .AppendPoint (_dcf );_dcc =_dcc .AppendPoint (_aabd );_dcc =_dcc .AppendPoint (_adb );_dcc =_dcc .AppendPoint (_dad );_dcc =_dcc .AppendPoint (_ea .GetPointNumber (4));_ea =_dcc ;};if _cgf ==LineEndingStyleArrow {_efe :=_ea .GetPointNumber (1);
   173  _cbf :=_ea .GetPointNumber (_ea .Length ());_gbfb :=NewVectorPolar (_gee /2,_feb +_ebf +_ebf /2);_deg :=_efe .AddVector (_gbfb );_bag :=NewVectorPolar (_gaef ,_feb ).Add (NewVectorPolar (_fgb /2,_feb +_ebf /2));_cge :=_deg .AddVector (_bag );_fdf :=NewVectorPolar (_baa ,_feb -_ebf /2);
   174  _dfa :=_cge .AddVector (_fdf );_aafd :=NewVectorPolar (_gaef ,_feb );_fbb :=_cbf .AddVector (_aafd );_fea :=NewVectorPolar (_baa ,_feb +_ebf +_ebf /2);_fga :=_fbb .AddVector (_fea );_dbbc :=_deg ;_ccg :=NewPath ();_ccg =_ccg .AppendPoint (_deg );_ccg =_ccg .AppendPoint (_cge );
   175  _ccg =_ccg .AppendPoint (_dfa );for _ ,_cgfe :=range _ea .Points [1:len (_ea .Points )-1]{_ccg =_ccg .AppendPoint (_cgfe );};_ccg =_ccg .AppendPoint (_fbb );_ccg =_ccg .AppendPoint (_fga );_ccg =_ccg .AppendPoint (_dbbc );_ea =_ccg ;};_fdag :=_gg .NewContentCreator ();
   176  _fdag .Add_q ().SetNonStrokingColor (_bfg .LineColor );if len (gsName )> 1{_fdag .Add_gs (_c .PdfObjectName (gsName ));};_ea =_ea .Offset (_bfg .X1 ,_bfg .Y1 );_dga :=_ea .GetBoundingBox ();DrawPathWithCreator (_ea ,_fdag );if _bfg .LineStyle ==LineStyleDashed {_fdag .Add_d ([]int64 {1,1},0).Add_S ().Add_f ().Add_Q ();
   177  }else {_fdag .Add_f ().Add_Q ();};return _fdag .Bytes (),_dga .ToPdfRectangle (),nil ;};
   178  
   179  // Rotate rotates the vector by the specified angle.
   180  func (_dca Vector )Rotate (phi float64 )Vector {_fcbdf :=_dca .Magnitude ();_cefe :=_dca .GetPolarAngle ();return NewVectorPolar (_fcbdf ,_cefe +phi );};
   181  
   182  // FlipY flips the sign of the Dy component of the vector.
   183  func (_dbe Vector )FlipY ()Vector {_dbe .Dy =-_dbe .Dy ;return _dbe };
   184  
   185  // Draw draws the polygon. A graphics state name can be specified for
   186  // setting the polygon properties (e.g. setting the opacity). Otherwise leave
   187  // empty (""). Returns the content stream as a byte array and the polygon
   188  // bounding box.
   189  func (_aad Polygon )Draw (gsName string )([]byte ,*_gfc .PdfRectangle ,error ){_ef :=_gg .NewContentCreator ();_ef .Add_q ();_aad .FillEnabled =_aad .FillEnabled &&_aad .FillColor !=nil ;if _aad .FillEnabled {_ef .SetNonStrokingColor (_aad .FillColor );
   190  };_aad .BorderEnabled =_aad .BorderEnabled &&_aad .BorderColor !=nil ;if _aad .BorderEnabled {_ef .SetStrokingColor (_aad .BorderColor );_ef .Add_w (_aad .BorderWidth );};if len (gsName )> 1{_ef .Add_gs (_c .PdfObjectName (gsName ));};_fcf :=NewPath ();
   191  for _ ,_bd :=range _aad .Points {for _eb ,_fbd :=range _bd {_fcf =_fcf .AppendPoint (_fbd );if _eb ==0{_ef .Add_m (_fbd .X ,_fbd .Y );}else {_ef .Add_l (_fbd .X ,_fbd .Y );};};_ef .Add_h ();};if _aad .FillEnabled &&_aad .BorderEnabled {_ef .Add_B ();}else if _aad .FillEnabled {_ef .Add_f ();
   192  }else if _aad .BorderEnabled {_ef .Add_S ();};_ef .Add_Q ();return _ef .Bytes (),_fcf .GetBoundingBox ().ToPdfRectangle (),nil ;};
   193  
   194  // NewCubicBezierCurve returns a new cubic Bezier curve.
   195  func NewCubicBezierCurve (x0 ,y0 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 float64 )CubicBezierCurve {_aa :=CubicBezierCurve {};_aa .P0 =NewPoint (x0 ,y0 );_aa .P1 =NewPoint (x1 ,y1 );_aa .P2 =NewPoint (x2 ,y2 );_aa .P3 =NewPoint (x3 ,y3 );return _aa ;};
   196  
   197  // Polyline defines a slice of points that are connected as straight lines.
   198  type Polyline struct{Points []Point ;LineColor _gfc .PdfColor ;LineWidth float64 ;};
   199  
   200  // BoundingBox represents the smallest rectangular area that encapsulates an object.
   201  type BoundingBox struct{X float64 ;Y float64 ;Width float64 ;Height float64 ;};
   202  
   203  // Scale scales the vector by the specified factor.
   204  func (_bdgg Vector )Scale (factor float64 )Vector {_acc :=_bdgg .Magnitude ();_edb :=_bdgg .GetPolarAngle ();_bdgg .Dx =factor *_acc *_g .Cos (_edb );_bdgg .Dy =factor *_acc *_g .Sin (_edb );return _bdgg ;};
   205  
   206  // RemovePoint removes the point at the index specified by number from the
   207  // path. The index is 1-based.
   208  func (_ae Path )RemovePoint (number int )Path {if number < 1||number > len (_ae .Points ){return _ae ;};_ga :=number -1;_ae .Points =append (_ae .Points [:_ga ],_ae .Points [_ga +1:]...);return _ae ;};const (LineStyleSolid LineStyle =0;LineStyleDashed LineStyle =1;
   209  );
   210  
   211  // NewPath returns a new empty path.
   212  func NewPath ()Path {return Path {}};
   213  
   214  // NewVectorBetween returns a new vector with the direction specified by
   215  // the subtraction of point a from point b (b-a).
   216  func NewVectorBetween (a Point ,b Point )Vector {_dbbcb :=Vector {};_dbbcb .Dx =b .X -a .X ;_dbbcb .Dy =b .Y -a .Y ;return _dbbcb ;};
   217  
   218  // GetPolarAngle returns the angle the magnitude of the vector forms with the
   219  // positive X-axis going counterclockwise.
   220  func (_ggaa Vector )GetPolarAngle ()float64 {return _g .Atan2 (_ggaa .Dy ,_ggaa .Dx )};
   221  
   222  // GetBoundingBox returns the bounding box of the Bezier path.
   223  func (_be CubicBezierPath )GetBoundingBox ()Rectangle {_ede :=Rectangle {};_dac :=0.0;_gd :=0.0;_gdf :=0.0;_f :=0.0;for _cd ,_ab :=range _be .Curves {_dg :=_ab .GetBounds ();if _cd ==0{_dac =_dg .Llx ;_gd =_dg .Urx ;_gdf =_dg .Lly ;_f =_dg .Ury ;continue ;
   224  };if _dg .Llx < _dac {_dac =_dg .Llx ;};if _dg .Urx > _gd {_gd =_dg .Urx ;};if _dg .Lly < _gdf {_gdf =_dg .Lly ;};if _dg .Ury > _f {_f =_dg .Ury ;};};_ede .X =_dac ;_ede .Y =_gdf ;_ede .Width =_gd -_dac ;_ede .Height =_f -_gdf ;return _ede ;};
   225  
   226  // CurvePolygon is a multi-point shape with rings containing curves that can be
   227  // drawn to a PDF content stream.
   228  type CurvePolygon struct{Rings [][]CubicBezierCurve ;FillEnabled bool ;FillColor _gfc .PdfColor ;BorderEnabled bool ;BorderColor _gfc .PdfColor ;BorderWidth float64 ;};
   229  
   230  // Point represents a two-dimensional point.
   231  type Point struct{X float64 ;Y float64 ;};
   232  
   233  // FlipX flips the sign of the Dx component of the vector.
   234  func (_gcf Vector )FlipX ()Vector {_gcf .Dx =-_gcf .Dx ;return _gcf };
   235  
   236  // BasicLine defines a line between point 1 (X1,Y1) and point 2 (X2,Y2). The line has a specified width, color and opacity.
   237  type BasicLine struct{X1 float64 ;Y1 float64 ;X2 float64 ;Y2 float64 ;LineColor _gfc .PdfColor ;Opacity float64 ;LineWidth float64 ;LineStyle LineStyle ;DashArray []int64 ;DashPhase int64 ;};
   238  
   239  // PolyBezierCurve represents a composite curve that is the result of
   240  // joining multiple cubic Bezier curves.
   241  type PolyBezierCurve struct{Curves []CubicBezierCurve ;BorderWidth float64 ;BorderColor _gfc .PdfColor ;FillEnabled bool ;FillColor _gfc .PdfColor ;};
   242  
   243  // Draw draws the rectangle. A graphics state can be specified for
   244  // setting additional properties (e.g. opacity). Otherwise pass an empty string
   245  // for the `gsName` parameter. The method returns the content stream as a byte
   246  // array and the bounding box of the shape.
   247  func (_gc Rectangle )Draw (gsName string )([]byte ,*_gfc .PdfRectangle ,error ){_abe :=_gg .NewContentCreator ();_abe .Add_q ();if _gc .FillEnabled {_abe .SetNonStrokingColor (_gc .FillColor );};if _gc .BorderEnabled {_abe .SetStrokingColor (_gc .BorderColor );
   248  _abe .Add_w (_gc .BorderWidth );};if len (gsName )> 1{_abe .Add_gs (_c .PdfObjectName (gsName ));};var (_dbbd ,_bda =_gc .X ,_gc .Y ;_fcag ,_bdg =_gc .Width ,_gc .Height ;_aae =_g .Abs (_gc .BorderRadiusTopLeft );_eef =_g .Abs (_gc .BorderRadiusTopRight );
   249  _cfe =_g .Abs (_gc .BorderRadiusBottomLeft );_acg =_g .Abs (_gc .BorderRadiusBottomRight );_ddf =0.4477;);_aabf :=Path {Points :[]Point {{X :_dbbd +_fcag -_acg ,Y :_bda },{X :_dbbd +_fcag ,Y :_bda +_bdg -_eef },{X :_dbbd +_aae ,Y :_bda +_bdg },{X :_dbbd ,Y :_bda +_cfe }}};
   250  _acb :=[][7]float64 {{_acg ,_dbbd +_fcag -_acg *_ddf ,_bda ,_dbbd +_fcag ,_bda +_acg *_ddf ,_dbbd +_fcag ,_bda +_acg },{_eef ,_dbbd +_fcag ,_bda +_bdg -_eef *_ddf ,_dbbd +_fcag -_eef *_ddf ,_bda +_bdg ,_dbbd +_fcag -_eef ,_bda +_bdg },{_aae ,_dbbd +_aae *_ddf ,_bda +_bdg ,_dbbd ,_bda +_bdg -_aae *_ddf ,_dbbd ,_bda +_bdg -_aae },{_cfe ,_dbbd ,_bda +_cfe *_ddf ,_dbbd +_cfe *_ddf ,_bda ,_dbbd +_cfe ,_bda }};
   251  _abe .Add_m (_dbbd +_cfe ,_bda );for _dcb :=0;_dcb < 4;_dcb ++{_ge :=_aabf .Points [_dcb ];_abe .Add_l (_ge .X ,_ge .Y );_bc :=_acb [_dcb ];if _ba :=_bc [0];_ba !=0{_abe .Add_c (_bc [1],_bc [2],_bc [3],_bc [4],_bc [5],_bc [6]);};};_abe .Add_h ();if _gc .FillEnabled &&_gc .BorderEnabled {_abe .Add_B ();
   252  }else if _gc .FillEnabled {_abe .Add_f ();}else if _gc .BorderEnabled {_abe .Add_S ();};_abe .Add_Q ();return _abe .Bytes (),_aabf .GetBoundingBox ().ToPdfRectangle (),nil ;};
   253  
   254  // Polygon is a multi-point shape that can be drawn to a PDF content stream.
   255  type Polygon struct{Points [][]Point ;FillEnabled bool ;FillColor _gfc .PdfColor ;BorderEnabled bool ;BorderColor _gfc .PdfColor ;BorderWidth float64 ;};
   256  
   257  // Draw draws the circle. Can specify a graphics state (gsName) for setting opacity etc.  Otherwise leave empty ("").
   258  // Returns the content stream as a byte array, the bounding box and an error on failure.
   259  func (_dfc Circle )Draw (gsName string )([]byte ,*_gfc .PdfRectangle ,error ){_bfd :=_dfc .Width /2;_edg :=_dfc .Height /2;if _dfc .BorderEnabled {_bfd -=_dfc .BorderWidth /2;_edg -=_dfc .BorderWidth /2;};_fce :=0.551784;_cee :=_bfd *_fce ;_adf :=_edg *_fce ;
   260  _cfd :=NewCubicBezierPath ();_cfd =_cfd .AppendCurve (NewCubicBezierCurve (-_bfd ,0,-_bfd ,_adf ,-_cee ,_edg ,0,_edg ));_cfd =_cfd .AppendCurve (NewCubicBezierCurve (0,_edg ,_cee ,_edg ,_bfd ,_adf ,_bfd ,0));_cfd =_cfd .AppendCurve (NewCubicBezierCurve (_bfd ,0,_bfd ,-_adf ,_cee ,-_edg ,0,-_edg ));
   261  _cfd =_cfd .AppendCurve (NewCubicBezierCurve (0,-_edg ,-_cee ,-_edg ,-_bfd ,-_adf ,-_bfd ,0));_cfd =_cfd .Offset (_bfd ,_edg );if _dfc .BorderEnabled {_cfd =_cfd .Offset (_dfc .BorderWidth /2,_dfc .BorderWidth /2);};if _dfc .X !=0||_dfc .Y !=0{_cfd =_cfd .Offset (_dfc .X ,_dfc .Y );
   262  };_abc :=_gg .NewContentCreator ();_abc .Add_q ();if _dfc .FillEnabled {_abc .SetNonStrokingColor (_dfc .FillColor );};if _dfc .BorderEnabled {_abc .SetStrokingColor (_dfc .BorderColor );_abc .Add_w (_dfc .BorderWidth );};if len (gsName )> 1{_abc .Add_gs (_c .PdfObjectName (gsName ));
   263  };DrawBezierPathWithCreator (_cfd ,_abc );_abc .Add_h ();if _dfc .FillEnabled &&_dfc .BorderEnabled {_abc .Add_B ();}else if _dfc .FillEnabled {_abc .Add_f ();}else if _dfc .BorderEnabled {_abc .Add_S ();};_abc .Add_Q ();_dbb :=_cfd .GetBoundingBox ();
   264  if _dfc .BorderEnabled {_dbb .Height +=_dfc .BorderWidth ;_dbb .Width +=_dfc .BorderWidth ;_dbb .X -=_dfc .BorderWidth /2;_dbb .Y -=_dfc .BorderWidth /2;};return _abc .Bytes (),_dbb .ToPdfRectangle (),nil ;};
   265  
   266  // CubicBezierCurve is defined by:
   267  // R(t) = P0*(1-t)^3 + P1*3*t*(1-t)^2 + P2*3*t^2*(1-t) + P3*t^3
   268  // where P0 is the current point, P1, P2 control points and P3 the final point.
   269  type CubicBezierCurve struct{P0 Point ;P1 Point ;P2 Point ;P3 Point ;};
   270  
   271  // Vector represents a two-dimensional vector.
   272  type Vector struct{Dx float64 ;Dy float64 ;};
   273  
   274  // ToPdfRectangle returns the rectangle as a PDF rectangle.
   275  func (_de Rectangle )ToPdfRectangle ()*_gfc .PdfRectangle {return &_gfc .PdfRectangle {Llx :_de .X ,Lly :_de .Y ,Urx :_de .X +_de .Width ,Ury :_de .Y +_de .Height };};
   276  
   277  // Flip changes the sign of the vector: -vector.
   278  func (_ddb Vector )Flip ()Vector {_gaa :=_ddb .Magnitude ();_cce :=_ddb .GetPolarAngle ();_ddb .Dx =_gaa *_g .Cos (_cce +_g .Pi );_ddb .Dy =_gaa *_g .Sin (_cce +_g .Pi );return _ddb ;};
   279  
   280  // NewCubicBezierPath returns a new empty cubic Bezier path.
   281  func NewCubicBezierPath ()CubicBezierPath {_ca :=CubicBezierPath {};_ca .Curves =[]CubicBezierCurve {};return _ca ;};
   282  
   283  // Magnitude returns the magnitude of the vector.
   284  func (_abcf Vector )Magnitude ()float64 {return _g .Sqrt (_g .Pow (_abcf .Dx ,2.0)+_g .Pow (_abcf .Dy ,2.0));};