2018-06-09 06:03:40 +06:00
|
|
|
package creator
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/unidoc/unidoc/pdf/contentstream/draw"
|
|
|
|
"github.com/unidoc/unidoc/pdf/model"
|
|
|
|
)
|
|
|
|
|
2018-07-06 21:11:34 +06:00
|
|
|
const (
|
|
|
|
doubleBorderAdjustment = 1
|
|
|
|
)
|
|
|
|
|
|
|
|
// border represents cell border
|
|
|
|
type border struct {
|
2018-06-12 03:41:33 +06:00
|
|
|
x float64 // Upper left corner
|
|
|
|
y float64
|
|
|
|
width float64
|
|
|
|
height float64
|
|
|
|
fillColor *model.PdfColorDeviceRGB
|
|
|
|
borderColorLeft *model.PdfColorDeviceRGB
|
|
|
|
borderWidthLeft float64
|
|
|
|
borderColorBottom *model.PdfColorDeviceRGB
|
|
|
|
borderWidthBottom float64
|
|
|
|
borderColorRight *model.PdfColorDeviceRGB
|
|
|
|
borderWidthRight float64
|
|
|
|
borderColorTop *model.PdfColorDeviceRGB
|
|
|
|
borderWidthTop float64
|
2018-06-29 23:55:23 +06:00
|
|
|
LineStyle draw.LineStyle
|
2018-07-06 21:11:34 +06:00
|
|
|
StyleLeft CellBorderStyle
|
|
|
|
StyleRight CellBorderStyle
|
|
|
|
StyleTop CellBorderStyle
|
|
|
|
StyleBottom CellBorderStyle
|
2018-06-09 06:03:40 +06:00
|
|
|
}
|
|
|
|
|
2018-07-06 22:12:20 +06:00
|
|
|
// newBorder returns and instance of border
|
|
|
|
func newBorder(x, y, width, height float64) *border {
|
2018-07-06 21:11:34 +06:00
|
|
|
border := &border{}
|
2018-06-09 06:03:40 +06:00
|
|
|
|
|
|
|
border.x = x
|
|
|
|
border.y = y
|
|
|
|
border.width = width
|
|
|
|
border.height = height
|
|
|
|
|
2018-06-12 03:41:33 +06:00
|
|
|
border.borderColorTop = model.NewPdfColorDeviceRGB(0, 0, 0)
|
|
|
|
border.borderColorBottom = model.NewPdfColorDeviceRGB(0, 0, 0)
|
|
|
|
border.borderColorLeft = model.NewPdfColorDeviceRGB(0, 0, 0)
|
|
|
|
border.borderColorRight = model.NewPdfColorDeviceRGB(0, 0, 0)
|
2018-06-29 23:55:23 +06:00
|
|
|
|
|
|
|
border.borderWidthTop = 1
|
|
|
|
border.borderWidthBottom = 1
|
|
|
|
border.borderWidthLeft = 1
|
|
|
|
border.borderWidthRight = 1
|
|
|
|
|
2018-07-06 21:11:34 +06:00
|
|
|
border.LineStyle = draw.LineStyleSolid
|
2018-06-09 06:03:40 +06:00
|
|
|
return border
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// GetCoords returns coordinates of border
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) GetCoords() (float64, float64) {
|
2018-06-09 06:03:40 +06:00
|
|
|
return border.x, border.y
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// SetWidthLeft sets border width for left
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) SetWidthLeft(bw float64) {
|
2018-06-09 06:03:40 +06:00
|
|
|
border.borderWidthLeft = bw
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// SetColorLeft sets border color for left
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) SetColorLeft(col Color) {
|
2018-06-09 06:03:40 +06:00
|
|
|
border.borderColorLeft = model.NewPdfColorDeviceRGB(col.ToRGB())
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// SetWidthBottom sets border width for bottom
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) SetWidthBottom(bw float64) {
|
2018-06-09 06:03:40 +06:00
|
|
|
border.borderWidthBottom = bw
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// SetColorBottom sets border color for bottom
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) SetColorBottom(col Color) {
|
2018-06-09 06:03:40 +06:00
|
|
|
border.borderColorBottom = model.NewPdfColorDeviceRGB(col.ToRGB())
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// SetWidthRight sets border width for right
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) SetWidthRight(bw float64) {
|
2018-06-09 06:03:40 +06:00
|
|
|
border.borderWidthRight = bw
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// SetColorRight sets border color for right
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) SetColorRight(col Color) {
|
2018-06-09 06:03:40 +06:00
|
|
|
border.borderColorRight = model.NewPdfColorDeviceRGB(col.ToRGB())
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// SetWidthTop sets border width for top
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) SetWidthTop(bw float64) {
|
2018-06-09 06:03:40 +06:00
|
|
|
border.borderWidthTop = bw
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// SetColorTop sets border color for top
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) SetColorTop(col Color) {
|
2018-06-09 06:03:40 +06:00
|
|
|
border.borderColorTop = model.NewPdfColorDeviceRGB(col.ToRGB())
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// SetFillColor sets background color for border
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) SetFillColor(col Color) {
|
2018-06-09 06:03:40 +06:00
|
|
|
border.fillColor = model.NewPdfColorDeviceRGB(col.ToRGB())
|
|
|
|
}
|
|
|
|
|
2018-06-29 23:55:23 +06:00
|
|
|
// GeneratePageBlocks creates drawable
|
2018-07-06 21:11:34 +06:00
|
|
|
func (border *border) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext, error) {
|
2018-06-09 06:03:40 +06:00
|
|
|
block := NewBlock(ctx.PageWidth, ctx.PageHeight)
|
|
|
|
startX := border.x
|
|
|
|
startY := ctx.PageHeight - border.y
|
|
|
|
|
2018-07-06 21:11:34 +06:00
|
|
|
// Width height adjustment for double border
|
|
|
|
autoTopAdjustmentOnLeft := border.borderWidthLeft * doubleBorderAdjustment
|
|
|
|
autoTopAdjustmentOnRight := border.borderWidthRight * doubleBorderAdjustment
|
|
|
|
autoRightAdjustmentOnTop := border.borderWidthTop * doubleBorderAdjustment
|
|
|
|
autoRightAdjustmentOnBottom := border.borderWidthBottom * doubleBorderAdjustment
|
|
|
|
autoLeftAdjustmentOnTop := border.borderWidthTop * doubleBorderAdjustment
|
|
|
|
autoLeftAdjustmentOnBottom := border.borderWidthBottom * doubleBorderAdjustment
|
|
|
|
autoBottomAdjustmentOnLeft := border.borderWidthLeft * doubleBorderAdjustment
|
|
|
|
autoBottomAdjustmentOnRight := border.borderWidthRight * doubleBorderAdjustment
|
|
|
|
|
2018-06-09 06:03:40 +06:00
|
|
|
if border.fillColor != nil {
|
|
|
|
drawrect := draw.Rectangle{
|
|
|
|
Opacity: 1.0,
|
2018-07-06 21:11:34 +06:00
|
|
|
X: border.x + (border.borderWidthLeft * 3) - 0.5,
|
2018-07-10 00:51:45 +06:00
|
|
|
Y: (ctx.PageHeight - border.y - border.height) + (border.borderWidthLeft * 2),
|
2018-07-06 21:11:34 +06:00
|
|
|
Height: border.height - (border.borderWidthBottom * 3),
|
|
|
|
Width: border.width - (border.borderWidthRight * 3),
|
2018-06-09 06:03:40 +06:00
|
|
|
}
|
|
|
|
drawrect.FillEnabled = true
|
|
|
|
drawrect.FillColor = border.fillColor
|
|
|
|
drawrect.BorderEnabled = false
|
|
|
|
|
|
|
|
contents, _, err := drawrect.Draw("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = block.addContentsByString(string(contents))
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-30 00:06:50 +06:00
|
|
|
if border.borderWidthTop != 0 {
|
2018-07-10 00:51:45 +06:00
|
|
|
offsetX1 := 0.0
|
|
|
|
offsetX2 := 0.0
|
|
|
|
|
2018-07-06 21:11:34 +06:00
|
|
|
y1 := startY
|
|
|
|
y2 := startY
|
|
|
|
|
|
|
|
if border.StyleTop == CellBorderStyleDoubleTop {
|
2018-07-10 00:51:45 +06:00
|
|
|
offsetX1 = 1
|
|
|
|
offsetX2 = 1
|
|
|
|
|
2018-07-06 21:11:34 +06:00
|
|
|
// Line Top
|
|
|
|
lineTop := draw.Line{
|
|
|
|
LineWidth: border.borderWidthTop,
|
|
|
|
Opacity: 1.0,
|
|
|
|
LineColor: border.borderColorTop,
|
|
|
|
LineEndingStyle1: draw.LineEndingStyleNone,
|
|
|
|
LineEndingStyle2: draw.LineEndingStyleNone,
|
2018-07-10 00:51:45 +06:00
|
|
|
X1: startX + autoTopAdjustmentOnLeft + offsetX1,
|
2018-07-06 21:11:34 +06:00
|
|
|
Y1: y1 - (doubleBorderAdjustment * border.borderWidthTop),
|
2018-07-10 00:51:45 +06:00
|
|
|
X2: ((startX + border.width) - autoTopAdjustmentOnRight) + offsetX2,
|
2018-07-06 21:11:34 +06:00
|
|
|
Y2: y2 - (doubleBorderAdjustment * border.borderWidthTop),
|
|
|
|
LineStyle: border.LineStyle,
|
|
|
|
}
|
|
|
|
contentsTop, _, err := lineTop.Draw("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
err = block.addContentsByString(string(contentsTop))
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
|
|
|
|
y1 = y1 + (doubleBorderAdjustment * border.borderWidthTop)
|
|
|
|
y2 = y2 + (doubleBorderAdjustment * border.borderWidthTop)
|
2018-07-10 00:51:45 +06:00
|
|
|
|
|
|
|
offsetX1 = (-(border.borderWidthRight / 2)) + 0.5
|
|
|
|
} else {
|
|
|
|
offsetX1 = 1
|
|
|
|
offsetX2 = -1
|
2018-07-06 21:11:34 +06:00
|
|
|
}
|
|
|
|
|
2018-06-30 00:06:50 +06:00
|
|
|
// Line Top
|
|
|
|
lineTop := draw.Line{
|
|
|
|
LineWidth: border.borderWidthTop,
|
|
|
|
Opacity: 1.0,
|
|
|
|
LineColor: border.borderColorTop,
|
|
|
|
LineEndingStyle1: draw.LineEndingStyleNone,
|
|
|
|
LineEndingStyle2: draw.LineEndingStyleNone,
|
2018-07-10 00:51:45 +06:00
|
|
|
X1: startX + offsetX1,
|
2018-07-06 21:11:34 +06:00
|
|
|
Y1: y1,
|
2018-07-10 00:51:45 +06:00
|
|
|
X2: startX + border.width + autoTopAdjustmentOnRight + offsetX2,
|
2018-07-06 21:11:34 +06:00
|
|
|
Y2: y2,
|
2018-06-30 00:06:50 +06:00
|
|
|
LineStyle: border.LineStyle,
|
|
|
|
}
|
|
|
|
contentsTop, _, err := lineTop.Draw("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
err = block.addContentsByString(string(contentsTop))
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
2018-06-09 06:03:40 +06:00
|
|
|
}
|
|
|
|
|
2018-06-30 00:06:50 +06:00
|
|
|
if border.borderWidthLeft != 0 {
|
2018-07-10 00:51:45 +06:00
|
|
|
offsetX1 := 1.0
|
|
|
|
offsetX2 := 1.0
|
|
|
|
|
|
|
|
x1 := startX + offsetX1
|
|
|
|
x2 := startX + offsetX2
|
2018-07-06 21:11:34 +06:00
|
|
|
|
|
|
|
if border.StyleLeft == CellBorderStyleDoubleLeft {
|
|
|
|
// Line Left
|
|
|
|
lineLeft := draw.Line{
|
|
|
|
LineWidth: border.borderWidthLeft,
|
|
|
|
Opacity: 1.0,
|
|
|
|
LineColor: border.borderColorLeft,
|
|
|
|
LineEndingStyle1: draw.LineEndingStyleNone,
|
|
|
|
LineEndingStyle2: draw.LineEndingStyleNone,
|
|
|
|
X1: x1 - (doubleBorderAdjustment * border.borderWidthLeft),
|
|
|
|
Y1: startY + autoLeftAdjustmentOnTop,
|
|
|
|
X2: x2 - (doubleBorderAdjustment * border.borderWidthLeft),
|
|
|
|
Y2: (startY - border.height) - autoLeftAdjustmentOnBottom,
|
|
|
|
LineStyle: border.LineStyle,
|
|
|
|
}
|
|
|
|
contentsLeft, _, err := lineLeft.Draw("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
err = block.addContentsByString(string(contentsLeft))
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
|
|
|
|
x1 = x1 + (doubleBorderAdjustment * border.borderWidthLeft)
|
|
|
|
x2 = x2 + (doubleBorderAdjustment * border.borderWidthLeft)
|
|
|
|
}
|
|
|
|
|
2018-06-30 00:06:50 +06:00
|
|
|
// Line Left
|
|
|
|
lineLeft := draw.Line{
|
|
|
|
LineWidth: border.borderWidthLeft,
|
|
|
|
Opacity: 1.0,
|
|
|
|
LineColor: border.borderColorLeft,
|
|
|
|
LineEndingStyle1: draw.LineEndingStyleNone,
|
|
|
|
LineEndingStyle2: draw.LineEndingStyleNone,
|
2018-07-06 21:11:34 +06:00
|
|
|
X1: x1,
|
2018-06-30 00:06:50 +06:00
|
|
|
Y1: startY,
|
2018-07-06 21:11:34 +06:00
|
|
|
X2: x2,
|
|
|
|
Y2: (startY - border.height) + autoLeftAdjustmentOnBottom,
|
2018-06-30 00:06:50 +06:00
|
|
|
LineStyle: border.LineStyle,
|
|
|
|
}
|
|
|
|
contentsLeft, _, err := lineLeft.Draw("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
err = block.addContentsByString(string(contentsLeft))
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
2018-06-09 06:03:40 +06:00
|
|
|
}
|
|
|
|
|
2018-06-30 00:06:50 +06:00
|
|
|
if border.borderWidthRight != 0 {
|
2018-07-10 00:51:45 +06:00
|
|
|
offsetY2 := 0.0
|
|
|
|
|
2018-07-06 21:11:34 +06:00
|
|
|
x1 := startX + border.width
|
|
|
|
x2 := startX + border.width
|
|
|
|
|
|
|
|
if border.StyleRight == CellBorderStyleDoubleRight {
|
|
|
|
// Line Right
|
|
|
|
lineRight := draw.Line{
|
|
|
|
LineWidth: border.borderWidthRight,
|
|
|
|
Opacity: 1.0,
|
|
|
|
LineColor: border.borderColorRight,
|
|
|
|
LineEndingStyle1: draw.LineEndingStyleNone,
|
|
|
|
LineEndingStyle2: draw.LineEndingStyleNone,
|
|
|
|
X1: x1 - (doubleBorderAdjustment * border.borderWidthRight),
|
|
|
|
Y1: startY - autoRightAdjustmentOnTop,
|
|
|
|
X2: x2 - (doubleBorderAdjustment * border.borderWidthRight),
|
|
|
|
Y2: (startY - border.height) + autoRightAdjustmentOnBottom,
|
|
|
|
LineStyle: border.LineStyle,
|
|
|
|
}
|
|
|
|
contentsRight, _, err := lineRight.Draw("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
err = block.addContentsByString(string(contentsRight))
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
|
|
|
|
x1 = x1 + (doubleBorderAdjustment * border.borderWidthRight)
|
|
|
|
x2 = x2 + (doubleBorderAdjustment * border.borderWidthRight)
|
2018-07-10 00:51:45 +06:00
|
|
|
} else {
|
|
|
|
offsetY2 = 1
|
2018-07-06 21:11:34 +06:00
|
|
|
}
|
|
|
|
|
2018-06-30 00:06:50 +06:00
|
|
|
// Line Right
|
|
|
|
lineRight := draw.Line{
|
|
|
|
LineWidth: border.borderWidthRight,
|
|
|
|
Opacity: 1.0,
|
|
|
|
LineColor: border.borderColorRight,
|
|
|
|
LineEndingStyle1: draw.LineEndingStyleNone,
|
|
|
|
LineEndingStyle2: draw.LineEndingStyleNone,
|
2018-07-06 21:11:34 +06:00
|
|
|
X1: x1,
|
|
|
|
Y1: startY + autoRightAdjustmentOnTop,
|
|
|
|
X2: x2,
|
2018-07-10 00:51:45 +06:00
|
|
|
Y2: (startY - border.height) - autoRightAdjustmentOnBottom + offsetY2,
|
2018-06-30 00:06:50 +06:00
|
|
|
LineStyle: border.LineStyle,
|
|
|
|
}
|
|
|
|
contentsRight, _, err := lineRight.Draw("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
err = block.addContentsByString(string(contentsRight))
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
2018-06-09 06:03:40 +06:00
|
|
|
}
|
|
|
|
|
2018-06-30 00:06:50 +06:00
|
|
|
if border.borderWidthBottom != 0 {
|
|
|
|
// Line Bottom
|
2018-07-10 00:51:45 +06:00
|
|
|
offsetFull := 0.0
|
2018-07-06 21:11:34 +06:00
|
|
|
|
|
|
|
y1 := startY - border.height
|
|
|
|
y2 := startY - border.height
|
|
|
|
|
|
|
|
if border.StyleBottom == CellBorderStyleDoubleBottom {
|
2018-07-10 00:51:45 +06:00
|
|
|
offsetFull = 1
|
|
|
|
|
2018-07-06 21:11:34 +06:00
|
|
|
lineBottom := draw.Line{
|
|
|
|
LineWidth: border.borderWidthBottom,
|
|
|
|
Opacity: 1.0,
|
|
|
|
LineColor: border.borderColorBottom,
|
|
|
|
LineEndingStyle1: draw.LineEndingStyleNone,
|
|
|
|
LineEndingStyle2: draw.LineEndingStyleNone,
|
|
|
|
X1: (startX + border.width) - autoBottomAdjustmentOnRight,
|
|
|
|
Y1: y1 + (doubleBorderAdjustment * border.borderWidthBottom),
|
2018-07-10 00:51:45 +06:00
|
|
|
X2: startX + autoBottomAdjustmentOnLeft + offsetFull,
|
2018-07-06 21:11:34 +06:00
|
|
|
Y2: y2 + (doubleBorderAdjustment * border.borderWidthBottom),
|
|
|
|
LineStyle: border.LineStyle,
|
|
|
|
}
|
|
|
|
contentsBottom, _, err := lineBottom.Draw("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
err = block.addContentsByString(string(contentsBottom))
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
|
|
|
|
y1 = y1 - (doubleBorderAdjustment * border.borderWidthBottom)
|
|
|
|
y2 = y2 - (doubleBorderAdjustment * border.borderWidthBottom)
|
|
|
|
}
|
|
|
|
|
2018-06-30 00:06:50 +06:00
|
|
|
lineBottom := draw.Line{
|
|
|
|
LineWidth: border.borderWidthBottom,
|
|
|
|
Opacity: 1.0,
|
|
|
|
LineColor: border.borderColorBottom,
|
|
|
|
LineEndingStyle1: draw.LineEndingStyleNone,
|
|
|
|
LineEndingStyle2: draw.LineEndingStyleNone,
|
2018-07-06 21:11:34 +06:00
|
|
|
X1: startX + border.width + autoBottomAdjustmentOnRight,
|
|
|
|
Y1: y1,
|
|
|
|
X2: startX + autoBottomAdjustmentOnRight,
|
|
|
|
Y2: y2,
|
2018-06-30 00:06:50 +06:00
|
|
|
LineStyle: border.LineStyle,
|
|
|
|
}
|
|
|
|
contentsBottom, _, err := lineBottom.Draw("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
|
|
|
err = block.addContentsByString(string(contentsBottom))
|
|
|
|
if err != nil {
|
|
|
|
return nil, ctx, err
|
|
|
|
}
|
2018-06-09 06:03:40 +06:00
|
|
|
}
|
2018-06-30 00:06:50 +06:00
|
|
|
|
2018-06-09 06:03:40 +06:00
|
|
|
return []*Block{block}, ctx, nil
|
|
|
|
}
|