217 lines
24 KiB
Go
Raw Normal View History

2020-08-27 21:45:09 +00:00
//
// 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).
2021-02-11 10:35:13 +00:00
package draw ;import (_a "fmt";_ab "github.com/unidoc/unipdf/v3/contentstream";_b "github.com/unidoc/unipdf/v3/core";_af "github.com/unidoc/unipdf/v3/internal/transform";_eb "github.com/unidoc/unipdf/v3/model";_f "math";);
// 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 (_bfe Polyline )Draw (gsName string )([]byte ,*_eb .PdfRectangle ,error ){if _bfe .LineColor ==nil {_bfe .LineColor =_eb .NewPdfColorDeviceRGB (0,0,0);};_dgc :=NewPath ();for _ ,_cgb :=range _bfe .Points {_dgc =_dgc .AppendPoint (_cgb );};_bbc :=_ab .NewContentCreator ();_bbc .Add_q ();_bbc .Add_RG (_bfe .LineColor .R (),_bfe .LineColor .G (),_bfe .LineColor .B ());_bbc .Add_w (_bfe .LineWidth );if len (gsName )> 1{_bbc .Add_gs (_b .PdfObjectName (gsName ));};DrawPathWithCreator (_dgc ,_bbc );_bbc .Add_S ();_bbc .Add_Q ();return _bbc .Bytes (),_dgc .GetBoundingBox ().ToPdfRectangle (),nil ;};
// AppendPoint adds the specified point to the path.
func (_eba Path )AppendPoint (point Point )Path {_eba .Points =append (_eba .Points ,point );return _eba };
// 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 *_eb .PdfColorDeviceRGB ;BorderEnabled bool ;BorderWidth float64 ;BorderColor *_eb .PdfColorDeviceRGB ;Opacity float64 ;};
// CubicBezierPath represents a collection of cubic Bezier curves.
type CubicBezierPath struct{Curves []CubicBezierCurve ;};
// AppendCurve appends the specified Bezier curve to the path.
func (_bd CubicBezierPath )AppendCurve (curve CubicBezierCurve )CubicBezierPath {_bd .Curves =append (_bd .Curves ,curve );return _bd ;};
2020-08-27 21:45:09 +00:00
2021-01-26 01:31:56 +00:00
// BoundingBox represents the smallest rectangular area that encapsulates an object.
type BoundingBox struct{X float64 ;Y float64 ;Width float64 ;Height float64 ;};
2020-08-31 21:12:07 +00:00
2021-02-11 10:35:13 +00:00
// NewCubicBezierPath returns a new empty cubic Bezier path.
func NewCubicBezierPath ()CubicBezierPath {_ed :=CubicBezierPath {};_ed .Curves =[]CubicBezierCurve {};return _ed ;};
2021-01-26 01:31:56 +00:00
2021-02-11 10:35:13 +00:00
// Length returns the number of points in the path.
func (_de Path )Length ()int {return len (_de .Points )};
2021-01-26 01:31:56 +00:00
2021-02-11 10:35:13 +00:00
// 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 *_eb .PdfColorDeviceRGB ;BorderEnabled bool ;BorderWidth float64 ;BorderColor *_eb .PdfColorDeviceRGB ;Opacity float64 ;};
2021-01-26 01:31:56 +00:00
2021-02-11 10:35:13 +00:00
// NewCubicBezierCurve returns a new cubic Bezier curve.
func NewCubicBezierCurve (x0 ,y0 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 float64 )CubicBezierCurve {_c :=CubicBezierCurve {};_c .P0 =NewPoint (x0 ,y0 );_c .P1 =NewPoint (x1 ,y1 );_c .P2 =NewPoint (x2 ,y2 );_c .P3 =NewPoint (x3 ,y3 );return _c ;};
2020-08-27 21:45:09 +00:00
2021-02-11 10:35:13 +00:00
// Add shifts the coordinates of the point with dx, dy and returns the result.
func (_gbg Point )Add (dx ,dy float64 )Point {_gbg .X +=dx ;_gbg .Y +=dy ;return _gbg };
2020-08-27 21:45:09 +00:00
2021-02-11 10:35:13 +00:00
// GetPolarAngle returns the angle the magnitude of the vector forms with the
// positive X-axis going counterclockwise.
func (_adc Vector )GetPolarAngle ()float64 {return _f .Atan2 (_adc .Dy ,_adc .Dx )};
2020-10-12 14:17:59 +00:00
2021-02-11 10:35:13 +00:00
// GetBoundingBox returns the bounding box of the path.
func (_gd Path )GetBoundingBox ()BoundingBox {_fc :=BoundingBox {};_gf :=0.0;_gdc :=0.0;_cb :=0.0;_dgb :=0.0;for _fgc ,_gg :=range _gd .Points {if _fgc ==0{_gf =_gg .X ;_gdc =_gg .X ;_cb =_gg .Y ;_dgb =_gg .Y ;continue ;};if _gg .X < _gf {_gf =_gg .X ;};if _gg .X > _gdc {_gdc =_gg .X ;};if _gg .Y < _cb {_cb =_gg .Y ;};if _gg .Y > _dgb {_dgb =_gg .Y ;};};_fc .X =_gf ;_fc .Y =_cb ;_fc .Width =_gdc -_gf ;_fc .Height =_dgb -_cb ;return _fc ;};
// Path consists of straight line connections between each point defined in an array of points.
type Path struct{Points []Point ;};
2020-10-19 10:58:10 +00:00
2021-01-26 01:31:56 +00:00
// 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.
2021-02-11 10:35:13 +00:00
func (_cbef BasicLine )Draw (gsName string )([]byte ,*_eb .PdfRectangle ,error ){_afb :=_cbef .LineWidth ;_bggg :=NewPath ();_bggg =_bggg .AppendPoint (NewPoint (_cbef .X1 ,_cbef .Y1 ));_bggg =_bggg .AppendPoint (NewPoint (_cbef .X2 ,_cbef .Y2 ));_gbf :=_ab .NewContentCreator ();_ag :=_bggg .GetBoundingBox ();DrawPathWithCreator (_bggg ,_gbf );if _cbef .LineStyle ==LineStyleDashed {_gbf .Add_d ([]int64 {1,1},0);};_gbf .Add_RG (_cbef .LineColor .R (),_cbef .LineColor .G (),_cbef .LineColor .B ()).Add_w (_afb ).Add_S ().Add_Q ();return _gbf .Bytes (),_ag .ToPdfRectangle (),nil ;};
// Copy returns a clone of the path.
func (_eeb Path )Copy ()Path {_dddb :=Path {};_dddb .Points =append (_dddb .Points ,_eeb .Points ...);return _dddb ;};
// Offset shifts the path with the specified offsets.
func (_gc Path )Offset (offX ,offY float64 )Path {for _fe ,_gb :=range _gc .Points {_gc .Points [_fe ]=_gb .Add (offX ,offY );};return _gc ;};
2020-08-27 21:45:09 +00:00
2021-01-07 14:20:10 +00:00
// NewPoint returns a new point with the coordinates x, y.
func NewPoint (x ,y float64 )Point {return Point {X :x ,Y :y }};
2020-08-27 21:45:09 +00:00
2021-02-11 10:35:13 +00:00
// Polyline defines a slice of points that are connected as straight lines.
type Polyline struct{Points []Point ;LineColor *_eb .PdfColorDeviceRGB ;LineWidth float64 ;};const (LineStyleSolid LineStyle =0;LineStyleDashed LineStyle =1;);
2020-08-27 21:45:09 +00:00
2021-02-11 10:35:13 +00:00
// 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 *_eb .PdfColorDeviceRGB ;Opacity float64 ;LineWidth float64 ;LineStyle LineStyle ;};
2020-08-27 21:45:09 +00:00
2021-01-26 01:31:56 +00:00
// 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.
2021-02-11 10:35:13 +00:00
func (_aa Rectangle )Draw (gsName string )([]byte ,*_eb .PdfRectangle ,error ){_ea :=NewPath ();_ea =_ea .AppendPoint (NewPoint (0,0));_ea =_ea .AppendPoint (NewPoint (0,_aa .Height ));_ea =_ea .AppendPoint (NewPoint (_aa .Width ,_aa .Height ));_ea =_ea .AppendPoint (NewPoint (_aa .Width ,0));_ea =_ea .AppendPoint (NewPoint (0,0));if _aa .X !=0||_aa .Y !=0{_ea =_ea .Offset (_aa .X ,_aa .Y );};_dddd :=_ab .NewContentCreator ();_dddd .Add_q ();if _aa .FillEnabled {_dddd .Add_rg (_aa .FillColor .R (),_aa .FillColor .G (),_aa .FillColor .B ());};if _aa .BorderEnabled {_dddd .Add_RG (_aa .BorderColor .R (),_aa .BorderColor .G (),_aa .BorderColor .B ());_dddd .Add_w (_aa .BorderWidth );};if len (gsName )> 1{_dddd .Add_gs (_b .PdfObjectName (gsName ));};DrawPathWithCreator (_ea ,_dddd );_dddd .Add_h ();if _aa .FillEnabled &&_aa .BorderEnabled {_dddd .Add_B ();}else if _aa .FillEnabled {_dddd .Add_f ();}else if _aa .BorderEnabled {_dddd .Add_S ();};_dddd .Add_Q ();return _dddd .Bytes (),_ea .GetBoundingBox ().ToPdfRectangle (),nil ;};
2020-08-27 21:45:09 +00:00
2021-02-11 10:35:13 +00:00
// DrawBezierPathWithCreator makes the bezier path with the content creator.
2021-01-26 01:31:56 +00:00
// Adds the PDF commands to draw the path to the creator instance.
2021-02-11 10:35:13 +00:00
func DrawBezierPathWithCreator (bpath CubicBezierPath ,creator *_ab .ContentCreator ){for _cdge ,_ddc :=range bpath .Curves {if _cdge ==0{creator .Add_m (_ddc .P0 .X ,_ddc .P0 .Y );};creator .Add_c (_ddc .P1 .X ,_ddc .P1 .Y ,_ddc .P2 .X ,_ddc .P2 .Y ,_ddc .P3 .X ,_ddc .P3 .Y );};};func (_ebg Point )String ()string {return _a .Sprintf ("(\u0025\u002e\u0031\u0066\u002c\u0025\u002e\u0031\u0066\u0029",_ebg .X ,_ebg .Y );};
2020-10-12 14:17:59 +00:00
2021-02-11 10:35:13 +00:00
// GetBounds returns the bounding box of the Bezier curve.
func (_d CubicBezierCurve )GetBounds ()_eb .PdfRectangle {_dd :=_d .P0 .X ;_df :=_d .P0 .X ;_ee :=_d .P0 .Y ;_bc :=_d .P0 .Y ;for _dg :=0.0;_dg <=1.0;_dg +=0.001{Rx :=_d .P0 .X *_f .Pow (1-_dg ,3)+_d .P1 .X *3*_dg *_f .Pow (1-_dg ,2)+_d .P2 .X *3*_f .Pow (_dg ,2)*(1-_dg )+_d .P3 .X *_f .Pow (_dg ,3);Ry :=_d .P0 .Y *_f .Pow (1-_dg ,3)+_d .P1 .Y *3*_dg *_f .Pow (1-_dg ,2)+_d .P2 .Y *3*_f .Pow (_dg ,2)*(1-_dg )+_d .P3 .Y *_f .Pow (_dg ,3);if Rx < _dd {_dd =Rx ;};if Rx > _df {_df =Rx ;};if Ry < _ee {_ee =Ry ;};if Ry > _bc {_bc =Ry ;};};_ca :=_eb .PdfRectangle {};_ca .Llx =_dd ;_ca .Lly =_ee ;_ca .Urx =_df ;_ca .Ury =_bc ;return _ca ;};
2020-10-12 14:17:59 +00:00
2021-02-11 10:35:13 +00:00
// Magnitude returns the magnitude of the vector.
func (_ga Vector )Magnitude ()float64 {return _f .Sqrt (_f .Pow (_ga .Dx ,2.0)+_f .Pow (_ga .Dy ,2.0))};
2020-08-31 21:12:07 +00:00
2021-02-11 10:35:13 +00:00
// 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 (_gfe Polygon )Draw (gsName string )([]byte ,*_eb .PdfRectangle ,error ){_cbb :=_ab .NewContentCreator ();_cbb .Add_q ();_gfe .FillEnabled =_gfe .FillEnabled &&_gfe .FillColor !=nil ;if _gfe .FillEnabled {_cbb .Add_rg (_gfe .FillColor .R (),_gfe .FillColor .G (),_gfe .FillColor .B ());};_gfe .BorderEnabled =_gfe .BorderEnabled &&_gfe .BorderColor !=nil ;if _gfe .BorderEnabled {_cbb .Add_RG (_gfe .BorderColor .R (),_gfe .BorderColor .G (),_gfe .BorderColor .B ());_cbb .Add_w (_gfe .BorderWidth );};if len (gsName )> 1{_cbb .Add_gs (_b .PdfObjectName (gsName ));};_gca :=NewPath ();for _ ,_ce :=range _gfe .Points {for _bee ,_bgg :=range _ce {_gca =_gca .AppendPoint (_bgg );if _bee ==0{_cbb .Add_m (_bgg .X ,_bgg .Y );}else {_cbb .Add_l (_bgg .X ,_bgg .Y );};};_cbb .Add_h ();};if _gfe .FillEnabled &&_gfe .BorderEnabled {_cbb .Add_B ();}else if _gfe .FillEnabled {_cbb .Add_f ();}else if _gfe .BorderEnabled {_cbb .Add_S ();};_cbb .Add_Q ();return _cbb .Bytes (),_gca .GetBoundingBox ().ToPdfRectangle (),nil ;};
2020-12-06 13:03:03 +00:00
2021-02-11 10:35:13 +00:00
// 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 {_aea :=Vector {};_aea .Dx =b .X -a .X ;_aea .Dy =b .Y -a .Y ;return _aea ;};
2020-10-05 19:28:24 +00:00
2021-02-11 10:35:13 +00:00
// RemovePoint removes the point at the index specified by number from the
// path. The index is 1-based.
func (_eef Path )RemovePoint (number int )Path {if number < 1||number > len (_eef .Points ){return _eef ;};_cf :=number -1;_eef .Points =append (_eef .Points [:_cf ],_eef .Points [_cf +1:]...);return _eef ;};
2020-10-05 19:28:24 +00:00
2021-02-11 10:35:13 +00:00
// FlipX flips the sign of the Dx component of the vector.
func (_dce Vector )FlipX ()Vector {_dce .Dx =-_dce .Dx ;return _dce };
2020-12-06 13:03:03 +00:00
2021-02-11 10:35:13 +00:00
// ToPdfRectangle returns the rectangle as a PDF rectangle.
func (_bcf Rectangle )ToPdfRectangle ()*_eb .PdfRectangle {return &_eb .PdfRectangle {Llx :_bcf .X ,Lly :_bcf .Y ,Urx :_bcf .X +_bcf .Width ,Ury :_bcf .Y +_bcf .Height };};
2020-10-05 19:28:24 +00:00
2021-02-11 10:35:13 +00:00
// LineEndingStyle defines the line ending style for lines.
// The currently supported line ending styles are None, Arrow (ClosedArrow) and Butt.
type LineEndingStyle int ;
// Point represents a two-dimensional point.
type Point struct{X float64 ;Y float64 ;};
2020-10-05 19:28:24 +00:00
2021-01-26 01:31:56 +00:00
// 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.
2021-02-11 10:35:13 +00:00
func (_bce PolyBezierCurve )Draw (gsName string )([]byte ,*_eb .PdfRectangle ,error ){if _bce .BorderColor ==nil {_bce .BorderColor =_eb .NewPdfColorDeviceRGB (0,0,0);};_ae :=NewCubicBezierPath ();for _ ,_cag :=range _bce .Curves {_ae =_ae .AppendCurve (_cag );};_bf :=_ab .NewContentCreator ();_bf .Add_q ();_bce .FillEnabled =_bce .FillEnabled &&_bce .FillColor !=nil ;if _bce .FillEnabled {_bf .Add_rg (_bce .FillColor .R (),_bce .FillColor .G (),_bce .FillColor .B ());};_bf .Add_RG (_bce .BorderColor .R (),_bce .BorderColor .G (),_bce .BorderColor .B ());_bf .Add_w (_bce .BorderWidth );if len (gsName )> 1{_bf .Add_gs (_b .PdfObjectName (gsName ));};for _ ,_cbea :=range _ae .Curves {_bf .Add_m (_cbea .P0 .X ,_cbea .P0 .Y );_bf .Add_c (_cbea .P1 .X ,_cbea .P1 .Y ,_cbea .P2 .X ,_cbea .P2 .Y ,_cbea .P3 .X ,_cbea .P3 .Y );};if _bce .FillEnabled {_bf .Add_h ();_bf .Add_B ();}else {_bf .Add_S ();};_bf .Add_Q ();return _bf .Bytes (),_ae .GetBoundingBox ().ToPdfRectangle (),nil ;};
2020-10-05 19:28:24 +00:00
2021-02-11 10:35:13 +00:00
// Scale scales the vector by the specified factor.
func (_edd Vector )Scale (factor float64 )Vector {_eae :=_edd .Magnitude ();_acb :=_edd .GetPolarAngle ();_edd .Dx =factor *_eae *_f .Cos (_acb );_edd .Dy =factor *_eae *_f .Sin (_acb );return _edd ;};const (LineEndingStyleNone LineEndingStyle =0;LineEndingStyleArrow LineEndingStyle =1;LineEndingStyleButt LineEndingStyle =2;);
2020-10-12 14:17:59 +00:00
2021-02-11 10:35:13 +00:00
// FlipY flips the sign of the Dy component of the vector.
func (_bfa Vector )FlipY ()Vector {_bfa .Dy =-_bfa .Dy ;return _bfa };
2021-01-26 01:31:56 +00:00
2021-02-11 10:35:13 +00:00
// AddVector adds vector to a point.
func (_fgb Point )AddVector (v Vector )Point {_fgb .X +=v .Dx ;_fgb .Y +=v .Dy ;return _fgb };
2020-10-12 14:17:59 +00:00
2021-02-11 10:35:13 +00:00
// 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 (_ggfa Line )Draw (gsName string )([]byte ,*_eb .PdfRectangle ,error ){_bde ,_dfa :=_ggfa .X1 ,_ggfa .X2 ;_cdg ,_ef :=_ggfa .Y1 ,_ggfa .Y2 ;_egf :=_ef -_cdg ;_ceb :=_dfa -_bde ;_fea :=_f .Atan2 (_egf ,_ceb );L :=_f .Sqrt (_f .Pow (_ceb ,2.0)+_f .Pow (_egf ,2.0));_dec :=_ggfa .LineWidth ;_fgba :=_f .Pi ;_db :=1.0;if _ceb < 0{_db *=-1.0;};if _egf < 0{_db *=-1.0;};VsX :=_db *(-_dec /2*_f .Cos (_fea +_fgba /2));VsY :=_db *(-_dec /2*_f .Sin (_fea +_fgba /2)+_dec *_f .Sin (_fea +_fgba /2));V1X :=VsX +_dec /2*_f .Cos (_fea +_fgba /2);V1Y :=VsY +_dec /2*_f .Sin (_fea +_fgba /2);V2X :=VsX +_dec /2*_f .Cos (_fea +_fgba /2)+L *_f .Cos (_fea );V2Y :=VsY +_dec /2*_f .Sin (_fea +_fgba /2)+L *_f .Sin (_fea );V3X :=VsX +_dec /2*_f .Cos (_fea +_fgba /2)+L *_f .Cos (_fea )+_dec *_f .Cos (_fea -_fgba /2);V3Y :=VsY +_dec /2*_f .Sin (_fea +_fgba /2)+L *_f .Sin (_fea )+_dec *_f .Sin (_fea -_fgba /2);V4X :=VsX +_dec /2*_f .Cos (_fea -_fgba /2);V4Y :=VsY +_dec /2*_f .Sin (_fea -_fgba /2);_bcg :=NewPath ();_bcg =_bcg .AppendPoint (NewPoint (V1X ,V1Y ));_bcg =_bcg .AppendPoint (NewPoint (V2X ,V2Y ));_bcg =_bcg .AppendPoint (NewPoint (V3X ,V3Y ));_bcg =_bcg .AppendPoint (NewPoint (V4X ,V4Y ));_gdf :=_ggfa .LineEndingStyle1 ;_cg :=_ggfa .LineEndingStyle2 ;_ba :=3*_dec ;_bbe :=3*_dec ;_gfd :=(_bbe -_dec )/2;if _cg ==LineEndingStyleArrow {_bab :=_bcg .GetPointNumber (2);_fdg :=NewVectorPolar (_ba ,_fea +_fgba );_ad :=_bab .AddVector (_fdg );_egg :=NewVectorPolar (_bbe /2,_fea +_fgba /2);_dbc :=NewVectorPolar (_ba ,_fea );_bfd :=NewVectorPolar (_gfd ,_fea +_fgba /2);_ec :=_ad .AddVector (_bfd );_decg :=_dbc .Add (_egg .Flip ());_afa :=_ec .AddVector (_decg );_fdc :=_egg .Scale (2).Flip ().Add (_decg .Flip ());_cbc :=_afa .AddVector (_fdc );_fgcc :=_ad .AddVector (NewVectorPolar (_dec ,_fea -_fgba /2));_dcf :=NewPath ();_dcf =_dcf .AppendPoint (_bcg .GetPointNumber (1));_dcf =_dcf .AppendPoint (_ad );_dcf =_dcf .AppendPoint (_ec );_dcf =_dcf .AppendPoint (_afa );_dcf =_dcf .AppendPoint (_cbc );_dcf =_dcf .AppendPoint (_fgcc );_dcf =_dcf .AppendPoint (_bcg .GetPointNumber (4));_bcg =_dcf ;};if _gdf ==LineEndingStyleArrow {_bcb :=_bcg .GetPointNumber (1);_aee :=_bcg .GetPointNumber (_bcg .Length ());_abd :=NewVectorPolar (_dec /2,_fea +_fgba +_fgba /2);_ace :=_bcb .AddVector (_abd );_deg :=NewVectorPolar (_ba ,_fea ).Add (NewVectorPolar (_bbe /2,_fea +_fgba /2));_gce :=_ace .AddVector (_deg );_dege :=NewVectorPolar (_gfd ,_fea -_fgba /2);_cc :=_gce .AddVector (_dege );_bfc :=NewVectorPolar (_ba ,_fea );_cbd :=_aee .AddVector (_bfc );_bgf :=NewVectorPolar (_gfd ,_fea +_fgba +_fgba /2);_cab :=_cbd .AddVector (_bgf );_eed :=_ace ;_edg :=NewPath ();_edg =_edg .AppendPoint (_ace );_edg =_edg .AppendPoint (_gce );_edg =_edg .AppendPoint (_cc );for _ ,_dee :=range _bcg .Points [1:len (_bcg .Points )-1]{_edg =_edg .AppendPoint (_dee );};_edg =_edg .AppendPoint (_cbd );_edg =_edg .AppendPoint (_cab );_edg =_edg .AppendPoint (_eed );_bcg =_edg ;};_cff :=_ab .NewContentCreator ();_cff .Add_q ().Add_rg (_ggfa .LineColor .R (),_ggfa .LineColor .G (),_ggfa .LineColor .B ());if len (gsName )> 1{_cff .Add_gs (_b .PdfObjectName (gsName ));};_bcg =_bcg .Offset (_ggfa .X1 ,_ggfa .Y1 );_fcdg :=_bcg .GetBoundingBox ();DrawPathWithCreator (_bcg ,_cff );if _ggfa .LineStyle ==LineStyleDashed {_cff .Add_d ([]int64 {1,1},0).Add_S ().Add_f ().Add_Q ();}else {_cff .Add_f ().Add_Q ();};return _cff .Bytes (),_fcdg .ToPdfRectangle (),nil ;};
2020-10-12 14:17:59 +00:00
2021-02-11 10:35:13 +00:00
// Add adds the specified vector to the current one and returns the result.
func (_aeac Vector )Add (other Vector )Vector {_aeac .Dx +=other .Dx ;_aeac .Dy +=other .Dy ;return _aeac ;};
2020-09-21 01:20:10 +00:00
2021-02-11 10:35:13 +00:00
// Vector represents a two-dimensional vector.
type Vector struct{Dx float64 ;Dy float64 ;};
2020-08-27 21:45:09 +00:00
2021-02-11 10:35:13 +00:00
// AddOffsetXY adds X,Y offset to all points on a curve.
func (_eg CubicBezierCurve )AddOffsetXY (offX ,offY float64 )CubicBezierCurve {_eg .P0 .X +=offX ;_eg .P1 .X +=offX ;_eg .P2 .X +=offX ;_eg .P3 .X +=offX ;_eg .P0 .Y +=offY ;_eg .P1 .Y +=offY ;_eg .P2 .Y +=offY ;_eg .P3 .Y +=offY ;return _eg ;};
2020-11-23 22:15:56 +00:00
2021-02-11 10:35:13 +00:00
// LineStyle refers to how the line will be created.
type LineStyle int ;
2020-11-23 22:15:56 +00:00
2021-02-11 10:35:13 +00:00
// GetPointNumber returns the path point at the index specified by number.
// The index is 1-based.
func (_dgd Path )GetPointNumber (number int )Point {if number < 1||number > len (_dgd .Points ){return Point {};};return _dgd .Points [number -1];};
2020-11-23 22:15:56 +00:00
2021-02-11 10:35:13 +00:00
// 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 *_eb .PdfColorDeviceRGB ;Opacity float64 ;LineWidth float64 ;LineEndingStyle1 LineEndingStyle ;LineEndingStyle2 LineEndingStyle ;LineStyle LineStyle ;};
2020-09-21 01:20:10 +00:00
2021-02-11 10:35:13 +00:00
// Offset shifts the Bezier path with the specified offsets.
func (_fd CubicBezierPath )Offset (offX ,offY float64 )CubicBezierPath {for _fb ,_bb :=range _fd .Curves {_fd .Curves [_fb ]=_bb .AddOffsetXY (offX ,offY );};return _fd ;};
2020-08-27 21:45:09 +00:00
2021-01-26 01:31:56 +00:00
// PolyBezierCurve represents a composite curve that is the result of
// joining multiple cubic Bezier curves.
2021-02-11 10:35:13 +00:00
type PolyBezierCurve struct{Curves []CubicBezierCurve ;BorderWidth float64 ;BorderColor *_eb .PdfColorDeviceRGB ;FillEnabled bool ;FillColor *_eb .PdfColorDeviceRGB ;};
2020-10-12 14:17:59 +00:00
2021-01-26 01:31:56 +00:00
// 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 ;};
2020-08-31 21:12:07 +00:00
2021-02-11 10:35:13 +00:00
// ToPdfRectangle returns the bounding box as a PDF rectangle.
func (_ebab BoundingBox )ToPdfRectangle ()*_eb .PdfRectangle {return &_eb .PdfRectangle {Llx :_ebab .X ,Lly :_ebab .Y ,Urx :_ebab .X +_ebab .Width ,Ury :_ebab .Y +_ebab .Height };};
2021-01-26 01:31:56 +00:00
2021-02-11 10:35:13 +00:00
// 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 *_ab .ContentCreator ){for _caa ,_deb :=range path .Points {if _caa ==0{creator .Add_m (_deb .X ,_deb .Y );}else {creator .Add_l (_deb .X ,_deb .Y );};};};
2021-01-07 14:20:10 +00:00
2021-02-11 10:35:13 +00:00
// Rotate rotates the vector by the specified angle.
func (_dcd Vector )Rotate (phi float64 )Vector {_cca :=_dcd .Magnitude ();_bec :=_dcd .GetPolarAngle ();return NewVectorPolar (_cca ,_bec +phi );};
2020-11-23 22:15:56 +00:00
2021-02-11 10:35:13 +00:00
// Polygon is a multi-point shape that can be drawn to a PDF content stream.
type Polygon struct{Points [][]Point ;FillEnabled bool ;FillColor *_eb .PdfColorDeviceRGB ;BorderEnabled bool ;BorderColor *_eb .PdfColorDeviceRGB ;BorderWidth float64 ;};
2020-11-23 22:15:56 +00:00
2021-02-11 10:35:13 +00:00
// Copy returns a clone of the Bezier path.
func (_ddd CubicBezierPath )Copy ()CubicBezierPath {_dc :=CubicBezierPath {};_dc .Curves =append (_dc .Curves ,_ddd .Curves ...);return _dc ;};
2020-12-06 13:03:03 +00:00
2021-02-11 10:35:13 +00:00
// 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 (_gfc Circle )Draw (gsName string )([]byte ,*_eb .PdfRectangle ,error ){_abg :=_gfc .Width /2;_cbe :=_gfc .Height /2;if _gfc .BorderEnabled {_abg -=_gfc .BorderWidth /2;_cbe -=_gfc .BorderWidth /2;};_fcd :=0.551784;_fde :=_abg *_fcd ;_gfb :=_cbe *_fcd ;_ff :=NewCubicBezierPath ();_ff =_ff .AppendCurve (NewCubicBezierCurve (-_abg ,0,-_abg ,_gfb ,-_fde ,_cbe ,0,_cbe ));_ff =_ff .AppendCurve (NewCubicBezierCurve (0,_cbe ,_fde ,_cbe ,_abg ,_gfb ,_abg ,0));_ff =_ff .AppendCurve (NewCubicBezierCurve (_abg ,0,_abg ,-_gfb ,_fde ,-_cbe ,0,-_cbe ));_ff =_ff .AppendCurve (NewCubicBezierCurve (0,-_cbe ,-_fde ,-_cbe ,-_abg ,-_gfb ,-_abg ,0));_ff =_ff .Offset (_abg ,_cbe );if _gfc .BorderEnabled {_ff =_ff .Offset (_gfc .BorderWidth /2,_gfc .BorderWidth /2);};if _gfc .X !=0||_gfc .Y !=0{_ff =_ff .Offset (_gfc .X ,_gfc .Y );};_abc :=_ab .NewContentCreator ();_abc .Add_q ();if _gfc .FillEnabled {_abc .Add_rg (_gfc .FillColor .R (),_gfc .FillColor .G (),_gfc .FillColor .B ());};if _gfc .BorderEnabled {_abc .Add_RG (_gfc .BorderColor .R (),_gfc .BorderColor .G (),_gfc .BorderColor .B ());_abc .Add_w (_gfc .BorderWidth );};if len (gsName )> 1{_abc .Add_gs (_b .PdfObjectName (gsName ));};DrawBezierPathWithCreator (_ff ,_abc );_abc .Add_h ();if _gfc .FillEnabled &&_gfc .BorderEnabled {_abc .Add_B ();}else if _gfc .FillEnabled {_abc .Add_f ();}else if _gfc .BorderEnabled {_abc .Add_S ();};_abc .Add_Q ();_feg :=_ff .GetBoundingBox ();if _gfc .BorderEnabled {_feg .Height +=_gfc .BorderWidth ;_feg .Width +=_gfc .BorderWidth ;_feg .X -=_gfc .BorderWidth /2;_feg .Y -=_gfc .BorderWidth /2;};return _abc .Bytes (),_feg .ToPdfRectangle (),nil ;};
2020-12-06 13:03:03 +00:00
2021-02-11 10:35:13 +00:00
// GetBoundingBox returns the bounding box of the Bezier path.
func (_fg CubicBezierPath )GetBoundingBox ()Rectangle {_g :=Rectangle {};_afc :=0.0;_fba :=0.0;_fbg :=0.0;_dde :=0.0;for _be ,_cd :=range _fg .Curves {_dfc :=_cd .GetBounds ();if _be ==0{_afc =_dfc .Llx ;_fba =_dfc .Urx ;_fbg =_dfc .Lly ;_dde =_dfc .Ury ;continue ;};if _dfc .Llx < _afc {_afc =_dfc .Llx ;};if _dfc .Urx > _fba {_fba =_dfc .Urx ;};if _dfc .Lly < _fbg {_fbg =_dfc .Lly ;};if _dfc .Ury > _dde {_dde =_dfc .Ury ;};};_g .X =_afc ;_g .Y =_fbg ;_g .Width =_fba -_afc ;_g .Height =_dde -_fbg ;return _g ;};
2020-12-06 13:03:03 +00:00
2021-02-11 10:35:13 +00:00
// NewVector returns a new vector with the direction specified by dx and dy.
func NewVector (dx ,dy float64 )Vector {_bfb :=Vector {};_bfb .Dx =dx ;_bfb .Dy =dy ;return _bfb };
2021-01-07 14:20:10 +00:00
2021-02-11 10:35:13 +00:00
// Flip changes the sign of the vector: -vector.
func (_ebgg Vector )Flip ()Vector {_cef :=_ebgg .Magnitude ();_fbf :=_ebgg .GetPolarAngle ();_ebgg .Dx =_cef *_f .Cos (_fbf +_f .Pi );_ebgg .Dy =_cef *_f .Sin (_fbf +_f .Pi );return _ebgg ;};
2021-01-07 14:20:10 +00:00
2021-02-11 10:35:13 +00:00
// Rotate returns a new Point at `p` rotated by `theta` degrees.
func (_bg Point )Rotate (theta float64 )Point {_fa :=_af .NewPoint (_bg .X ,_bg .Y ).Rotate (theta );return NewPoint (_fa .X ,_fa .Y );};
2021-01-07 14:20:10 +00:00
2021-02-11 10:35:13 +00:00
// NewVectorPolar returns a new vector calculated from the specified
// magnitude and angle.
func NewVectorPolar (length float64 ,theta float64 )Vector {_aeb :=Vector {};_aeb .Dx =length *_f .Cos (theta );_aeb .Dy =length *_f .Sin (theta );return _aeb ;};
2021-01-07 14:20:10 +00:00
2021-02-11 10:35:13 +00:00
// NewPath returns a new empty path.
func NewPath ()Path {return Path {}};