mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-27 13:48:51 +08:00
217 lines
24 KiB
Go
217 lines
24 KiB
Go
//
|
|
// 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 )}; |