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 (_g "fmt";_c "github.com/unidoc/unipdf/v3/contentstream";_f "github.com/unidoc/unipdf/v3/core";_e "github.com/unidoc/unipdf/v3/internal/transform";_bg "github.com/unidoc/unipdf/v3/model";_b "math";);
|
|
|
|
// ToPdfRectangle returns the bounding box as a PDF rectangle.
|
|
func (_ggd BoundingBox )ToPdfRectangle ()*_bg .PdfRectangle {return &_bg .PdfRectangle {Llx :_ggd .X ,Lly :_ggd .Y ,Urx :_ggd .X +_ggd .Width ,Ury :_ggd .Y +_ggd .Height };};
|
|
|
|
// RemovePoint removes the point at the index specified by number from the
|
|
// path. The index is 1-based.
|
|
func (_gd Path )RemovePoint (number int )Path {if number < 1||number > len (_gd .Points ){return _gd ;};_cbe :=number -1;_gd .Points =append (_gd .Points [:_cbe ],_gd .Points [_cbe +1:]...);return _gd ;};
|
|
|
|
// 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 (_aef BasicLine )Draw (gsName string )([]byte ,*_bg .PdfRectangle ,error ){_cfbe :=_aef .LineWidth ;_abbg :=NewPath ();_abbg =_abbg .AppendPoint (NewPoint (_aef .X1 ,_aef .Y1 ));_abbg =_abbg .AppendPoint (NewPoint (_aef .X2 ,_aef .Y2 ));_acd :=_c .NewContentCreator ();_dcg :=_abbg .GetBoundingBox ();DrawPathWithCreator (_abbg ,_acd );if _aef .LineStyle ==LineStyleDashed {_acd .Add_d ([]int64 {1,1},0);};_acd .Add_RG (_aef .LineColor .R (),_aef .LineColor .G (),_aef .LineColor .B ()).Add_w (_cfbe ).Add_S ().Add_Q ();return _acd .Bytes (),_dcg .ToPdfRectangle (),nil ;};
|
|
|
|
// Path consists of straight line connections between each point defined in an array of points.
|
|
type Path struct{Points []Point ;};
|
|
|
|
// NewPoint returns a new point with the coordinates x, y.
|
|
func NewPoint (x ,y float64 )Point {return Point {X :x ,Y :y }};
|
|
|
|
// ToPdfRectangle returns the rectangle as a PDF rectangle.
|
|
func (_cda Rectangle )ToPdfRectangle ()*_bg .PdfRectangle {return &_bg .PdfRectangle {Llx :_cda .X ,Lly :_cda .Y ,Urx :_cda .X +_cda .Width ,Ury :_cda .Y +_cda .Height };};const (LineStyleSolid LineStyle =0;LineStyleDashed LineStyle =1;);
|
|
|
|
// 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 ;};
|
|
|
|
// Add shifts the coordinates of the point with dx, dy and returns the result.
|
|
func (_gda Point )Add (dx ,dy float64 )Point {_gda .X +=dx ;_gda .Y +=dy ;return _gda };
|
|
|
|
// 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 (_gdaf PolyBezierCurve )Draw (gsName string )([]byte ,*_bg .PdfRectangle ,error ){if _gdaf .BorderColor ==nil {_gdaf .BorderColor =_bg .NewPdfColorDeviceRGB (0,0,0);};_fbd :=NewCubicBezierPath ();for _ ,_ag :=range _gdaf .Curves {_fbd =_fbd .AppendCurve (_ag );};_ga :=_c .NewContentCreator ();_ga .Add_q ();_gdaf .FillEnabled =_gdaf .FillEnabled &&_gdaf .FillColor !=nil ;if _gdaf .FillEnabled {_ga .Add_rg (_gdaf .FillColor .R (),_gdaf .FillColor .G (),_gdaf .FillColor .B ());};_ga .Add_RG (_gdaf .BorderColor .R (),_gdaf .BorderColor .G (),_gdaf .BorderColor .B ());_ga .Add_w (_gdaf .BorderWidth );if len (gsName )> 1{_ga .Add_gs (_f .PdfObjectName (gsName ));};for _ ,_cdd :=range _fbd .Curves {_ga .Add_m (_cdd .P0 .X ,_cdd .P0 .Y );_ga .Add_c (_cdd .P1 .X ,_cdd .P1 .Y ,_cdd .P2 .X ,_cdd .P2 .Y ,_cdd .P3 .X ,_cdd .P3 .Y );};if _gdaf .FillEnabled {_ga .Add_h ();_ga .Add_B ();}else {_ga .Add_S ();};_ga .Add_Q ();return _ga .Bytes (),_fbd .GetBoundingBox ().ToPdfRectangle (),nil ;};
|
|
|
|
// NewVector returns a new vector with the direction specified by dx and dy.
|
|
func NewVector (dx ,dy float64 )Vector {_cgg :=Vector {};_cgg .Dx =dx ;_cgg .Dy =dy ;return _cgg };
|
|
|
|
// Copy returns a clone of the path.
|
|
func (_be Path )Copy ()Path {_de :=Path {};_de .Points =[]Point {};for _ ,_dge :=range _be .Points {_de .Points =append (_de .Points ,_dge );};return _de ;};
|
|
|
|
// Rotate returns a new Point at `p` rotated by `theta` degrees.
|
|
func (_eed Point )Rotate (theta float64 )Point {_aeb :=_e .NewPoint (_eed .X ,_eed .Y ).Rotate (theta );return NewPoint (_aeb .X ,_aeb .Y );};
|
|
|
|
// NewPath returns a new empty path.
|
|
func NewPath ()Path {return Path {}};
|
|
|
|
// Copy returns a clone of the Bezier path.
|
|
func (_ee CubicBezierPath )Copy ()CubicBezierPath {_dg :=CubicBezierPath {};_dg .Curves =[]CubicBezierCurve {};for _ ,_abb :=range _ee .Curves {_dg .Curves =append (_dg .Curves ,_abb );};return _dg ;};
|
|
|
|
// NewCubicBezierCurve returns a new cubic Bezier curve.
|
|
func NewCubicBezierCurve (x0 ,y0 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 float64 )CubicBezierCurve {_fa :=CubicBezierCurve {};_fa .P0 =NewPoint (x0 ,y0 );_fa .P1 =NewPoint (x1 ,y1 );_fa .P2 =NewPoint (x2 ,y2 );_fa .P3 =NewPoint (x3 ,y3 );return _fa ;};
|
|
|
|
// PolyBezierCurve represents a composite curve that is the result of
|
|
// joining multiple cubic Bezier curves.
|
|
type PolyBezierCurve struct{Curves []CubicBezierCurve ;BorderWidth float64 ;BorderColor *_bg .PdfColorDeviceRGB ;FillEnabled bool ;FillColor *_bg .PdfColorDeviceRGB ;};
|
|
|
|
// 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 *_bg .PdfColorDeviceRGB ;BorderEnabled bool ;BorderWidth float64 ;BorderColor *_bg .PdfColorDeviceRGB ;Opacity 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 {_gdeg :=Vector {};_gdeg .Dx =b .X -a .X ;_gdeg .Dy =b .Y -a .Y ;return _gdeg ;};
|
|
|
|
// AppendPoint adds the specified point to the path.
|
|
func (_cd Path )AppendPoint (point Point )Path {_cd .Points =append (_cd .Points ,point );return _cd };
|
|
|
|
// FlipX flips the sign of the Dx component of the vector.
|
|
func (_cdae Vector )FlipX ()Vector {_cdae .Dx =-_cdae .Dx ;return _cdae };
|
|
|
|
// Scale scales the vector by the specified factor.
|
|
func (_fe Vector )Scale (factor float64 )Vector {_ggde :=_fe .Magnitude ();_eda :=_fe .GetPolarAngle ();_fe .Dx =factor *_ggde *_b .Cos (_eda );_fe .Dy =factor *_ggde *_b .Sin (_eda );return _fe ;};
|
|
|
|
// AddVector adds vector to a point.
|
|
func (_eeg Point )AddVector (v Vector )Point {_eeg .X +=v .Dx ;_eeg .Y +=v .Dy ;return _eeg };
|
|
|
|
// 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 (_gbc Polygon )Draw (gsName string )([]byte ,*_bg .PdfRectangle ,error ){_beb :=_c .NewContentCreator ();_beb .Add_q ();_gbc .FillEnabled =_gbc .FillEnabled &&_gbc .FillColor !=nil ;if _gbc .FillEnabled {_beb .Add_rg (_gbc .FillColor .R (),_gbc .FillColor .G (),_gbc .FillColor .B ());};_gbc .BorderEnabled =_gbc .BorderEnabled &&_gbc .BorderColor !=nil ;if _gbc .BorderEnabled {_beb .Add_RG (_gbc .BorderColor .R (),_gbc .BorderColor .G (),_gbc .BorderColor .B ());_beb .Add_w (_gbc .BorderWidth );};if len (gsName )> 1{_beb .Add_gs (_f .PdfObjectName (gsName ));};_fgd :=NewPath ();for _ ,_bcb :=range _gbc .Points {for _gag ,_edb :=range _bcb {_fgd =_fgd .AppendPoint (_edb );if _gag ==0{_beb .Add_m (_edb .X ,_edb .Y );}else {_beb .Add_l (_edb .X ,_edb .Y );};};_beb .Add_h ();};if _gbc .FillEnabled &&_gbc .BorderEnabled {_beb .Add_B ();}else if _gbc .FillEnabled {_beb .Add_f ();}else if _gbc .BorderEnabled {_beb .Add_S ();};_beb .Add_Q ();return _beb .Bytes (),_fgd .GetBoundingBox ().ToPdfRectangle (),nil ;};
|
|
|
|
// 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 (_gdac Line )Draw (gsName string )([]byte ,*_bg .PdfRectangle ,error ){_aga ,_dfa :=_gdac .X1 ,_gdac .X2 ;_gaa ,_cf :=_gdac .Y1 ,_gdac .Y2 ;_gff :=_cf -_gaa ;_bga :=_dfa -_aga ;_dba :=_b .Atan2 (_gff ,_bga );L :=_b .Sqrt (_b .Pow (_bga ,2.0)+_b .Pow (_gff ,2.0));_edg :=_gdac .LineWidth ;_aa :=_b .Pi ;_ef :=1.0;if _bga < 0{_ef *=-1.0;};if _gff < 0{_ef *=-1.0;};VsX :=_ef *(-_edg /2*_b .Cos (_dba +_aa /2));VsY :=_ef *(-_edg /2*_b .Sin (_dba +_aa /2)+_edg *_b .Sin (_dba +_aa /2));V1X :=VsX +_edg /2*_b .Cos (_dba +_aa /2);V1Y :=VsY +_edg /2*_b .Sin (_dba +_aa /2);V2X :=VsX +_edg /2*_b .Cos (_dba +_aa /2)+L *_b .Cos (_dba );V2Y :=VsY +_edg /2*_b .Sin (_dba +_aa /2)+L *_b .Sin (_dba );V3X :=VsX +_edg /2*_b .Cos (_dba +_aa /2)+L *_b .Cos (_dba )+_edg *_b .Cos (_dba -_aa /2);V3Y :=VsY +_edg /2*_b .Sin (_dba +_aa /2)+L *_b .Sin (_dba )+_edg *_b .Sin (_dba -_aa /2);V4X :=VsX +_edg /2*_b .Cos (_dba -_aa /2);V4Y :=VsY +_edg /2*_b .Sin (_dba -_aa /2);_fba :=NewPath ();_fba =_fba .AppendPoint (NewPoint (V1X ,V1Y ));_fba =_fba .AppendPoint (NewPoint (V2X ,V2Y ));_fba =_fba .AppendPoint (NewPoint (V3X ,V3Y ));_fba =_fba .AppendPoint (NewPoint (V4X ,V4Y ));_ba :=_gdac .LineEndingStyle1 ;_cfb :=_gdac .LineEndingStyle2 ;_bea :=3*_edg ;_gc :=3*_edg ;_gba :=(_gc -_edg )/2;if _cfb ==LineEndingStyleArrow {_gea :=_fba .GetPointNumber (2);_bf :=NewVectorPolar (_bea ,_dba +_aa );_ffa :=_gea .AddVector (_bf );_cg :=NewVectorPolar (_gc /2,_dba +_aa /2);_fge :=NewVectorPolar (_bea ,_dba );_dbd :=NewVectorPolar (_gba ,_dba +_aa /2);_fac :=_ffa .AddVector (_dbd );_bgdd :=_fge .Add (_cg .Flip ());_afg :=_fac .AddVector (_bgdd );_gffa :=_cg .Scale (2).Flip ().Add (_bgdd .Flip ());_bfg :=_afg .AddVector (_gffa );_geb :=_ffa .AddVector (NewVectorPolar (_edg ,_dba -_aa /2));_gde :=NewPath ();_gde =_gde .AppendPoint (_fba .GetPointNumber (1));_gde =_gde .AppendPoint (_ffa );_gde =_gde .AppendPoint (_fac );_gde =_gde .AppendPoint (_afg );_gde =_gde .AppendPoint (_bfg );_gde =_gde .AppendPoint (_geb );_gde =_gde .AppendPoint (_fba .GetPointNumber (4));_fba =_gde ;};if _ba ==LineEndingStyleArrow {_cga :=_fba .GetPointNumber (1);_cba :=_fba .GetPointNumber (_fba .Length ());_bca :=NewVectorPolar (_edg /2,_dba +_aa +_aa /2);_abg :=_cga .AddVector (_bca );_beae :=NewVectorPolar (_bea ,_dba ).Add (NewVectorPolar (_gc /2,_dba +_aa /2));_bed :=_abg .AddVector (_beae );_caf :=NewVectorPolar (_gba ,_dba -_aa /2);_gaaa :=_bed .AddVector (_caf );_bgb :=NewVectorPolar (_bea ,_dba );_fd :=_cba .AddVector (_bgb );_ccb :=NewVectorPolar (_gba ,_dba +_aa +_aa /2);_dda :=_fd .AddVector (_ccb );_egde :=_abg ;_gaf :=NewPath ();_gaf =_gaf .AppendPoint (_abg );_gaf =_gaf .AppendPoint (_bed );_gaf =_gaf .AppendPoint (_gaaa );for _ ,_ffad :=range _fba .Points [1:len (_fba .Points )-1]{_gaf =_gaf .AppendPoint (_ffad );};_gaf =_gaf .AppendPoint (_fd );_gaf =_gaf .AppendPoint (_dda );_gaf =_gaf .AppendPoint (_egde );_fba =_gaf ;};_bgg :=_c .NewContentCreator ();_bgg .Add_q ().Add_rg (_gdac .LineColor .R (),_gdac .LineColor .G (),_gdac .LineColor .B ());if len (gsName )> 1{_bgg .Add_gs (_f .PdfObjectName (gsName ));};_fba =_fba .Offset (_gdac .X1 ,_gdac .Y1 );_fgc :=_fba .GetBoundingBox ();DrawPathWithCreator (_fba ,_bgg );if _gdac .LineStyle ==LineStyleDashed {_bgg .Add_d ([]int64 {1,1},0).Add_S ().Add_f ().Add_Q ();}else {_bgg .Add_f ().Add_Q ();};return _bgg .Bytes (),_fgc .ToPdfRectangle (),nil ;};
|
|
|
|
// GetBoundingBox returns the bounding box of the path.
|
|
func (_acg Path )GetBoundingBox ()BoundingBox {_gbg :=BoundingBox {};_adf :=0.0;_fg :=0.0;_egd :=0.0;_deg :=0.0;for _ff ,_eac :=range _acg .Points {if _ff ==0{_adf =_eac .X ;_fg =_eac .X ;_egd =_eac .Y ;_deg =_eac .Y ;continue ;};if _eac .X < _adf {_adf =_eac .X ;};if _eac .X > _fg {_fg =_eac .X ;};if _eac .Y < _egd {_egd =_eac .Y ;};if _eac .Y > _deg {_deg =_eac .Y ;};};_gbg .X =_adf ;_gbg .Y =_egd ;_gbg .Width =_fg -_adf ;_gbg .Height =_deg -_egd ;return _gbg ;};
|
|
|
|
// Polygon is a multi-point shape that can be drawn to a PDF content stream.
|
|
type Polygon struct{Points [][]Point ;FillEnabled bool ;FillColor *_bg .PdfColorDeviceRGB ;BorderEnabled bool ;BorderColor *_bg .PdfColorDeviceRGB ;BorderWidth float64 ;};
|
|
|
|
// NewCubicBezierPath returns a new empty cubic Bezier path.
|
|
func NewCubicBezierPath ()CubicBezierPath {_ed :=CubicBezierPath {};_ed .Curves =[]CubicBezierCurve {};return _ed ;};
|
|
|
|
// Point represents a two-dimensional point.
|
|
type Point struct{X float64 ;Y float64 ;};
|
|
|
|
// LineEndingStyle defines the line ending style for lines.
|
|
// The currently supported line ending styles are None, Arrow (ClosedArrow) and Butt.
|
|
type LineEndingStyle int ;
|
|
|
|
// 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 *_bg .PdfColorDeviceRGB ;Opacity float64 ;LineWidth float64 ;LineStyle LineStyle ;};
|
|
|
|
// 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 (_cc Circle )Draw (gsName string )([]byte ,*_bg .PdfRectangle ,error ){_da :=_cc .Width /2;_ge :=_cc .Height /2;if _cc .BorderEnabled {_da -=_cc .BorderWidth /2;_ge -=_cc .BorderWidth /2;};_fce :=0.551784;_faa :=_da *_fce ;_ggfg :=_ge *_fce ;_acgd :=NewCubicBezierPath ();_acgd =_acgd .AppendCurve (NewCubicBezierCurve (-_da ,0,-_da ,_ggfg ,-_faa ,_ge ,0,_ge ));_acgd =_acgd .AppendCurve (NewCubicBezierCurve (0,_ge ,_faa ,_ge ,_da ,_ggfg ,_da ,0));_acgd =_acgd .AppendCurve (NewCubicBezierCurve (_da ,0,_da ,-_ggfg ,_faa ,-_ge ,0,-_ge ));_acgd =_acgd .AppendCurve (NewCubicBezierCurve (0,-_ge ,-_faa ,-_ge ,-_da ,-_ggfg ,-_da ,0));_acgd =_acgd .Offset (_da ,_ge );if _cc .BorderEnabled {_acgd =_acgd .Offset (_cc .BorderWidth /2,_cc .BorderWidth /2);};if _cc .X !=0||_cc .Y !=0{_acgd =_acgd .Offset (_cc .X ,_cc .Y );};_dce :=_c .NewContentCreator ();_dce .Add_q ();if _cc .FillEnabled {_dce .Add_rg (_cc .FillColor .R (),_cc .FillColor .G (),_cc .FillColor .B ());};if _cc .BorderEnabled {_dce .Add_RG (_cc .BorderColor .R (),_cc .BorderColor .G (),_cc .BorderColor .B ());_dce .Add_w (_cc .BorderWidth );};if len (gsName )> 1{_dce .Add_gs (_f .PdfObjectName (gsName ));};DrawBezierPathWithCreator (_acgd ,_dce );_dce .Add_h ();if _cc .FillEnabled &&_cc .BorderEnabled {_dce .Add_B ();}else if _cc .FillEnabled {_dce .Add_f ();}else if _cc .BorderEnabled {_dce .Add_S ();};_dce .Add_Q ();_ffc :=_acgd .GetBoundingBox ();if _cc .BorderEnabled {_ffc .Height +=_cc .BorderWidth ;_ffc .Width +=_cc .BorderWidth ;_ffc .X -=_cc .BorderWidth /2;_ffc .Y -=_cc .BorderWidth /2;};return _dce .Bytes (),_ffc .ToPdfRectangle (),nil ;};
|
|
|
|
// FlipY flips the sign of the Dy component of the vector.
|
|
func (_fbb Vector )FlipY ()Vector {_fbb .Dy =-_fbb .Dy ;return _fbb };
|
|
|
|
// BoundingBox represents the smallest rectangular area that encapsulates an object.
|
|
type BoundingBox struct{X float64 ;Y float64 ;Width float64 ;Height 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 *_c .ContentCreator ){for _acdd ,_ec :=range path .Points {if _acdd ==0{creator .Add_m (_ec .X ,_ec .Y );}else {creator .Add_l (_ec .X ,_ec .Y );};};};
|
|
|
|
// Offset shifts the path with the specified offsets.
|
|
func (_ce Path )Offset (offX ,offY float64 )Path {for _eg ,_db :=range _ce .Points {_ce .Points [_eg ]=_db .Add (offX ,offY );};return _ce ;};
|
|
|
|
// 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 *_bg .PdfColorDeviceRGB ;Opacity float64 ;LineWidth float64 ;LineEndingStyle1 LineEndingStyle ;LineEndingStyle2 LineEndingStyle ;LineStyle LineStyle ;};
|
|
|
|
// GetPointNumber returns the path point at the index specified by number.
|
|
// The index is 1-based.
|
|
func (_ac Path )GetPointNumber (number int )Point {if number < 1||number > len (_ac .Points ){return Point {};};return _ac .Points [number -1];};
|
|
|
|
// 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 (_dbab Polyline )Draw (gsName string )([]byte ,*_bg .PdfRectangle ,error ){if _dbab .LineColor ==nil {_dbab .LineColor =_bg .NewPdfColorDeviceRGB (0,0,0);};_eagd :=NewPath ();for _ ,_fdd :=range _dbab .Points {_eagd =_eagd .AppendPoint (_fdd );};_cdc :=_c .NewContentCreator ();_cdc .Add_q ();_cdc .Add_RG (_dbab .LineColor .R (),_dbab .LineColor .G (),_dbab .LineColor .B ());_cdc .Add_w (_dbab .LineWidth );if len (gsName )> 1{_cdc .Add_gs (_f .PdfObjectName (gsName ));};DrawPathWithCreator (_eagd ,_cdc );_cdc .Add_S ();_cdc .Add_Q ();return _cdc .Bytes (),_eagd .GetBoundingBox ().ToPdfRectangle (),nil ;};
|
|
|
|
// Magnitude returns the magnitude of the vector.
|
|
func (_aebe Vector )Magnitude ()float64 {return _b .Sqrt (_b .Pow (_aebe .Dx ,2.0)+_b .Pow (_aebe .Dy ,2.0));};
|
|
|
|
// Flip changes the sign of the vector: -vector.
|
|
func (_ffae Vector )Flip ()Vector {_gdg :=_ffae .Magnitude ();_eaf :=_ffae .GetPolarAngle ();_ffae .Dx =_gdg *_b .Cos (_eaf +_b .Pi );_ffae .Dy =_gdg *_b .Sin (_eaf +_b .Pi );return _ffae ;};
|
|
|
|
// GetBounds returns the bounding box of the Bezier curve.
|
|
func (_bc CubicBezierCurve )GetBounds ()_bg .PdfRectangle {_cb :=_bc .P0 .X ;_dd :=_bc .P0 .X ;_ea :=_bc .P0 .Y ;_ca :=_bc .P0 .Y ;for _ae :=0.0;_ae <=1.0;_ae +=0.001{Rx :=_bc .P0 .X *_b .Pow (1-_ae ,3)+_bc .P1 .X *3*_ae *_b .Pow (1-_ae ,2)+_bc .P2 .X *3*_b .Pow (_ae ,2)*(1-_ae )+_bc .P3 .X *_b .Pow (_ae ,3);Ry :=_bc .P0 .Y *_b .Pow (1-_ae ,3)+_bc .P1 .Y *3*_ae *_b .Pow (1-_ae ,2)+_bc .P2 .Y *3*_b .Pow (_ae ,2)*(1-_ae )+_bc .P3 .Y *_b .Pow (_ae ,3);if Rx < _cb {_cb =Rx ;};if Rx > _dd {_dd =Rx ;};if Ry < _ea {_ea =Ry ;};if Ry > _ca {_ca =Ry ;};};_ab :=_bg .PdfRectangle {};_ab .Llx =_cb ;_ab .Lly =_ea ;_ab .Urx =_dd ;_ab .Ury =_ca ;return _ab ;};
|
|
|
|
// 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 *_c .ContentCreator ){for _efg ,_cag :=range bpath .Curves {if _efg ==0{creator .Add_m (_cag .P0 .X ,_cag .P0 .Y );};creator .Add_c (_cag .P1 .X ,_cag .P1 .Y ,_cag .P2 .X ,_cag .P2 .Y ,_cag .P3 .X ,_cag .P3 .Y );};};
|
|
|
|
// AppendCurve appends the specified Bezier curve to the path.
|
|
func (_eae CubicBezierPath )AppendCurve (curve CubicBezierCurve )CubicBezierPath {_eae .Curves =append (_eae .Curves ,curve );return _eae ;};
|
|
|
|
// LineStyle refers to how the line will be created.
|
|
type LineStyle int ;
|
|
|
|
// Rotate rotates the vector by the specified angle.
|
|
func (_dfd Vector )Rotate (phi float64 )Vector {_gdegb :=_dfd .Magnitude ();_ace :=_dfd .GetPolarAngle ();return NewVectorPolar (_gdegb ,_ace +phi );};
|
|
|
|
// AddOffsetXY adds X,Y offset to all points on a curve.
|
|
func (_d CubicBezierCurve )AddOffsetXY (offX ,offY float64 )CubicBezierCurve {_d .P0 .X +=offX ;_d .P1 .X +=offX ;_d .P2 .X +=offX ;_d .P3 .X +=offX ;_d .P0 .Y +=offY ;_d .P1 .Y +=offY ;_d .P2 .Y +=offY ;_d .P3 .Y +=offY ;return _d ;};
|
|
|
|
// Length returns the number of points in the path.
|
|
func (_ade Path )Length ()int {return len (_ade .Points )};
|
|
|
|
// CubicBezierPath represents a collection of cubic Bezier curves.
|
|
type CubicBezierPath struct{Curves []CubicBezierCurve ;};
|
|
|
|
// Offset shifts the Bezier path with the specified offsets.
|
|
func (_af CubicBezierPath )Offset (offX ,offY float64 )CubicBezierPath {for _gb ,_dc :=range _af .Curves {_af .Curves [_gb ]=_dc .AddOffsetXY (offX ,offY );};return _af ;};
|
|
|
|
// GetBoundingBox returns the bounding box of the Bezier path.
|
|
func (_fb CubicBezierPath )GetBoundingBox ()Rectangle {_fc :=Rectangle {};_eb :=0.0;_eag :=0.0;_gge :=0.0;_gf :=0.0;for _ggf ,_ad :=range _fb .Curves {_df :=_ad .GetBounds ();if _ggf ==0{_eb =_df .Llx ;_eag =_df .Urx ;_gge =_df .Lly ;_gf =_df .Ury ;continue ;};if _df .Llx < _eb {_eb =_df .Llx ;};if _df .Urx > _eag {_eag =_df .Urx ;};if _df .Lly < _gge {_gge =_df .Lly ;};if _df .Ury > _gf {_gf =_df .Ury ;};};_fc .X =_eb ;_fc .Y =_gge ;_fc .Width =_eag -_eb ;_fc .Height =_gf -_gge ;return _fc ;};
|
|
|
|
// Polyline defines a slice of points that are connected as straight lines.
|
|
type Polyline struct{Points []Point ;LineColor *_bg .PdfColorDeviceRGB ;LineWidth float64 ;};
|
|
|
|
// Add adds the specified vector to the current one and returns the result.
|
|
func (_gbe Vector )Add (other Vector )Vector {_gbe .Dx +=other .Dx ;_gbe .Dy +=other .Dy ;return _gbe };
|
|
|
|
// Vector represents a two-dimensional vector.
|
|
type Vector struct{Dx float64 ;Dy float64 ;};func (_gbf Point )String ()string {return _g .Sprintf ("(\u0025\u002e\u0031\u0066\u002c\u0025\u002e\u0031\u0066\u0029",_gbf .X ,_gbf .Y );};
|
|
|
|
// GetPolarAngle returns the angle the magnitude of the vector forms with the
|
|
// positive X-axis going counterclockwise.
|
|
func (_abc Vector )GetPolarAngle ()float64 {return _b .Atan2 (_abc .Dy ,_abc .Dx )};const (LineEndingStyleNone LineEndingStyle =0;LineEndingStyleArrow LineEndingStyle =1;LineEndingStyleButt LineEndingStyle =2;);
|
|
|
|
// 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 *_bg .PdfColorDeviceRGB ;BorderEnabled bool ;BorderWidth float64 ;BorderColor *_bg .PdfColorDeviceRGB ;Opacity float64 ;};
|
|
|
|
// 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 (_def Rectangle )Draw (gsName string )([]byte ,*_bg .PdfRectangle ,error ){_age :=NewPath ();_age =_age .AppendPoint (NewPoint (0,0));_age =_age .AppendPoint (NewPoint (0,_def .Height ));_age =_age .AppendPoint (NewPoint (_def .Width ,_def .Height ));_age =_age .AppendPoint (NewPoint (_def .Width ,0));_age =_age .AppendPoint (NewPoint (0,0));if _def .X !=0||_def .Y !=0{_age =_age .Offset (_def .X ,_def .Y );};_bgd :=_c .NewContentCreator ();_bgd .Add_q ();if _def .FillEnabled {_bgd .Add_rg (_def .FillColor .R (),_def .FillColor .G (),_def .FillColor .B ());};if _def .BorderEnabled {_bgd .Add_RG (_def .BorderColor .R (),_def .BorderColor .G (),_def .BorderColor .B ());_bgd .Add_w (_def .BorderWidth );};if len (gsName )> 1{_bgd .Add_gs (_f .PdfObjectName (gsName ));};DrawPathWithCreator (_age ,_bgd );_bgd .Add_h ();if _def .FillEnabled &&_def .BorderEnabled {_bgd .Add_B ();}else if _def .FillEnabled {_bgd .Add_f ();}else if _def .BorderEnabled {_bgd .Add_S ();};_bgd .Add_Q ();return _bgd .Bytes (),_age .GetBoundingBox ().ToPdfRectangle (),nil ;};
|
|
|
|
// NewVectorPolar returns a new vector calculated from the specified
|
|
// magnitude and angle.
|
|
func NewVectorPolar (length float64 ,theta float64 )Vector {_bcd :=Vector {};_bcd .Dx =length *_b .Cos (theta );_bcd .Dy =length *_b .Sin (theta );return _bcd ;}; |