-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented : Curve & Filled Curve Shape with test
- Loading branch information
Showing
6 changed files
with
279 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package creator | ||
|
||
import ( | ||
"strings" | ||
"fmt" | ||
"github.com/unidoc/unidoc/pdf/model" | ||
) | ||
|
||
// NewCurve returns new instance of Curve | ||
func NewCurve(x1, y1, cx, cy, x2, y2 float64) *Curve { | ||
c := &Curve{} | ||
|
||
c.x1 = x1 | ||
c.y1 = y1 | ||
|
||
c.cx = cx | ||
c.cy = cy | ||
|
||
c.x2 = x2 | ||
c.y2 = y2 | ||
|
||
c.lineColor = model.NewPdfColorDeviceRGB(0, 0, 0) | ||
c.lineWidth = 1.0 | ||
return c | ||
} | ||
|
||
type Curve struct { | ||
x1 float64 | ||
y1 float64 | ||
cx float64 // control point | ||
cy float64 | ||
x2 float64 | ||
y2 float64 | ||
|
||
lineColor *model.PdfColorDeviceRGB | ||
lineWidth float64 | ||
} | ||
|
||
// SetWidth sets line width | ||
func (c *Curve) SetWidth(width float64) { | ||
c.lineWidth = width | ||
} | ||
|
||
// SetColor sets the line color. | ||
func (c *Curve) SetColor(col Color) { | ||
c.lineColor = model.NewPdfColorDeviceRGB(col.ToRGB()) | ||
} | ||
|
||
// GeneratePageBlocks generates page blocks | ||
func (c *Curve) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext, error) { | ||
block := NewBlock(ctx.PageWidth, ctx.PageHeight) | ||
|
||
var ops []string | ||
ops = append(ops, fmt.Sprintf("%.2f w", c.lineWidth)) // line widtdh | ||
ops = append(ops, fmt.Sprintf("%.3f %.3f %.3f RG", c.lineColor[0], c.lineColor[1], c.lineColor[2])) // line color | ||
ops = append(ops, fmt.Sprintf("%.2f %.2f m", c.x1, ctx.PageHeight-c.y1)) // move to | ||
ops = append(ops, fmt.Sprintf("%.5f %.5f %.5f %.5f v S", c.cx, ctx.PageHeight-c.cy, c.x2, ctx.PageHeight-c.y2)) | ||
|
||
err := block.addContentsByString(strings.Join(ops, "\n")) | ||
if err != nil { | ||
return nil, ctx, err | ||
} | ||
return []*Block{block}, ctx, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package creator | ||
|
||
import "testing" | ||
|
||
const testPdfFileWithCurve = "../../testfiles/curve.pdf" | ||
|
||
func TestNewCurve(t *testing.T) { | ||
creator := New() | ||
creator.NewPage() | ||
curve := NewCurve(20, 20, 15, 35, 40, 150) | ||
curve.SetWidth(3.0) | ||
curve.SetColor(ColorGreen) | ||
err := creator.Draw(curve) | ||
if err != nil { | ||
t.Errorf("Fail: %v", err) | ||
return | ||
} | ||
|
||
err = creator.WriteToFile(testPdfFileWithCurve) | ||
if err != nil { | ||
t.Errorf("Fail: %v", err) | ||
return | ||
} | ||
} | ||
|
||
func CreateCurve(x1, y1, cx, cy, x2, y2 float64, color Color) *Curve { | ||
curve := NewCurve(x1, y1, cx, cy, x2, y2) | ||
curve.SetWidth(1) | ||
curve.SetColor(color) | ||
return curve | ||
} | ||
|
||
func CreateLine(x1, y1, x2, y2, width float64) *Line { | ||
line := NewLine(x1, y1, x2, y2) | ||
line.SetLineWidth(width) | ||
line.SetColor(ColorRed) | ||
return line | ||
} | ||
|
||
func TestNewCurveWithGlass(t *testing.T) { | ||
creator := New() | ||
creator.NewPage() | ||
|
||
// Width 200 | ||
creator.Draw(CreateLine(30, 200, 270, 200, 1)) | ||
|
||
// Curve up | ||
creator.Draw(CreateCurve(50, 200, 75, 145, 150, 150, ColorRed)) | ||
creator.Draw(CreateCurve(150, 150, 205, 145, 250, 200, ColorGreen)) | ||
|
||
// Curve down | ||
creator.Draw(CreateCurve(50, 200, 75, 245, 150, 250, ColorBlue)) | ||
creator.Draw(CreateCurve(150, 250, 225, 245, 250, 200, ColorBlack)) | ||
|
||
// Vertical line | ||
creator.Draw(CreateLine(50, 200, 51, 400, 1)) | ||
creator.Draw(CreateLine(250, 200, 251, 400, 1)) | ||
|
||
// Curve down | ||
creator.Draw(CreateCurve(51, 399, 75, 445, 150, 450, ColorRed)) | ||
creator.Draw(CreateCurve(150, 450, 225, 445, 251, 399, ColorGreen)) | ||
|
||
err := creator.WriteToFile(testPdfFileWithCurve) | ||
if err != nil { | ||
t.Errorf("Fail: %v", err) | ||
return | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package creator | ||
|
||
import ( | ||
"github.com/unidoc/unidoc/pdf/contentstream/draw" | ||
pdfcontent "github.com/unidoc/unidoc/pdf/contentstream" | ||
pdfcore "github.com/unidoc/unidoc/pdf/core" | ||
pdf "github.com/unidoc/unidoc/pdf/model" | ||
) | ||
|
||
type FilledCurve struct { | ||
curves []draw.CubicBezierCurve | ||
FillEnabled bool // Show fill? | ||
fillColor *pdf.PdfColorDeviceRGB | ||
BorderEnabled bool // Show border? | ||
BorderWidth float64 | ||
borderColor *pdf.PdfColorDeviceRGB | ||
Opacity float64 // Alpha value (0-1). | ||
} | ||
|
||
// NewFilledCurve returns a instance of filled curve | ||
func NewFilledCurve() *FilledCurve { | ||
curve := FilledCurve{} | ||
curve.curves = []draw.CubicBezierCurve{} | ||
return &curve | ||
} | ||
|
||
// AppendCurve appends curve to filled curve | ||
func (this *FilledCurve) AppendCurve(curve draw.CubicBezierCurve) *FilledCurve { | ||
this.curves = append(this.curves, curve) | ||
return this | ||
} | ||
|
||
func (this *FilledCurve) SetFillColor(color Color) { | ||
this.fillColor = pdf.NewPdfColorDeviceRGB(color.ToRGB()) | ||
} | ||
|
||
func (this *FilledCurve) SetBorderColor(color Color) { | ||
this.borderColor = pdf.NewPdfColorDeviceRGB(color.ToRGB()) | ||
} | ||
|
||
// Draw a 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 (this *FilledCurve) draw(gsName string) ([]byte, *pdf.PdfRectangle, error) { | ||
bpath := draw.NewCubicBezierPath() | ||
for _, c := range this.curves { | ||
bpath = bpath.AppendCurve(c) | ||
} | ||
|
||
creator := pdfcontent.NewContentCreator() | ||
creator.Add_q() | ||
|
||
if this.FillEnabled { | ||
creator.Add_rg(this.fillColor.R(), this.fillColor.G(), this.fillColor.B()) | ||
} | ||
if this.BorderEnabled { | ||
creator.Add_RG(this.borderColor.R(), this.borderColor.G(), this.borderColor.B()) | ||
creator.Add_w(this.BorderWidth) | ||
} | ||
if len(gsName) > 1 { | ||
// If a graphics state is provided, use it. (Used for transparency settings here). | ||
creator.Add_gs(pdfcore.PdfObjectName(gsName)) | ||
} | ||
|
||
draw.DrawBezierPathWithCreator(bpath, creator) | ||
creator.Add_h() // Close the path. | ||
|
||
if this.FillEnabled && this.BorderEnabled { | ||
creator.Add_B() // fill and stroke. | ||
} else if this.FillEnabled { | ||
creator.Add_f() // Fill. | ||
} else if this.BorderEnabled { | ||
creator.Add_S() // Stroke. | ||
} | ||
creator.Add_Q() | ||
|
||
// Get bounding box. | ||
pathBbox := bpath.GetBoundingBox() | ||
if this.BorderEnabled { | ||
// Account for stroke width. | ||
pathBbox.Height += this.BorderWidth | ||
pathBbox.Width += this.BorderWidth | ||
pathBbox.X -= this.BorderWidth / 2 | ||
pathBbox.Y -= this.BorderWidth / 2 | ||
} | ||
|
||
// Bounding box - global coordinate system. | ||
bbox := &pdf.PdfRectangle{} | ||
bbox.Llx = pathBbox.X | ||
bbox.Lly = pathBbox.Y | ||
bbox.Urx = pathBbox.X + pathBbox.Width | ||
bbox.Ury = pathBbox.Y + pathBbox.Height | ||
return creator.Bytes(), bbox, nil | ||
} | ||
|
||
// GeneratePageBlocks generates page blocks | ||
func (this *FilledCurve) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext, error) { | ||
block := NewBlock(ctx.PageWidth, ctx.PageHeight) | ||
|
||
contents, _, err := this.draw("") | ||
err = block.addContentsByString(string(contents)) | ||
if err != nil { | ||
return nil, ctx, err | ||
} | ||
return []*Block{block}, ctx, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package creator | ||
|
||
import ( | ||
"testing" | ||
"github.com/unidoc/unidoc/pdf/contentstream/draw" | ||
) | ||
|
||
const testPdfFileWithFilledCurve = "../../testfiles/filledCurve.pdf" | ||
|
||
func CreateFillCurve(x0, y0, x1, y1, x2, y2, x3, y3 float64) draw.CubicBezierCurve { | ||
return draw.NewCubicBezierCurve(x0, y0, x1, y1, x2, y2, x3, y3) | ||
} | ||
|
||
func TestNewFilledCurve(t *testing.T) { | ||
filledCurve := NewFilledCurve() | ||
filledCurve.FillEnabled = true | ||
filledCurve.BorderEnabled = true | ||
filledCurve.BorderWidth = 2 | ||
filledCurve.SetFillColor(ColorGreen) | ||
filledCurve.SetBorderColor(ColorBlue) | ||
|
||
// Up Left | ||
filledCurve.AppendCurve(CreateFillCurve(300, 300, 230, 350, 200, 280, 220, 220)) | ||
// Down Left | ||
filledCurve.AppendCurve(CreateFillCurve(225, 240, 240, 180, 260, 160, 300, 180)) | ||
// Down Right | ||
filledCurve.AppendCurve(CreateFillCurve(305, 170, 335, 165, 350, 185, 365, 220)) | ||
// Up Right | ||
filledCurve.AppendCurve(CreateFillCurve(365, 240, 385, 315, 350, 325, 300, 300)) | ||
// Leaf | ||
filledCurve.AppendCurve(CreateFillCurve(300, 300, 290, 350, 295, 370, 300, 390)) | ||
|
||
creator := New() | ||
creator.NewPage() | ||
creator.Draw(filledCurve) | ||
|
||
err := creator.WriteToFile(testPdfFileWithFilledCurve) | ||
if err != nil { | ||
t.Errorf("Fail: %v", err) | ||
return | ||
} | ||
} |
Binary file not shown.
Binary file not shown.