// // 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 (_f "fmt";_b "github.com/unidoc/unipdf/v3/contentstream";_e "github.com/unidoc/unipdf/v3/core";_ee "github.com/unidoc/unipdf/v3/internal/transform";_fe "github.com/unidoc/unipdf/v3/model";_g "math";); // FlipY flips the sign of the Dy component of the vector. func (_aac Vector )FlipY ()Vector {_aac .Dy =-_aac .Dy ;return _aac }; // 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 *_b .ContentCreator ){for _fdd ,_ffg :=range path .Points {if _fdd ==0{creator .Add_m (_ffg .X ,_ffg .Y );}else {creator .Add_l (_ffg .X ,_ffg .Y );};};};const (LineStyleSolid LineStyle =0;LineStyleDashed LineStyle =1;); // Rotate rotates the vector by the specified angle. func (_ga Vector )Rotate (phi float64 )Vector {_ccd :=_ga .Magnitude ();_aaa :=_ga .GetPolarAngle ();return NewVectorPolar (_ccd ,_aaa +phi );}; // NewCubicBezierCurve returns a new cubic Bezier curve. func NewCubicBezierCurve (x0 ,y0 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 float64 )CubicBezierCurve {_fea :=CubicBezierCurve {};_fea .P0 =NewPoint (x0 ,y0 );_fea .P1 =NewPoint (x1 ,y1 );_fea .P2 =NewPoint (x2 ,y2 );_fea .P3 =NewPoint (x3 ,y3 );return _fea ;}; // BoundingBox represents the smallest rectangular area that encapsulates an object. type BoundingBox struct{X float64 ;Y float64 ;Width float64 ;Height float64 ;}; // ToPdfRectangle returns the bounding box as a PDF rectangle. func (_dgg BoundingBox )ToPdfRectangle ()*_fe .PdfRectangle {return &_fe .PdfRectangle {Llx :_dgg .X ,Lly :_dgg .Y ,Urx :_dgg .X +_dgg .Width ,Ury :_dgg .Y +_dgg .Height };}; // 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 *_fe .PdfColorDeviceRGB ;BorderEnabled bool ;BorderWidth float64 ;BorderColor *_fe .PdfColorDeviceRGB ;Opacity float64 ;}; // GetBoundingBox returns the bounding box of the path. func (_dg Path )GetBoundingBox ()BoundingBox {_cd :=BoundingBox {};_cgf :=0.0;_ce :=0.0;_dc :=0.0;_bb :=0.0;for _af ,_ea :=range _dg .Points {if _af ==0{_cgf =_ea .X ;_ce =_ea .X ;_dc =_ea .Y ;_bb =_ea .Y ;continue ;};if _ea .X < _cgf {_cgf =_ea .X ;};if _ea .X > _ce {_ce =_ea .X ;};if _ea .Y < _dc {_dc =_ea .Y ;};if _ea .Y > _bb {_bb =_ea .Y ;};};_cd .X =_cgf ;_cd .Y =_dc ;_cd .Width =_ce -_cgf ;_cd .Height =_bb -_dc ;return _cd ;}; // 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 *_b .ContentCreator ){for _ebf ,_bcga :=range bpath .Curves {if _ebf ==0{creator .Add_m (_bcga .P0 .X ,_bcga .P0 .Y );};creator .Add_c (_bcga .P1 .X ,_bcga .P1 .Y ,_bcga .P2 .X ,_bcga .P2 .Y ,_bcga .P3 .X ,_bcga .P3 .Y );};}; // 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 *_fe .PdfColorDeviceRGB ;Opacity float64 ;LineWidth float64 ;LineEndingStyle1 LineEndingStyle ;LineEndingStyle2 LineEndingStyle ;LineStyle LineStyle ;}; // Scale scales the vector by the specified factor. func (_ceb Vector )Scale (factor float64 )Vector {_ffc :=_ceb .Magnitude ();_ccc :=_ceb .GetPolarAngle ();_ceb .Dx =factor *_ffc *_g .Cos (_ccc );_ceb .Dy =factor *_ffc *_g .Sin (_ccc );return _ceb ;}; // NewPoint returns a new point with the coordinates x, y. func NewPoint (x ,y float64 )Point {return Point {X :x ,Y :y }};func (_adb Point )String ()string {return _f .Sprintf ("(\u0025\u002e\u0031\u0066\u002c\u0025\u002e\u0031\u0066\u0029",_adb .X ,_adb .Y );}; // PolyBezierCurve represents a composite curve that is the result of // joining multiple cubic Bezier curves. type PolyBezierCurve struct{Curves []CubicBezierCurve ;BorderWidth float64 ;BorderColor *_fe .PdfColorDeviceRGB ;FillEnabled bool ;FillColor *_fe .PdfColorDeviceRGB ;}; // 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 (_edb Polyline )Draw (gsName string )([]byte ,*_fe .PdfRectangle ,error ){if _edb .LineColor ==nil {_edb .LineColor =_fe .NewPdfColorDeviceRGB (0,0,0);};_bagd :=NewPath ();for _ ,_bda :=range _edb .Points {_bagd =_bagd .AppendPoint (_bda );};_gfb :=_b .NewContentCreator ();_gfb .Add_q ();_gfb .Add_RG (_edb .LineColor .R (),_edb .LineColor .G (),_edb .LineColor .B ());_gfb .Add_w (_edb .LineWidth );if len (gsName )> 1{_gfb .Add_gs (_e .PdfObjectName (gsName ));};DrawPathWithCreator (_bagd ,_gfb );_gfb .Add_S ();_gfb .Add_Q ();return _gfb .Bytes (),_bagd .GetBoundingBox ().ToPdfRectangle (),nil ;}; // AppendCurve appends the specified Bezier curve to the path. func (_de CubicBezierPath )AppendCurve (curve CubicBezierCurve )CubicBezierPath {_de .Curves =append (_de .Curves ,curve );return _de ;}; // Magnitude returns the magnitude of the vector. func (_gde Vector )Magnitude ()float64 {return _g .Sqrt (_g .Pow (_gde .Dx ,2.0)+_g .Pow (_gde .Dy ,2.0))}; // Copy returns a clone of the Bezier path. func (_fg CubicBezierPath )Copy ()CubicBezierPath {_aa :=CubicBezierPath {};_aa .Curves =[]CubicBezierCurve {};for _ ,_dd :=range _fg .Curves {_aa .Curves =append (_aa .Curves ,_dd );};return _aa ;}; // Flip changes the sign of the vector: -vector. func (_eecg Vector )Flip ()Vector {_cbg :=_eecg .Magnitude ();_cgd :=_eecg .GetPolarAngle ();_eecg .Dx =_cbg *_g .Cos (_cgd +_g .Pi );_eecg .Dy =_cbg *_g .Sin (_cgd +_g .Pi );return _eecg ;}; // 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 (_afa Polygon )Draw (gsName string )([]byte ,*_fe .PdfRectangle ,error ){_dcf :=_b .NewContentCreator ();_dcf .Add_q ();_afa .FillEnabled =_afa .FillEnabled &&_afa .FillColor !=nil ;if _afa .FillEnabled {_dcf .Add_rg (_afa .FillColor .R (),_afa .FillColor .G (),_afa .FillColor .B ());};_afa .BorderEnabled =_afa .BorderEnabled &&_afa .BorderColor !=nil ;if _afa .BorderEnabled {_dcf .Add_RG (_afa .BorderColor .R (),_afa .BorderColor .G (),_afa .BorderColor .B ());_dcf .Add_w (_afa .BorderWidth );};if len (gsName )> 1{_dcf .Add_gs (_e .PdfObjectName (gsName ));};_ead :=NewPath ();for _ ,_gff :=range _afa .Points {for _dff ,_edf :=range _gff {_ead =_ead .AppendPoint (_edf );if _dff ==0{_dcf .Add_m (_edf .X ,_edf .Y );}else {_dcf .Add_l (_edf .X ,_edf .Y );};};_dcf .Add_h ();};if _afa .FillEnabled &&_afa .BorderEnabled {_dcf .Add_B ();}else if _afa .FillEnabled {_dcf .Add_f ();}else if _afa .BorderEnabled {_dcf .Add_S ();};_dcf .Add_Q ();return _dcf .Bytes (),_ead .GetBoundingBox ().ToPdfRectangle (),nil ;}; // 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 (_bf BasicLine )Draw (gsName string )([]byte ,*_fe .PdfRectangle ,error ){_agd :=_bf .LineWidth ;_egd :=NewPath ();_egd =_egd .AppendPoint (NewPoint (_bf .X1 ,_bf .Y1 ));_egd =_egd .AppendPoint (NewPoint (_bf .X2 ,_bf .Y2 ));_fbe :=_b .NewContentCreator ();_bab :=_egd .GetBoundingBox ();DrawPathWithCreator (_egd ,_fbe );if _bf .LineStyle ==LineStyleDashed {_fbe .Add_d ([]int64 {1,1},0);};_fbe .Add_RG (_bf .LineColor .R (),_bf .LineColor .G (),_bf .LineColor .B ()).Add_w (_agd ).Add_S ().Add_Q ();return _fbe .Bytes (),_bab .ToPdfRectangle (),nil ;}; // Copy returns a clone of the path. func (_fc Path )Copy ()Path {_ag :=Path {};_ag .Points =[]Point {};for _ ,_gga :=range _fc .Points {_ag .Points =append (_ag .Points ,_gga );};return _ag ;}; // Polygon is a multi-point shape that can be drawn to a PDF content stream. type Polygon struct{Points [][]Point ;FillEnabled bool ;FillColor *_fe .PdfColorDeviceRGB ;BorderEnabled bool ;BorderColor *_fe .PdfColorDeviceRGB ;BorderWidth float64 ;}; // Length returns the number of points in the path. func (_bcg Path )Length ()int {return len (_bcg .Points )}; // GetBoundingBox returns the bounding box of the Bezier path. func (_efe CubicBezierPath )GetBoundingBox ()Rectangle {_gc :=Rectangle {};_cb :=0.0;_ddb :=0.0;_aeb :=0.0;_ca :=0.0;for _cf ,_ec :=range _efe .Curves {_db :=_ec .GetBounds ();if _cf ==0{_cb =_db .Llx ;_ddb =_db .Urx ;_aeb =_db .Lly ;_ca =_db .Ury ;continue ;};if _db .Llx < _cb {_cb =_db .Llx ;};if _db .Urx > _ddb {_ddb =_db .Urx ;};if _db .Lly < _aeb {_aeb =_db .Lly ;};if _db .Ury > _ca {_ca =_db .Ury ;};};_gc .X =_cb ;_gc .Y =_aeb ;_gc .Width =_ddb -_cb ;_gc .Height =_ca -_aeb ;return _gc ;}; // Add shifts the coordinates of the point with dx, dy and returns the result. func (_cff Point )Add (dx ,dy float64 )Point {_cff .X +=dx ;_cff .Y +=dy ;return _cff }; // NewCubicBezierPath returns a new empty cubic Bezier path. func NewCubicBezierPath ()CubicBezierPath {_da :=CubicBezierPath {};_da .Curves =[]CubicBezierCurve {};return _da ;}; // 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 (_bcfe Line )Draw (gsName string )([]byte ,*_fe .PdfRectangle ,error ){_eef ,_gd :=_bcfe .X1 ,_bcfe .X2 ;_gdf ,_efd :=_bcfe .Y1 ,_bcfe .Y2 ;_bcgf :=_efd -_gdf ;_eeg :=_gd -_eef ;_efa :=_g .Atan2 (_bcgf ,_eeg );L :=_g .Sqrt (_g .Pow (_eeg ,2.0)+_g .Pow (_bcgf ,2.0));_cdb :=_bcfe .LineWidth ;_afc :=_g .Pi ;_gfe :=1.0;if _eeg < 0{_gfe *=-1.0;};if _bcgf < 0{_gfe *=-1.0;};VsX :=_gfe *(-_cdb /2*_g .Cos (_efa +_afc /2));VsY :=_gfe *(-_cdb /2*_g .Sin (_efa +_afc /2)+_cdb *_g .Sin (_efa +_afc /2));V1X :=VsX +_cdb /2*_g .Cos (_efa +_afc /2);V1Y :=VsY +_cdb /2*_g .Sin (_efa +_afc /2);V2X :=VsX +_cdb /2*_g .Cos (_efa +_afc /2)+L *_g .Cos (_efa );V2Y :=VsY +_cdb /2*_g .Sin (_efa +_afc /2)+L *_g .Sin (_efa );V3X :=VsX +_cdb /2*_g .Cos (_efa +_afc /2)+L *_g .Cos (_efa )+_cdb *_g .Cos (_efa -_afc /2);V3Y :=VsY +_cdb /2*_g .Sin (_efa +_afc /2)+L *_g .Sin (_efa )+_cdb *_g .Sin (_efa -_afc /2);V4X :=VsX +_cdb /2*_g .Cos (_efa -_afc /2);V4Y :=VsY +_cdb /2*_g .Sin (_efa -_afc /2);_daa :=NewPath ();_daa =_daa .AppendPoint (NewPoint (V1X ,V1Y ));_daa =_daa .AppendPoint (NewPoint (V2X ,V2Y ));_daa =_daa .AppendPoint (NewPoint (V3X ,V3Y ));_daa =_daa .AppendPoint (NewPoint (V4X ,V4Y ));_ece :=_bcfe .LineEndingStyle1 ;_ebb :=_bcfe .LineEndingStyle2 ;_dge :=3*_cdb ;_ceg :=3*_cdb ;_ac :=(_ceg -_cdb )/2;if _ebb ==LineEndingStyleArrow {_affb :=_daa .GetPointNumber (2);_fde :=NewVectorPolar (_dge ,_efa +_afc );_dfe :=_affb .AddVector (_fde );_bgc :=NewVectorPolar (_ceg /2,_efa +_afc /2);_afag :=NewVectorPolar (_dge ,_efa );_ecc :=NewVectorPolar (_ac ,_efa +_afc /2);_dce :=_dfe .AddVector (_ecc );_cfg :=_afag .Add (_bgc .Flip ());_fb :=_dce .AddVector (_cfg );_cec :=_bgc .Scale (2).Flip ().Add (_cfg .Flip ());_fbb :=_fb .AddVector (_cec );_ba :=_dfe .AddVector (NewVectorPolar (_cdb ,_efa -_afc /2));_eec :=NewPath ();_eec =_eec .AppendPoint (_daa .GetPointNumber (1));_eec =_eec .AppendPoint (_dfe );_eec =_eec .AppendPoint (_dce );_eec =_eec .AppendPoint (_fb );_eec =_eec .AppendPoint (_fbb );_eec =_eec .AppendPoint (_ba );_eec =_eec .AppendPoint (_daa .GetPointNumber (4));_daa =_eec ;};if _ece ==LineEndingStyleArrow {_dffa :=_daa .GetPointNumber (1);_aab :=_daa .GetPointNumber (_daa .Length ());_cecc :=NewVectorPolar (_cdb /2,_efa +_afc +_afc /2);_cef :=_dffa .AddVector (_cecc );_gdc :=NewVectorPolar (_dge ,_efa ).Add (NewVectorPolar (_ceg /2,_efa +_afc /2));_gb :=_cef .AddVector (_gdc );_aec :=NewVectorPolar (_ac ,_efa -_afc /2);_bag :=_gb .AddVector (_aec );_gfed :=NewVectorPolar (_dge ,_efa );_bd :=_aab .AddVector (_gfed );_dee :=NewVectorPolar (_ac ,_efa +_afc +_afc /2);_dfg :=_bd .AddVector (_dee );_gda :=_cef ;_egb :=NewPath ();_egb =_egb .AppendPoint (_cef );_egb =_egb .AppendPoint (_gb );_egb =_egb .AppendPoint (_bag );for _ ,_fcb :=range _daa .Points [1:len (_daa .Points )-1]{_egb =_egb .AppendPoint (_fcb );};_egb =_egb .AppendPoint (_bd );_egb =_egb .AppendPoint (_dfg );_egb =_egb .AppendPoint (_gda );_daa =_egb ;};_ebc :=_b .NewContentCreator ();_ebc .Add_q ().Add_rg (_bcfe .LineColor .R (),_bcfe .LineColor .G (),_bcfe .LineColor .B ());if len (gsName )> 1{_ebc .Add_gs (_e .PdfObjectName (gsName ));};_daa =_daa .Offset (_bcfe .X1 ,_bcfe .Y1 );_dfa :=_daa .GetBoundingBox ();DrawPathWithCreator (_daa ,_ebc );if _bcfe .LineStyle ==LineStyleDashed {_ebc .Add_d ([]int64 {1,1},0).Add_S ().Add_f ().Add_Q ();}else {_ebc .Add_f ().Add_Q ();};return _ebc .Bytes (),_dfa .ToPdfRectangle (),nil ;}; // Point represents a two-dimensional point. type Point struct{X float64 ;Y float64 ;}; // LineStyle refers to how the line will be created. type LineStyle int ; // 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 (_dcg Rectangle )Draw (gsName string )([]byte ,*_fe .PdfRectangle ,error ){_fed :=NewPath ();_fed =_fed .AppendPoint (NewPoint (0,0));_fed =_fed .AppendPoint (NewPoint (0,_dcg .Height ));_fed =_fed .AppendPoint (NewPoint (_dcg .Width ,_dcg .Height ));_fed =_fed .AppendPoint (NewPoint (_dcg .Width ,0));_fed =_fed .AppendPoint (NewPoint (0,0));if _dcg .X !=0||_dcg .Y !=0{_fed =_fed .Offset (_dcg .X ,_dcg .Y );};_ff :=_b .NewContentCreator ();_ff .Add_q ();if _dcg .FillEnabled {_ff .Add_rg (_dcg .FillColor .R (),_dcg .FillColor .G (),_dcg .FillColor .B ());};if _dcg .BorderEnabled {_ff .Add_RG (_dcg .BorderColor .R (),_dcg .BorderColor .G (),_dcg .BorderColor .B ());_ff .Add_w (_dcg .BorderWidth );};if len (gsName )> 1{_ff .Add_gs (_e .PdfObjectName (gsName ));};DrawPathWithCreator (_fed ,_ff );_ff .Add_h ();if _dcg .FillEnabled &&_dcg .BorderEnabled {_ff .Add_B ();}else if _dcg .FillEnabled {_ff .Add_f ();}else if _dcg .BorderEnabled {_ff .Add_S ();};_ff .Add_Q ();return _ff .Bytes (),_fed .GetBoundingBox ().ToPdfRectangle (),nil ;}; // CubicBezierPath represents a collection of cubic Bezier curves. type CubicBezierPath struct{Curves []CubicBezierCurve ;}; // 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 *_fe .PdfColorDeviceRGB ;Opacity float64 ;LineWidth float64 ;LineStyle LineStyle ;}; // Vector represents a two-dimensional vector. type Vector struct{Dx float64 ;Dy float64 ;};const (LineEndingStyleNone LineEndingStyle =0;LineEndingStyleArrow LineEndingStyle =1;LineEndingStyleButt LineEndingStyle =2;); // NewPath returns a new empty path. func NewPath ()Path {return Path {}}; // Offset shifts the Bezier path with the specified offsets. func (_bg CubicBezierPath )Offset (offX ,offY float64 )CubicBezierPath {for _dad ,_cg :=range _bg .Curves {_bg .Curves [_dad ]=_cg .AddOffsetXY (offX ,offY );};return _bg ;}; // 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 ;}; // LineEndingStyle defines the line ending style for lines. // The currently supported line ending styles are None, Arrow (ClosedArrow) and Butt. type LineEndingStyle int ; // 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 *_fe .PdfColorDeviceRGB ;BorderEnabled bool ;BorderWidth float64 ;BorderColor *_fe .PdfColorDeviceRGB ;Opacity float64 ;}; // GetBounds returns the bounding box of the Bezier curve. func (_d CubicBezierCurve )GetBounds ()_fe .PdfRectangle {_ggc :=_d .P0 .X ;_ae :=_d .P0 .X ;_ad :=_d .P0 .Y ;_eb :=_d .P0 .Y ;for _c :=0.0;_c <=1.0;_c +=0.001{Rx :=_d .P0 .X *_g .Pow (1-_c ,3)+_d .P1 .X *3*_c *_g .Pow (1-_c ,2)+_d .P2 .X *3*_g .Pow (_c ,2)*(1-_c )+_d .P3 .X *_g .Pow (_c ,3);Ry :=_d .P0 .Y *_g .Pow (1-_c ,3)+_d .P1 .Y *3*_c *_g .Pow (1-_c ,2)+_d .P2 .Y *3*_g .Pow (_c ,2)*(1-_c )+_d .P3 .Y *_g .Pow (_c ,3);if Rx < _ggc {_ggc =Rx ;};if Rx > _ae {_ae =Rx ;};if Ry < _ad {_ad =Ry ;};if Ry > _eb {_eb =Ry ;};};_ef :=_fe .PdfRectangle {};_ef .Llx =_ggc ;_ef .Lly =_ad ;_ef .Urx =_ae ;_ef .Ury =_eb ;return _ef ;}; // 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 (_ge PolyBezierCurve )Draw (gsName string )([]byte ,*_fe .PdfRectangle ,error ){if _ge .BorderColor ==nil {_ge .BorderColor =_fe .NewPdfColorDeviceRGB (0,0,0);};_feb :=NewCubicBezierPath ();for _ ,_cc :=range _ge .Curves {_feb =_feb .AppendCurve (_cc );};_age :=_b .NewContentCreator ();_age .Add_q ();_ge .FillEnabled =_ge .FillEnabled &&_ge .FillColor !=nil ;if _ge .FillEnabled {_age .Add_rg (_ge .FillColor .R (),_ge .FillColor .G (),_ge .FillColor .B ());};_age .Add_RG (_ge .BorderColor .R (),_ge .BorderColor .G (),_ge .BorderColor .B ());_age .Add_w (_ge .BorderWidth );if len (gsName )> 1{_age .Add_gs (_e .PdfObjectName (gsName ));};for _ ,_ccf :=range _feb .Curves {_age .Add_m (_ccf .P0 .X ,_ccf .P0 .Y );_age .Add_c (_ccf .P1 .X ,_ccf .P1 .Y ,_ccf .P2 .X ,_ccf .P2 .Y ,_ccf .P3 .X ,_ccf .P3 .Y );};if _ge .FillEnabled {_age .Add_h ();_age .Add_B ();}else {_age .Add_S ();};_age .Add_Q ();return _age .Bytes (),_feb .GetBoundingBox ().ToPdfRectangle (),nil ;}; // Polyline defines a slice of points that are connected as straight lines. type Polyline struct{Points []Point ;LineColor *_fe .PdfColorDeviceRGB ;LineWidth float64 ;}; // 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 {_bbc :=Vector {};_bbc .Dx =b .X -a .X ;_bbc .Dy =b .Y -a .Y ;return _bbc ;}; // NewVector returns a new vector with the direction specified by dx and dy. func NewVector (dx ,dy float64 )Vector {_cce :=Vector {};_cce .Dx =dx ;_cce .Dy =dy ;return _cce }; // GetPointNumber returns the path point at the index specified by number. // The index is 1-based. func (_be Path )GetPointNumber (number int )Point {if number < 1||number > len (_be .Points ){return Point {};};return _be .Points [number -1];}; // Add adds the specified vector to the current one and returns the result. func (_ab Vector )Add (other Vector )Vector {_ab .Dx +=other .Dx ;_ab .Dy +=other .Dy ;return _ab }; // Rotate returns a new Point at `p` rotated by `theta` degrees. func (_fa Point )Rotate (theta float64 )Point {_agg :=_ee .NewPoint (_fa .X ,_fa .Y ).Rotate (theta );return NewPoint (_agg .X ,_agg .Y );}; // Path consists of straight line connections between each point defined in an array of points. type Path struct{Points []Point ;}; // AddOffsetXY adds X,Y offset to all points on a curve. func (_gg CubicBezierCurve )AddOffsetXY (offX ,offY float64 )CubicBezierCurve {_gg .P0 .X +=offX ;_gg .P1 .X +=offX ;_gg .P2 .X +=offX ;_gg .P3 .X +=offX ;_gg .P0 .Y +=offY ;_gg .P1 .Y +=offY ;_gg .P2 .Y +=offY ;_gg .P3 .Y +=offY ;return _gg ;}; // RemovePoint removes the point at the index specified by number from the // path. The index is 1-based. func (_cfd Path )RemovePoint (number int )Path {if number < 1||number > len (_cfd .Points ){return _cfd ;};_add :=number -1;_cfd .Points =append (_cfd .Points [:_add ],_cfd .Points [_add +1:]...);return _cfd ;}; // AppendPoint adds the specified point to the path. func (_cbd Path )AppendPoint (point Point )Path {_cbd .Points =append (_cbd .Points ,point );return _cbd }; // NewVectorPolar returns a new vector calculated from the specified // magnitude and angle. func NewVectorPolar (length float64 ,theta float64 )Vector {_eeb :=Vector {};_eeb .Dx =length *_g .Cos (theta );_eeb .Dy =length *_g .Sin (theta );return _eeb ;}; // FlipX flips the sign of the Dx component of the vector. func (_cgc Vector )FlipX ()Vector {_cgc .Dx =-_cgc .Dx ;return _cgc }; // 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 (_ecd Circle )Draw (gsName string )([]byte ,*_fe .PdfRectangle ,error ){_bcf :=_ecd .Width /2;_gfg :=_ecd .Height /2;if _ecd .BorderEnabled {_bcf -=_ecd .BorderWidth /2;_gfg -=_ecd .BorderWidth /2;};_agb :=0.551784;_fce :=_bcf *_agb ;_fd :=_gfg *_agb ;_ggca :=NewCubicBezierPath ();_ggca =_ggca .AppendCurve (NewCubicBezierCurve (-_bcf ,0,-_bcf ,_fd ,-_fce ,_gfg ,0,_gfg ));_ggca =_ggca .AppendCurve (NewCubicBezierCurve (0,_gfg ,_fce ,_gfg ,_bcf ,_fd ,_bcf ,0));_ggca =_ggca .AppendCurve (NewCubicBezierCurve (_bcf ,0,_bcf ,-_fd ,_fce ,-_gfg ,0,-_gfg ));_ggca =_ggca .AppendCurve (NewCubicBezierCurve (0,-_gfg ,-_fce ,-_gfg ,-_bcf ,-_fd ,-_bcf ,0));_ggca =_ggca .Offset (_bcf ,_gfg );if _ecd .BorderEnabled {_ggca =_ggca .Offset (_ecd .BorderWidth /2,_ecd .BorderWidth /2);};if _ecd .X !=0||_ecd .Y !=0{_ggca =_ggca .Offset (_ecd .X ,_ecd .Y );};_dbg :=_b .NewContentCreator ();_dbg .Add_q ();if _ecd .FillEnabled {_dbg .Add_rg (_ecd .FillColor .R (),_ecd .FillColor .G (),_ecd .FillColor .B ());};if _ecd .BorderEnabled {_dbg .Add_RG (_ecd .BorderColor .R (),_ecd .BorderColor .G (),_ecd .BorderColor .B ());_dbg .Add_w (_ecd .BorderWidth );};if len (gsName )> 1{_dbg .Add_gs (_e .PdfObjectName (gsName ));};DrawBezierPathWithCreator (_ggca ,_dbg );_dbg .Add_h ();if _ecd .FillEnabled &&_ecd .BorderEnabled {_dbg .Add_B ();}else if _ecd .FillEnabled {_dbg .Add_f ();}else if _ecd .BorderEnabled {_dbg .Add_S ();};_dbg .Add_Q ();_eg :=_ggca .GetBoundingBox ();if _ecd .BorderEnabled {_eg .Height +=_ecd .BorderWidth ;_eg .Width +=_ecd .BorderWidth ;_eg .X -=_ecd .BorderWidth /2;_eg .Y -=_ecd .BorderWidth /2;};return _dbg .Bytes (),_eg .ToPdfRectangle (),nil ;}; // Offset shifts the path with the specified offsets. func (_gf Path )Offset (offX ,offY float64 )Path {for _df ,_ed :=range _gf .Points {_gf .Points [_df ]=_ed .Add (offX ,offY );};return _gf ;}; // ToPdfRectangle returns the rectangle as a PDF rectangle. func (_gfa Rectangle )ToPdfRectangle ()*_fe .PdfRectangle {return &_fe .PdfRectangle {Llx :_gfa .X ,Lly :_gfa .Y ,Urx :_gfa .X +_gfa .Width ,Ury :_gfa .Y +_gfa .Height };}; // GetPolarAngle returns the angle the magnitude of the vector forms with the // positive X-axis going counterclockwise. func (_faf Vector )GetPolarAngle ()float64 {return _g .Atan2 (_faf .Dy ,_faf .Dx )}; // AddVector adds vector to a point. func (_dac Point )AddVector (v Vector )Point {_dac .X +=v .Dx ;_dac .Y +=v .Dy ;return _dac };