// // Copyright 2020 FoxyUtils ehf. All rights reserved. // // This is a commercial product and requires a license to operate. // A trial license can be obtained at https://unidoc.io // // DO NOT EDIT: generated by unitwist Go source code obfuscator. // // Use of this source code is governed by the UniDoc End User License Agreement // terms that can be accessed at https://unidoc.io/eula/ // Package draw has handy features for defining paths which can be used to draw content on a PDF page. Handles // defining paths as points, vector calculations and conversion to PDF content stream data which can be used in // page content streams and XObject forms and thus also in annotation appearance streams. // // Also defines utility functions for drawing common shapes such as rectangles, lines and circles (ovals). package draw ;import (_e "fmt";_ae "github.com/unidoc/unipdf/v3/contentstream";_a "github.com/unidoc/unipdf/v3/core";_ga "github.com/unidoc/unipdf/v3/internal/transform";_c "github.com/unidoc/unipdf/v3/model";_d "math";); // GetBoundingBox returns the bounding box of the path. func (_de Path )GetBoundingBox ()BoundingBox {_ef :=BoundingBox {};_fac :=0.0;_gd :=0.0;_ecc :=0.0;_abg :=0.0;for _fee ,_fdf :=range _de .Points {if _fee ==0{_fac =_fdf .X ;_gd =_fdf .X ;_ecc =_fdf .Y ;_abg =_fdf .Y ;continue ;};if _fdf .X < _fac {_fac =_fdf .X ;};if _fdf .X > _gd {_gd =_fdf .X ;};if _fdf .Y < _ecc {_ecc =_fdf .Y ;};if _fdf .Y > _abg {_abg =_fdf .Y ;};};_ef .X =_fac ;_ef .Y =_ecc ;_ef .Width =_gd -_fac ;_ef .Height =_abg -_ecc ;return _ef ;}; // Draw draws the basic line to PDF. Generates the content stream which can be used in page contents or appearance // stream of annotation. Returns the stream content, XForm bounding box (local), bounding box and an error if // one occurred. func (_cb BasicLine )Draw (gsName string )([]byte ,*_c .PdfRectangle ,error ){_fbfe :=_cb .LineWidth ;_bgc :=NewPath ();_bgc =_bgc .AppendPoint (NewPoint (_cb .X1 ,_cb .Y1 ));_bgc =_bgc .AppendPoint (NewPoint (_cb .X2 ,_cb .Y2 ));_fad :=_ae .NewContentCreator ();_gda :=_bgc .GetBoundingBox ();DrawPathWithCreator (_bgc ,_fad );if _cb .LineStyle ==LineStyleDashed {_fad .Add_d ([]int64 {1,1},0);};_fad .Add_RG (_cb .LineColor .R (),_cb .LineColor .G (),_cb .LineColor .B ()).Add_w (_fbfe ).Add_S ().Add_Q ();return _fad .Bytes (),_gda .ToPdfRectangle (),nil ;}; // Add adds the specified vector to the current one and returns the result. func (_fcg Vector )Add (other Vector )Vector {_fcg .Dx +=other .Dx ;_fcg .Dy +=other .Dy ;return _fcg }; // Rotate rotates the vector by the specified angle. func (_gff Vector )Rotate (phi float64 )Vector {_cgf :=_gff .Magnitude ();_bab :=_gff .GetPolarAngle ();return NewVectorPolar (_cgf ,_bab +phi );}; // Line defines a line shape between point 1 (X1,Y1) and point 2 (X2,Y2). The line ending styles can be none (regular line), // or arrows at either end. The line also has a specified width, color and opacity. type Line struct{X1 float64 ;Y1 float64 ;X2 float64 ;Y2 float64 ;LineColor *_c .PdfColorDeviceRGB ;Opacity float64 ;LineWidth float64 ;LineEndingStyle1 LineEndingStyle ;LineEndingStyle2 LineEndingStyle ;LineStyle LineStyle ;}; // ToPdfRectangle returns the rectangle as a PDF rectangle. func (_cfg Rectangle )ToPdfRectangle ()*_c .PdfRectangle {return &_c .PdfRectangle {Llx :_cfg .X ,Lly :_cfg .Y ,Urx :_cfg .X +_cfg .Width ,Ury :_cfg .Y +_cfg .Height };}; // PolyBezierCurve represents a composite curve that is the result of // joining multiple cubic Bezier curves. type PolyBezierCurve struct{Curves []CubicBezierCurve ;BorderWidth float64 ;BorderColor *_c .PdfColorDeviceRGB ;FillEnabled bool ;FillColor *_c .PdfColorDeviceRGB ;}; // BoundingBox represents the smallest rectangular area that encapsulates an object. type BoundingBox struct{X float64 ;Y float64 ;Width float64 ;Height float64 ;}; // Add shifts the coordinates of the point with dx, dy and returns the result. func (_ce Point )Add (dx ,dy float64 )Point {_ce .X +=dx ;_ce .Y +=dy ;return _ce }; // AppendPoint adds the specified point to the path. func (_gad Path )AppendPoint (point Point )Path {_gad .Points =append (_gad .Points ,point );return _gad }; // Circle represents a circle shape with fill and border properties that can be drawn to a PDF content stream. type Circle struct{X float64 ;Y float64 ;Width float64 ;Height float64 ;FillEnabled bool ;FillColor *_c .PdfColorDeviceRGB ;BorderEnabled bool ;BorderWidth float64 ;BorderColor *_c .PdfColorDeviceRGB ;Opacity float64 ;}; // RemovePoint removes the point at the index specified by number from the // path. The index is 1-based. func (_dg Path )RemovePoint (number int )Path {if number < 1||number > len (_dg .Points ){return _dg ;};_ad :=number -1;_dg .Points =append (_dg .Points [:_ad ],_dg .Points [_ad +1:]...);return _dg ;}; // Flip changes the sign of the vector: -vector. func (_ced Vector )Flip ()Vector {_aef :=_ced .Magnitude ();_bac :=_ced .GetPolarAngle ();_ced .Dx =_aef *_d .Cos (_bac +_d .Pi );_ced .Dy =_aef *_d .Sin (_bac +_d .Pi );return _ced ;}; // BasicLine defines a line between point 1 (X1,Y1) and point 2 (X2,Y2). The line has a specified width, color and opacity. type BasicLine struct{X1 float64 ;Y1 float64 ;X2 float64 ;Y2 float64 ;LineColor *_c .PdfColorDeviceRGB ;Opacity float64 ;LineWidth float64 ;LineStyle LineStyle ;}; // Offset shifts the path with the specified offsets. func (_cd Path )Offset (offX ,offY float64 )Path {for _fag ,_faa :=range _cd .Points {_cd .Points [_fag ]=_faa .Add (offX ,offY );};return _cd ;}; // AppendCurve appends the specified Bezier curve to the path. func (_ba CubicBezierPath )AppendCurve (curve CubicBezierCurve )CubicBezierPath {_ba .Curves =append (_ba .Curves ,curve );return _ba ;}; // Length returns the number of points in the path. func (_fe Path )Length ()int {return len (_fe .Points )}; // NewVector returns a new vector with the direction specified by dx and dy. func NewVector (dx ,dy float64 )Vector {_bcg :=Vector {};_bcg .Dx =dx ;_bcg .Dy =dy ;return _bcg }; // Draw draws the circle. Can specify a graphics state (gsName) for setting opacity etc. Otherwise leave empty (""). // Returns the content stream as a byte array, the bounding box and an error on failure. func (_ceb Circle )Draw (gsName string )([]byte ,*_c .PdfRectangle ,error ){_bf :=_ceb .Width /2;_dc :=_ceb .Height /2;if _ceb .BorderEnabled {_bf -=_ceb .BorderWidth /2;_dc -=_ceb .BorderWidth /2;};_ca :=0.551784;_ee :=_bf *_ca ;_gc :=_dc *_ca ;_gdc :=NewCubicBezierPath ();_gdc =_gdc .AppendCurve (NewCubicBezierCurve (-_bf ,0,-_bf ,_gc ,-_ee ,_dc ,0,_dc ));_gdc =_gdc .AppendCurve (NewCubicBezierCurve (0,_dc ,_ee ,_dc ,_bf ,_gc ,_bf ,0));_gdc =_gdc .AppendCurve (NewCubicBezierCurve (_bf ,0,_bf ,-_gc ,_ee ,-_dc ,0,-_dc ));_gdc =_gdc .AppendCurve (NewCubicBezierCurve (0,-_dc ,-_ee ,-_dc ,-_bf ,-_gc ,-_bf ,0));_gdc =_gdc .Offset (_bf ,_dc );if _ceb .BorderEnabled {_gdc =_gdc .Offset (_ceb .BorderWidth /2,_ceb .BorderWidth /2);};if _ceb .X !=0||_ceb .Y !=0{_gdc =_gdc .Offset (_ceb .X ,_ceb .Y );};_gde :=_ae .NewContentCreator ();_gde .Add_q ();if _ceb .FillEnabled {_gde .Add_rg (_ceb .FillColor .R (),_ceb .FillColor .G (),_ceb .FillColor .B ());};if _ceb .BorderEnabled {_gde .Add_RG (_ceb .BorderColor .R (),_ceb .BorderColor .G (),_ceb .BorderColor .B ());_gde .Add_w (_ceb .BorderWidth );};if len (gsName )> 1{_gde .Add_gs (_a .PdfObjectName (gsName ));};DrawBezierPathWithCreator (_gdc ,_gde );_gde .Add_h ();if _ceb .FillEnabled &&_ceb .BorderEnabled {_gde .Add_B ();}else if _ceb .FillEnabled {_gde .Add_f ();}else if _ceb .BorderEnabled {_gde .Add_S ();};_gde .Add_Q ();_ag :=_gdc .GetBoundingBox ();if _ceb .BorderEnabled {_ag .Height +=_ceb .BorderWidth ;_ag .Width +=_ceb .BorderWidth ;_ag .X -=_ceb .BorderWidth /2;_ag .Y -=_ceb .BorderWidth /2;};return _gde .Bytes (),_ag .ToPdfRectangle (),nil ;}; // CubicBezierCurve is defined by: // R(t) = P0*(1-t)^3 + P1*3*t*(1-t)^2 + P2*3*t^2*(1-t) + P3*t^3 // where P0 is the current point, P1, P2 control points and P3 the final point. type CubicBezierCurve struct{P0 Point ;P1 Point ;P2 Point ;P3 Point ;}; // NewVectorPolar returns a new vector calculated from the specified // magnitude and angle. func NewVectorPolar (length float64 ,theta float64 )Vector {_dba :=Vector {};_dba .Dx =length *_d .Cos (theta );_dba .Dy =length *_d .Sin (theta );return _dba ;}; // Rotate returns a new Point at `p` rotated by `theta` degrees. func (_bc Point )Rotate (theta float64 )Point {_ggd :=_ga .NewPoint (_bc .X ,_bc .Y ).Rotate (theta );return NewPoint (_ggd .X ,_ggd .Y );}; // Rectangle is a shape with a specified Width and Height and a lower left corner at (X,Y) that can be // drawn to a PDF content stream. The rectangle can optionally have a border and a filling color. // The Width/Height includes the border (if any specified), i.e. is positioned inside. type Rectangle struct{X float64 ;Y float64 ;Width float64 ;Height float64 ;FillEnabled bool ;FillColor *_c .PdfColorDeviceRGB ;BorderEnabled bool ;BorderWidth float64 ;BorderColor *_c .PdfColorDeviceRGB ;Opacity float64 ;}; // DrawPathWithCreator makes the path with the content creator. // Adds the PDF commands to draw the path to the creator instance. func DrawPathWithCreator (path Path ,creator *_ae .ContentCreator ){for _fcd ,_bgge :=range path .Points {if _fcd ==0{creator .Add_m (_bgge .X ,_bgge .Y );}else {creator .Add_l (_bgge .X ,_bgge .Y );};};}; // Copy returns a clone of the Bezier path. func (_ebd CubicBezierPath )Copy ()CubicBezierPath {_fd :=CubicBezierPath {};_fd .Curves =append (_fd .Curves ,_ebd .Curves ...);return _fd ;}; // FlipX flips the sign of the Dx component of the vector. func (_af Vector )FlipX ()Vector {_af .Dx =-_af .Dx ;return _af }; // GetBoundingBox returns the bounding box of the Bezier path. func (_ebc CubicBezierPath )GetBoundingBox ()Rectangle {_ab :=Rectangle {};_ge :=0.0;_aea :=0.0;_ec :=0.0;_gbc :=0.0;for _gf ,_fa :=range _ebc .Curves {_ebcc :=_fa .GetBounds ();if _gf ==0{_ge =_ebcc .Llx ;_aea =_ebcc .Urx ;_ec =_ebcc .Lly ;_gbc =_ebcc .Ury ;continue ;};if _ebcc .Llx < _ge {_ge =_ebcc .Llx ;};if _ebcc .Urx > _aea {_aea =_ebcc .Urx ;};if _ebcc .Lly < _ec {_ec =_ebcc .Lly ;};if _ebcc .Ury > _gbc {_gbc =_ebcc .Ury ;};};_ab .X =_ge ;_ab .Y =_ec ;_ab .Width =_aea -_ge ;_ab .Height =_gbc -_ec ;return _ab ;}; // LineEndingStyle defines the line ending style for lines. // The currently supported line ending styles are None, Arrow (ClosedArrow) and Butt. type LineEndingStyle int ; // Draw draws the polyline. A graphics state name can be specified for // setting the polyline properties (e.g. setting the opacity). Otherwise leave // empty (""). Returns the content stream as a byte array and the polyline // bounding box. func (_gdb Polyline )Draw (gsName string )([]byte ,*_c .PdfRectangle ,error ){if _gdb .LineColor ==nil {_gdb .LineColor =_c .NewPdfColorDeviceRGB (0,0,0);};_geg :=NewPath ();for _ ,_acc :=range _gdb .Points {_geg =_geg .AppendPoint (_acc );};_edd :=_ae .NewContentCreator ();_edd .Add_q ();_edd .Add_RG (_gdb .LineColor .R (),_gdb .LineColor .G (),_gdb .LineColor .B ());_edd .Add_w (_gdb .LineWidth );if len (gsName )> 1{_edd .Add_gs (_a .PdfObjectName (gsName ));};DrawPathWithCreator (_geg ,_edd );_edd .Add_S ();_edd .Add_Q ();return _edd .Bytes (),_geg .GetBoundingBox ().ToPdfRectangle (),nil ;}; // Polyline defines a slice of points that are connected as straight lines. type Polyline struct{Points []Point ;LineColor *_c .PdfColorDeviceRGB ;LineWidth float64 ;}; // NewCubicBezierCurve returns a new cubic Bezier curve. func NewCubicBezierCurve (x0 ,y0 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 float64 )CubicBezierCurve {_eb :=CubicBezierCurve {};_eb .P0 =NewPoint (x0 ,y0 );_eb .P1 =NewPoint (x1 ,y1 );_eb .P2 =NewPoint (x2 ,y2 );_eb .P3 =NewPoint (x3 ,y3 );return _eb ;}; // LineStyle refers to how the line will be created. type LineStyle int ; // Offset shifts the Bezier path with the specified offsets. func (_ed CubicBezierPath )Offset (offX ,offY float64 )CubicBezierPath {for _gg ,_ac :=range _ed .Curves {_ed .Curves [_gg ]=_ac .AddOffsetXY (offX ,offY );};return _ed ;};const (LineEndingStyleNone LineEndingStyle =0;LineEndingStyleArrow LineEndingStyle =1;LineEndingStyleButt LineEndingStyle =2;); // Polygon is a multi-point shape that can be drawn to a PDF content stream. type Polygon struct{Points [][]Point ;FillEnabled bool ;FillColor *_c .PdfColorDeviceRGB ;BorderEnabled bool ;BorderColor *_c .PdfColorDeviceRGB ;BorderWidth float64 ;}; // Magnitude returns the magnitude of the vector. func (_cef Vector )Magnitude ()float64 {return _d .Sqrt (_d .Pow (_cef .Dx ,2.0)+_d .Pow (_cef .Dy ,2.0))}; // NewPath returns a new empty path. func NewPath ()Path {return Path {}};const (LineStyleSolid LineStyle =0;LineStyleDashed LineStyle =1;); // DrawBezierPathWithCreator makes the bezier path with the content creator. // Adds the PDF commands to draw the path to the creator instance. func DrawBezierPathWithCreator (bpath CubicBezierPath ,creator *_ae .ContentCreator ){for _gea ,_fbcg :=range bpath .Curves {if _gea ==0{creator .Add_m (_fbcg .P0 .X ,_fbcg .P0 .Y );};creator .Add_c (_fbcg .P1 .X ,_fbcg .P1 .Y ,_fbcg .P2 .X ,_fbcg .P2 .Y ,_fbcg .P3 .X ,_fbcg .P3 .Y );};}; // Path consists of straight line connections between each point defined in an array of points. type Path struct{Points []Point ;}; // FlipY flips the sign of the Dy component of the vector. func (_deb Vector )FlipY ()Vector {_deb .Dy =-_deb .Dy ;return _deb }; // ToPdfRectangle returns the bounding box as a PDF rectangle. func (_abge BoundingBox )ToPdfRectangle ()*_c .PdfRectangle {return &_c .PdfRectangle {Llx :_abge .X ,Lly :_abge .Y ,Urx :_abge .X +_abge .Width ,Ury :_abge .Y +_abge .Height };}; // NewVectorBetween returns a new vector with the direction specified by // the subtraction of point a from point b (b-a). func NewVectorBetween (a Point ,b Point )Vector {_cbb :=Vector {};_cbb .Dx =b .X -a .X ;_cbb .Dy =b .Y -a .Y ;return _cbb ;}; // CubicBezierPath represents a collection of cubic Bezier curves. type CubicBezierPath struct{Curves []CubicBezierCurve ;}; // Vector represents a two-dimensional vector. type Vector struct{Dx float64 ;Dy float64 ;}; // AddOffsetXY adds X,Y offset to all points on a curve. func (_f CubicBezierCurve )AddOffsetXY (offX ,offY float64 )CubicBezierCurve {_f .P0 .X +=offX ;_f .P1 .X +=offX ;_f .P2 .X +=offX ;_f .P3 .X +=offX ;_f .P0 .Y +=offY ;_f .P1 .Y +=offY ;_f .P2 .Y +=offY ;_f .P3 .Y +=offY ;return _f ;}; // AddVector adds vector to a point. func (_dfc Point )AddVector (v Vector )Point {_dfc .X +=v .Dx ;_dfc .Y +=v .Dy ;return _dfc }; // Draw draws the rectangle. Can specify a graphics state (gsName) for setting opacity etc. // Otherwise leave empty (""). Returns the content stream as a byte array, bounding box and an error on failure. func (_cg Rectangle )Draw (gsName string )([]byte ,*_c .PdfRectangle ,error ){_gcf :=NewPath ();_gcf =_gcf .AppendPoint (NewPoint (0,0));_gcf =_gcf .AppendPoint (NewPoint (0,_cg .Height ));_gcf =_gcf .AppendPoint (NewPoint (_cg .Width ,_cg .Height ));_gcf =_gcf .AppendPoint (NewPoint (_cg .Width ,0));_gcf =_gcf .AppendPoint (NewPoint (0,0));if _cg .X !=0||_cg .Y !=0{_gcf =_gcf .Offset (_cg .X ,_cg .Y );};_db :=_ae .NewContentCreator ();_db .Add_q ();if _cg .FillEnabled {_db .Add_rg (_cg .FillColor .R (),_cg .FillColor .G (),_cg .FillColor .B ());};if _cg .BorderEnabled {_db .Add_RG (_cg .BorderColor .R (),_cg .BorderColor .G (),_cg .BorderColor .B ());_db .Add_w (_cg .BorderWidth );};if len (gsName )> 1{_db .Add_gs (_a .PdfObjectName (gsName ));};DrawPathWithCreator (_gcf ,_db );_db .Add_h ();if _cg .FillEnabled &&_cg .BorderEnabled {_db .Add_B ();}else if _cg .FillEnabled {_db .Add_f ();}else if _cg .BorderEnabled {_db .Add_S ();};_db .Add_Q ();return _db .Bytes (),_gcf .GetBoundingBox ().ToPdfRectangle (),nil ;}; // NewCubicBezierPath returns a new empty cubic Bezier path. func NewCubicBezierPath ()CubicBezierPath {_bg :=CubicBezierPath {};_bg .Curves =[]CubicBezierCurve {};return _bg ;}; // Point represents a two-dimensional point. type Point struct{X float64 ;Y float64 ;}; // Scale scales the vector by the specified factor. func (_ccc Vector )Scale (factor float64 )Vector {_bb :=_ccc .Magnitude ();_aec :=_ccc .GetPolarAngle ();_ccc .Dx =factor *_bb *_d .Cos (_aec );_ccc .Dy =factor *_bb *_d .Sin (_aec );return _ccc ;}; // Draw draws the composite Bezier curve. A graphics state name can be // specified for setting the curve properties (e.g. setting the opacity). // Otherwise leave empty (""). Returns the content stream as a byte array and // the curve bounding box. func (_cc PolyBezierCurve )Draw (gsName string )([]byte ,*_c .PdfRectangle ,error ){if _cc .BorderColor ==nil {_cc .BorderColor =_c .NewPdfColorDeviceRGB (0,0,0);};_bd :=NewCubicBezierPath ();for _ ,_gfd :=range _cc .Curves {_bd =_bd .AppendCurve (_gfd );};_feg :=_ae .NewContentCreator ();_feg .Add_q ();_cc .FillEnabled =_cc .FillEnabled &&_cc .FillColor !=nil ;if _cc .FillEnabled {_feg .Add_rg (_cc .FillColor .R (),_cc .FillColor .G (),_cc .FillColor .B ());};_feg .Add_RG (_cc .BorderColor .R (),_cc .BorderColor .G (),_cc .BorderColor .B ());_feg .Add_w (_cc .BorderWidth );if len (gsName )> 1{_feg .Add_gs (_a .PdfObjectName (gsName ));};for _ ,_acf :=range _bd .Curves {_feg .Add_m (_acf .P0 .X ,_acf .P0 .Y );_feg .Add_c (_acf .P1 .X ,_acf .P1 .Y ,_acf .P2 .X ,_acf .P2 .Y ,_acf .P3 .X ,_acf .P3 .Y );};if _cc .FillEnabled {_feg .Add_h ();_feg .Add_B ();}else {_feg .Add_S ();};_feg .Add_Q ();return _feg .Bytes (),_bd .GetBoundingBox ().ToPdfRectangle (),nil ;}; // GetBounds returns the bounding box of the Bezier curve. func (_gb CubicBezierCurve )GetBounds ()_c .PdfRectangle {_ff :=_gb .P0 .X ;_ffc :=_gb .P0 .X ;_b :=_gb .P0 .Y ;_be :=_gb .P0 .Y ;for _bef :=0.0;_bef <=1.0;_bef +=0.001{Rx :=_gb .P0 .X *_d .Pow (1-_bef ,3)+_gb .P1 .X *3*_bef *_d .Pow (1-_bef ,2)+_gb .P2 .X *3*_d .Pow (_bef ,2)*(1-_bef )+_gb .P3 .X *_d .Pow (_bef ,3);Ry :=_gb .P0 .Y *_d .Pow (1-_bef ,3)+_gb .P1 .Y *3*_bef *_d .Pow (1-_bef ,2)+_gb .P2 .Y *3*_d .Pow (_bef ,2)*(1-_bef )+_gb .P3 .Y *_d .Pow (_bef ,3);if Rx < _ff {_ff =Rx ;};if Rx > _ffc {_ffc =Rx ;};if Ry < _b {_b =Ry ;};if Ry > _be {_be =Ry ;};};_df :=_c .PdfRectangle {};_df .Llx =_ff ;_df .Lly =_b ;_df .Urx =_ffc ;_df .Ury =_be ;return _df ;}; // NewPoint returns a new point with the coordinates x, y. func NewPoint (x ,y float64 )Point {return Point {X :x ,Y :y }}; // Copy returns a clone of the path. func (_gae Path )Copy ()Path {_gbf :=Path {};_gbf .Points =append (_gbf .Points ,_gae .Points ...);return _gbf ;}; // Draw draws the polygon. A graphics state name can be specified for // setting the polygon properties (e.g. setting the opacity). Otherwise leave // empty (""). Returns the content stream as a byte array and the polygon // bounding box. func (_ggb Polygon )Draw (gsName string )([]byte ,*_c .PdfRectangle ,error ){_bag :=_ae .NewContentCreator ();_bag .Add_q ();_ggb .FillEnabled =_ggb .FillEnabled &&_ggb .FillColor !=nil ;if _ggb .FillEnabled {_bag .Add_rg (_ggb .FillColor .R (),_ggb .FillColor .G (),_ggb .FillColor .B ());};_ggb .BorderEnabled =_ggb .BorderEnabled &&_ggb .BorderColor !=nil ;if _ggb .BorderEnabled {_bag .Add_RG (_ggb .BorderColor .R (),_ggb .BorderColor .G (),_ggb .BorderColor .B ());_bag .Add_w (_ggb .BorderWidth );};if len (gsName )> 1{_bag .Add_gs (_a .PdfObjectName (gsName ));};_gcb :=NewPath ();for _ ,_abb :=range _ggb .Points {for _cf ,_fb :=range _abb {_gcb =_gcb .AppendPoint (_fb );if _cf ==0{_bag .Add_m (_fb .X ,_fb .Y );}else {_bag .Add_l (_fb .X ,_fb .Y );};};_bag .Add_h ();};if _ggb .FillEnabled &&_ggb .BorderEnabled {_bag .Add_B ();}else if _ggb .FillEnabled {_bag .Add_f ();}else if _ggb .BorderEnabled {_bag .Add_S ();};_bag .Add_Q ();return _bag .Bytes (),_gcb .GetBoundingBox ().ToPdfRectangle (),nil ;};func (_adc Point )String ()string {return _e .Sprintf ("(\u0025\u002e\u0031\u0066\u002c\u0025\u002e\u0031\u0066\u0029",_adc .X ,_adc .Y );}; // GetPointNumber returns the path point at the index specified by number. // The index is 1-based. func (_dd Path )GetPointNumber (number int )Point {if number < 1||number > len (_dd .Points ){return Point {};};return _dd .Points [number -1];}; // Draw draws the line to PDF contentstream. Generates the content stream which can be used in page contents or // appearance stream of annotation. Returns the stream content, XForm bounding box (local), bounding box and an error // if one occurred. func (_aa Line )Draw (gsName string )([]byte ,*_c .PdfRectangle ,error ){_dbb ,_gdcg :=_aa .X1 ,_aa .X2 ;_abd ,_agg :=_aa .Y1 ,_aa .Y2 ;_cab :=_agg -_abd ;_aac :=_gdcg -_dbb ;_fc :=_d .Atan2 (_cab ,_aac );L :=_d .Sqrt (_d .Pow (_aac ,2.0)+_d .Pow (_cab ,2.0));_ebb :=_aa .LineWidth ;_dea :=_d .Pi ;_cea :=1.0;if _aac < 0{_cea *=-1.0;};if _cab < 0{_cea *=-1.0;};VsX :=_cea *(-_ebb /2*_d .Cos (_fc +_dea /2));VsY :=_cea *(-_ebb /2*_d .Sin (_fc +_dea /2)+_ebb *_d .Sin (_fc +_dea /2));V1X :=VsX +_ebb /2*_d .Cos (_fc +_dea /2);V1Y :=VsY +_ebb /2*_d .Sin (_fc +_dea /2);V2X :=VsX +_ebb /2*_d .Cos (_fc +_dea /2)+L *_d .Cos (_fc );V2Y :=VsY +_ebb /2*_d .Sin (_fc +_dea /2)+L *_d .Sin (_fc );V3X :=VsX +_ebb /2*_d .Cos (_fc +_dea /2)+L *_d .Cos (_fc )+_ebb *_d .Cos (_fc -_dea /2);V3Y :=VsY +_ebb /2*_d .Sin (_fc +_dea /2)+L *_d .Sin (_fc )+_ebb *_d .Sin (_fc -_dea /2);V4X :=VsX +_ebb /2*_d .Cos (_fc -_dea /2);V4Y :=VsY +_ebb /2*_d .Sin (_fc -_dea /2);_deab :=NewPath ();_deab =_deab .AppendPoint (NewPoint (V1X ,V1Y ));_deab =_deab .AppendPoint (NewPoint (V2X ,V2Y ));_deab =_deab .AppendPoint (NewPoint (V3X ,V3Y ));_deab =_deab .AppendPoint (NewPoint (V4X ,V4Y ));_dgc :=_aa .LineEndingStyle1 ;_abc :=_aa .LineEndingStyle2 ;_efd :=3*_ebb ;_fca :=3*_ebb ;_bfa :=(_fca -_ebb )/2;if _abc ==LineEndingStyleArrow {_efdg :=_deab .GetPointNumber (2);_dga :=NewVectorPolar (_efd ,_fc +_dea );_dddd :=_efdg .AddVector (_dga );_adcc :=NewVectorPolar (_fca /2,_fc +_dea /2);_ceg :=NewVectorPolar (_efd ,_fc );_ged :=NewVectorPolar (_bfa ,_fc +_dea /2);_ecb :=_dddd .AddVector (_ged );_fbc :=_ceg .Add (_adcc .Flip ());_efb :=_ecb .AddVector (_fbc );_fbf :=_adcc .Scale (2).Flip ().Add (_fbc .Flip ());_ffa :=_efb .AddVector (_fbf );_dfa :=_dddd .AddVector (NewVectorPolar (_ebb ,_fc -_dea /2));_aeb :=NewPath ();_aeb =_aeb .AppendPoint (_deab .GetPointNumber (1));_aeb =_aeb .AppendPoint (_dddd );_aeb =_aeb .AppendPoint (_ecb );_aeb =_aeb .AppendPoint (_efb );_aeb =_aeb .AppendPoint (_ffa );_aeb =_aeb .AppendPoint (_dfa );_aeb =_aeb .AppendPoint (_deab .GetPointNumber (4));_deab =_aeb ;};if _dgc ==LineEndingStyleArrow {_ebca :=_deab .GetPointNumber (1);_gadg :=_deab .GetPointNumber (_deab .Length ());_bgg :=NewVectorPolar (_ebb /2,_fc +_dea +_dea /2);_eeg :=_ebca .AddVector (_bgg );_gab :=NewVectorPolar (_efd ,_fc ).Add (NewVectorPolar (_fca /2,_fc +_dea /2));_adb :=_eeg .AddVector (_gab );_aab :=NewVectorPolar (_bfa ,_fc -_dea /2);_ade :=_adb .AddVector (_aab );_beff :=NewVectorPolar (_efd ,_fc );_cfb :=_gadg .AddVector (_beff );_adba :=NewVectorPolar (_bfa ,_fc +_dea +_dea /2);_cee :=_cfb .AddVector (_adba );_abgb :=_eeg ;_adg :=NewPath ();_adg =_adg .AppendPoint (_eeg );_adg =_adg .AppendPoint (_adb );_adg =_adg .AppendPoint (_ade );for _ ,_cac :=range _deab .Points [1:len (_deab .Points )-1]{_adg =_adg .AppendPoint (_cac );};_adg =_adg .AppendPoint (_cfb );_adg =_adg .AppendPoint (_cee );_adg =_adg .AppendPoint (_abgb );_deab =_adg ;};_dgd :=_ae .NewContentCreator ();_dgd .Add_q ().Add_rg (_aa .LineColor .R (),_aa .LineColor .G (),_aa .LineColor .B ());if len (gsName )> 1{_dgd .Add_gs (_a .PdfObjectName (gsName ));};_deab =_deab .Offset (_aa .X1 ,_aa .Y1 );_gfg :=_deab .GetBoundingBox ();DrawPathWithCreator (_deab ,_dgd );if _aa .LineStyle ==LineStyleDashed {_dgd .Add_d ([]int64 {1,1},0).Add_S ().Add_f ().Add_Q ();}else {_dgd .Add_f ().Add_Q ();};return _dgd .Bytes (),_gfg .ToPdfRectangle (),nil ;}; // GetPolarAngle returns the angle the magnitude of the vector forms with the // positive X-axis going counterclockwise. func (_gcd Vector )GetPolarAngle ()float64 {return _d .Atan2 (_gcd .Dy ,_gcd .Dx )};