mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-30 13:48:51 +08:00
Merge pull request #237 from adrg/component-creator
Create components through the creator
This commit is contained in:
commit
94146c2603
@ -8,6 +8,8 @@ package creator
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/unidoc/unidoc/common"
|
||||
"github.com/unidoc/unidoc/pdf/contentstream"
|
||||
@ -391,18 +393,12 @@ func mergeContents(contents *contentstream.ContentStreamOperations, resources *m
|
||||
if len(op.Params) == 2 {
|
||||
if name, ok := op.Params[0].(*core.PdfObjectName); ok {
|
||||
if _, processed := fontMap[*name]; !processed {
|
||||
var useName core.PdfObjectName
|
||||
// Process if not already processed.
|
||||
obj, found := resourcesToAdd.GetFontByName(*name)
|
||||
if found {
|
||||
useName = *name
|
||||
for {
|
||||
obj2, found := resources.GetFontByName(useName)
|
||||
if !found || obj2 == obj {
|
||||
break
|
||||
}
|
||||
useName = useName + "0"
|
||||
}
|
||||
|
||||
useName := *name
|
||||
if found && obj != nil {
|
||||
useName = resourcesNextUnusedFontName(name.String(), obj, resources)
|
||||
}
|
||||
|
||||
resources.SetFontByName(useName, obj)
|
||||
@ -548,3 +544,27 @@ func mergeContents(contents *contentstream.ContentStreamOperations, resources *m
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourcesNextUnusedFontName(name string, font core.PdfObject, resources *model.PdfPageResources) core.PdfObjectName {
|
||||
prefix := strings.TrimRightFunc(strings.TrimSpace(name), func(r rune) bool {
|
||||
return unicode.IsNumber(r)
|
||||
})
|
||||
if prefix == "" {
|
||||
prefix = "Font"
|
||||
}
|
||||
|
||||
num := 0
|
||||
fontName := core.PdfObjectName(name)
|
||||
|
||||
for {
|
||||
f, found := resources.GetFontByName(fontName)
|
||||
if !found || f == font {
|
||||
break
|
||||
}
|
||||
|
||||
num++
|
||||
fontName = core.PdfObjectName(fmt.Sprintf("%s%d", prefix, num))
|
||||
}
|
||||
|
||||
return fontName
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/unidoc/unidoc/common"
|
||||
"github.com/unidoc/unidoc/pdf/model"
|
||||
)
|
||||
|
||||
// Chapter is used to arrange multiple drawables (paragraphs, images, etc) into a single section.
|
||||
@ -44,30 +43,21 @@ type Chapter struct {
|
||||
toc *TOC
|
||||
}
|
||||
|
||||
// NewChapter creates a new chapter with the specified title as the heading.
|
||||
func (c *Creator) NewChapter(title string) *Chapter {
|
||||
chap := &Chapter{}
|
||||
|
||||
c.chapters++
|
||||
chap.number = c.chapters
|
||||
chap.title = title
|
||||
|
||||
chap.showNumbering = true
|
||||
chap.includeInTOC = true
|
||||
|
||||
heading := fmt.Sprintf("%d. %s", c.chapters, title)
|
||||
p := NewParagraph(heading)
|
||||
// newChapter creates a new chapter with the specified title as the heading.
|
||||
func newChapter(toc *TOC, title string, number int, style TextStyle) *Chapter {
|
||||
p := newParagraph(fmt.Sprintf("%d. %s", number, title), style)
|
||||
p.SetFont(style.Font)
|
||||
p.SetFontSize(16)
|
||||
helvetica := model.NewStandard14FontMustCompile(model.Helvetica)
|
||||
p.SetFont(helvetica) // bold?
|
||||
|
||||
chap.heading = p
|
||||
chap.contents = []Drawable{}
|
||||
|
||||
// Keep a reference for toc.
|
||||
chap.toc = c.toc
|
||||
|
||||
return chap
|
||||
return &Chapter{
|
||||
number: number,
|
||||
title: title,
|
||||
showNumbering: true,
|
||||
includeInTOC: true,
|
||||
toc: toc,
|
||||
heading: p,
|
||||
contents: []Drawable{},
|
||||
}
|
||||
}
|
||||
|
||||
// SetShowNumbering sets a flag to indicate whether or not to show chapter numbers as part of title.
|
||||
|
@ -12,7 +12,8 @@ type PageSize [2]float64
|
||||
var PPI float64 = 72 // Points per inch. (Default resolution).
|
||||
|
||||
// PPMM specifies the default PDF resolution in points/mm.
|
||||
var PPMM float64 = 72 * 1.0 / 25.4 // Points per mm. (Default resolution).
|
||||
// Points per mm. (Default resolution).
|
||||
var PPMM = float64(72 * 1.0 / 25.4)
|
||||
|
||||
//
|
||||
// Commonly used page sizes
|
||||
|
@ -7,12 +7,14 @@ package creator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
goimage "image"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/unidoc/unidoc/common"
|
||||
"github.com/unidoc/unidoc/pdf/model"
|
||||
"github.com/unidoc/unidoc/pdf/model/textencoding"
|
||||
)
|
||||
|
||||
// Creator is a wrapper around functionality for creating PDF reports and/or adding new
|
||||
@ -51,6 +53,13 @@ type Creator struct {
|
||||
acroForm *model.PdfAcroForm
|
||||
|
||||
optimizer model.Optimizer
|
||||
|
||||
// Default fonts used by all components instantiated through the creator.
|
||||
defaultFontRegular *model.PdfFont
|
||||
defaultFontBold *model.PdfFont
|
||||
|
||||
// Default encoder used by all components instantiated through the creator.
|
||||
defaultTextEncoder textencoding.TextEncoder
|
||||
}
|
||||
|
||||
// SetForms adds an Acroform to a PDF file. Sets the specified form for writing.
|
||||
@ -103,7 +112,26 @@ func New() *Creator {
|
||||
c.pageMargins.top = m
|
||||
c.pageMargins.bottom = m
|
||||
|
||||
c.toc = NewTOC("Table of Contents")
|
||||
// Initialize default text encoder.
|
||||
c.defaultTextEncoder = textencoding.NewWinAnsiTextEncoder()
|
||||
|
||||
// Initialize default fonts.
|
||||
var err error
|
||||
|
||||
c.defaultFontRegular, err = model.NewStandard14Font(model.Helvetica)
|
||||
if err != nil {
|
||||
c.defaultFontRegular = model.DefaultFont()
|
||||
}
|
||||
c.defaultFontRegular.SetEncoder(c.defaultTextEncoder)
|
||||
|
||||
c.defaultFontBold, err = model.NewStandard14Font(model.HelveticaBold)
|
||||
if err != nil {
|
||||
c.defaultFontRegular = model.DefaultFont()
|
||||
}
|
||||
c.defaultFontBold.SetEncoder(c.defaultTextEncoder)
|
||||
|
||||
// Initialize creator table of contents.
|
||||
c.toc = c.NewTOC("Table of Contents")
|
||||
|
||||
return c
|
||||
}
|
||||
@ -288,7 +316,7 @@ func (c *Creator) RotateDeg(angleDeg int64) error {
|
||||
}
|
||||
|
||||
// Do the rotation.
|
||||
var rotation int64 = 0
|
||||
var rotation int64
|
||||
if page.Rotate != nil {
|
||||
rotation = *(page.Rotate)
|
||||
}
|
||||
@ -566,3 +594,131 @@ func (c *Creator) WriteToFile(outputPath string) error {
|
||||
|
||||
return c.Write(fWrite)
|
||||
}
|
||||
|
||||
/*
|
||||
Component creation methods.
|
||||
*/
|
||||
|
||||
// NewTextStyle creates a new text style object which can be used to style
|
||||
// chunks of text.
|
||||
// Default attributes:
|
||||
// Font: Helvetica
|
||||
// Font size: 10
|
||||
// Encoding: WinAnsiEncoding
|
||||
// Text color: black
|
||||
func (c *Creator) NewTextStyle() TextStyle {
|
||||
return newTextStyle(c.defaultFontRegular)
|
||||
}
|
||||
|
||||
// NewParagraph creates a new text paragraph.
|
||||
// Default attributes:
|
||||
// Font: Helvetica,
|
||||
// Font size: 10
|
||||
// Encoding: WinAnsiEncoding
|
||||
// Wrap: enabled
|
||||
// Text color: black
|
||||
func (c *Creator) NewParagraph(text string) *Paragraph {
|
||||
return newParagraph(text, c.NewTextStyle())
|
||||
}
|
||||
|
||||
// NewStyledParagraph creates a new styled paragraph.
|
||||
// Default attributes:
|
||||
// Font: Helvetica,
|
||||
// Font size: 10
|
||||
// Encoding: WinAnsiEncoding
|
||||
// Wrap: enabled
|
||||
// Text color: black
|
||||
func (c *Creator) NewStyledParagraph() *StyledParagraph {
|
||||
return newStyledParagraph(c.NewTextStyle())
|
||||
}
|
||||
|
||||
// NewTable create a new Table with a specified number of columns.
|
||||
func (c *Creator) NewTable(cols int) *Table {
|
||||
return newTable(cols)
|
||||
}
|
||||
|
||||
// NewDivision returns a new Division container component.
|
||||
func (c *Creator) NewDivision() *Division {
|
||||
return newDivision()
|
||||
}
|
||||
|
||||
// NewTOC creates a new table of contents.
|
||||
func (c *Creator) NewTOC(title string) *TOC {
|
||||
headingStyle := c.NewTextStyle()
|
||||
headingStyle.Font = c.defaultFontBold
|
||||
|
||||
return newTOC(title, c.NewTextStyle(), headingStyle)
|
||||
}
|
||||
|
||||
// NewTOCLine creates a new table of contents line with the default style.
|
||||
func (c *Creator) NewTOCLine(number, title, page string, level uint) *TOCLine {
|
||||
return newTOCLine(number, title, page, level, c.NewTextStyle())
|
||||
}
|
||||
|
||||
// NewStyledTOCLine creates a new table of contents line with the provided style.
|
||||
func (c *Creator) NewStyledTOCLine(number, title, page TextChunk, level uint, style TextStyle) *TOCLine {
|
||||
return newStyledTOCLine(number, title, page, level, style)
|
||||
}
|
||||
|
||||
// NewChapter creates a new chapter with the specified title as the heading.
|
||||
func (c *Creator) NewChapter(title string) *Chapter {
|
||||
c.chapters++
|
||||
return newChapter(c.toc, title, c.chapters, c.NewTextStyle())
|
||||
}
|
||||
|
||||
// NewSubchapter creates a new Subchapter under Chapter ch with specified title.
|
||||
// All other parameters are set to their defaults.
|
||||
func (c *Creator) NewSubchapter(ch *Chapter, title string) *Subchapter {
|
||||
return newSubchapter(ch, title, c.NewTextStyle())
|
||||
}
|
||||
|
||||
// NewRectangle creates a new Rectangle with default parameters
|
||||
// with left corner at (x,y) and width, height as specified.
|
||||
func (c *Creator) NewRectangle(x, y, width, height float64) *Rectangle {
|
||||
return newRectangle(x, y, width, height)
|
||||
}
|
||||
|
||||
// NewPageBreak create a new page break.
|
||||
func (c *Creator) NewPageBreak() *PageBreak {
|
||||
return newPageBreak()
|
||||
}
|
||||
|
||||
// NewLine creates a new Line with default parameters between (x1,y1) to (x2,y2).
|
||||
func (c *Creator) NewLine(x1, y1, x2, y2 float64) *Line {
|
||||
return newLine(x1, y1, x2, y2)
|
||||
}
|
||||
|
||||
// NewFilledCurve returns a instance of filled curve.
|
||||
func (c *Creator) NewFilledCurve() *FilledCurve {
|
||||
return newFilledCurve()
|
||||
}
|
||||
|
||||
// NewEllipse creates a new ellipse centered at (xc,yc) with a width and height specified.
|
||||
func (c *Creator) NewEllipse(xc, yc, width, height float64) *Ellipse {
|
||||
return newEllipse(xc, yc, width, height)
|
||||
}
|
||||
|
||||
// NewCurve returns new instance of Curve between points (x1,y1) and (x2, y2) with control point (cx,cy).
|
||||
func (c *Creator) NewCurve(x1, y1, cx, cy, x2, y2 float64) *Curve {
|
||||
return newCurve(x1, y1, cx, cy, x2, y2)
|
||||
}
|
||||
|
||||
// NewImage create a new image from a unidoc image (model.Image).
|
||||
func (c *Creator) NewImage(img *model.Image) (*Image, error) {
|
||||
return newImage(img)
|
||||
}
|
||||
|
||||
// NewImageFromData creates an Image from image data.
|
||||
func (c *Creator) NewImageFromData(data []byte) (*Image, error) {
|
||||
return newImageFromData(data)
|
||||
}
|
||||
|
||||
// NewImageFromFile creates an Image from a file.
|
||||
func (c *Creator) NewImageFromFile(path string) (*Image, error) {
|
||||
return newImageFromFile(path)
|
||||
}
|
||||
|
||||
// NewImageFromGoImage creates an Image from a go image.Image data structure.
|
||||
func (c *Creator) NewImageFromGoImage(goimg goimage.Image) (*Image, error) {
|
||||
return newImageFromGoImage(goimg)
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,8 +12,8 @@ import (
|
||||
"github.com/unidoc/unidoc/pdf/model"
|
||||
)
|
||||
|
||||
// NewCurve returns new instance of Curve between points (x1,y1) and (x2, y2) with control point (cx,cy).
|
||||
func NewCurve(x1, y1, cx, cy, x2, y2 float64) *Curve {
|
||||
// newCurve returns new instance of Curve between points (x1,y1) and (x2, y2) with control point (cx,cy).
|
||||
func newCurve(x1, y1, cx, cy, x2, y2 float64) *Curve {
|
||||
c := &Curve{}
|
||||
|
||||
c.x1 = x1
|
||||
|
@ -10,7 +10,7 @@ import "testing"
|
||||
func TestNewCurve(t *testing.T) {
|
||||
creator := New()
|
||||
creator.NewPage()
|
||||
curve := NewCurve(20, 20, 15, 35, 40, 150)
|
||||
curve := creator.NewCurve(20, 20, 15, 35, 40, 150)
|
||||
curve.SetWidth(3.0)
|
||||
curve.SetColor(ColorGreen)
|
||||
err := creator.Draw(curve)
|
||||
@ -26,15 +26,15 @@ func TestNewCurve(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func CreateCurve(x1, y1, cx, cy, x2, y2 float64, color Color) *Curve {
|
||||
curve := NewCurve(x1, y1, cx, cy, x2, y2)
|
||||
func CreateCurve(c *Creator, x1, y1, cx, cy, x2, y2 float64, color Color) *Curve {
|
||||
curve := c.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)
|
||||
func CreateLine(c *Creator, x1, y1, x2, y2, width float64) *Line {
|
||||
line := c.NewLine(x1, y1, x2, y2)
|
||||
line.SetLineWidth(width)
|
||||
line.SetColor(ColorRed)
|
||||
return line
|
||||
@ -45,23 +45,23 @@ func TestNewCurveWithGlass(t *testing.T) {
|
||||
creator.NewPage()
|
||||
|
||||
// Width 200
|
||||
creator.Draw(CreateLine(30, 200, 270, 200, 1))
|
||||
creator.Draw(CreateLine(creator, 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))
|
||||
creator.Draw(CreateCurve(creator, 50, 200, 75, 145, 150, 150, ColorRed))
|
||||
creator.Draw(CreateCurve(creator, 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))
|
||||
creator.Draw(CreateCurve(creator, 50, 200, 75, 245, 150, 250, ColorBlue))
|
||||
creator.Draw(CreateCurve(creator, 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))
|
||||
creator.Draw(CreateLine(creator, 50, 200, 51, 400, 1))
|
||||
creator.Draw(CreateLine(creator, 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))
|
||||
creator.Draw(CreateCurve(creator, 51, 399, 75, 445, 150, 450, ColorRed))
|
||||
creator.Draw(CreateCurve(creator, 150, 450, 225, 445, 251, 399, ColorGreen))
|
||||
|
||||
err := creator.WriteToFile("/tmp/curve_glass.pdf")
|
||||
if err != nil {
|
||||
|
@ -29,8 +29,8 @@ type Division struct {
|
||||
inline bool
|
||||
}
|
||||
|
||||
// NewDivision returns a new Division container component.
|
||||
func NewDivision() *Division {
|
||||
// newDivision returns a new Division container component.
|
||||
func newDivision() *Division {
|
||||
return &Division{
|
||||
components: []VectorDrawable{},
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func TestDivVertical(t *testing.T) {
|
||||
c.NewPage()
|
||||
|
||||
// Draw section title.
|
||||
p := NewParagraph("Regular division component")
|
||||
p := c.NewParagraph("Regular division component")
|
||||
p.SetMargins(0, 0, 20, 10)
|
||||
p.SetFont(fontBold)
|
||||
|
||||
@ -52,28 +52,31 @@ func TestDivVertical(t *testing.T) {
|
||||
}
|
||||
|
||||
// Draw division.
|
||||
div := NewDivision()
|
||||
div := c.NewDivision()
|
||||
|
||||
if div.Inline() {
|
||||
t.Fatal("Fail: Incorrect inline mode value")
|
||||
}
|
||||
|
||||
p = NewParagraph("Components are stacked vertically ")
|
||||
p = c.NewParagraph("Components are stacked vertically ")
|
||||
p.SetFont(fontRegular)
|
||||
div.Add(p)
|
||||
|
||||
p = NewParagraph("but not horizontally")
|
||||
p = c.NewParagraph("but not horizontally")
|
||||
p.SetFont(fontBold)
|
||||
div.Add(p)
|
||||
|
||||
// Add styled paragraph
|
||||
style := NewTextStyle()
|
||||
style := c.NewTextStyle()
|
||||
style.Color = ColorRGBFrom8bit(0, 0, 255)
|
||||
|
||||
s := NewStyledParagraph("Not even with a styled ", style)
|
||||
s := c.NewStyledParagraph()
|
||||
chunk := s.Append("Not even with a styled ")
|
||||
chunk.Style = style
|
||||
|
||||
style.Color = ColorRGBFrom8bit(255, 0, 0)
|
||||
s.Append("paragraph", style)
|
||||
chunk = s.Append("paragraph")
|
||||
chunk.Style = style
|
||||
|
||||
div.Add(s)
|
||||
|
||||
@ -97,7 +100,7 @@ func TestDivInline(t *testing.T) {
|
||||
c.NewPage()
|
||||
|
||||
// Draw section title.
|
||||
p := NewParagraph("Inline division component")
|
||||
p := c.NewParagraph("Inline division component")
|
||||
p.SetMargins(0, 0, 20, 10)
|
||||
p.SetFont(fontBold)
|
||||
|
||||
@ -107,46 +110,51 @@ func TestDivInline(t *testing.T) {
|
||||
}
|
||||
|
||||
// Draw division.
|
||||
div := NewDivision()
|
||||
div := c.NewDivision()
|
||||
div.SetInline(true)
|
||||
|
||||
if !div.Inline() {
|
||||
t.Fatal("Fail: Incorrect inline mode value")
|
||||
}
|
||||
|
||||
p = NewParagraph("Components are stacked both vertically ")
|
||||
p = c.NewParagraph("Components are stacked both vertically ")
|
||||
p.SetEnableWrap(false)
|
||||
p.SetFont(fontRegular)
|
||||
div.Add(p)
|
||||
|
||||
p = NewParagraph("and horizontally. ")
|
||||
p = c.NewParagraph("and horizontally. ")
|
||||
p.SetEnableWrap(false)
|
||||
p.SetFont(fontBold)
|
||||
div.Add(p)
|
||||
|
||||
p = NewParagraph("Only if they fit right!")
|
||||
p = c.NewParagraph("Only if they fit right!")
|
||||
p.SetEnableWrap(false)
|
||||
p.SetFont(fontRegular)
|
||||
div.Add(p)
|
||||
|
||||
p = NewParagraph("This one did not fit in the available line space. ")
|
||||
p = c.NewParagraph("This one did not fit in the available line space. ")
|
||||
p.SetEnableWrap(false)
|
||||
p.SetFont(fontBold)
|
||||
div.Add(p)
|
||||
|
||||
// Add styled paragraph
|
||||
style := NewTextStyle()
|
||||
style := c.NewTextStyle()
|
||||
style.Color = ColorRGBFrom8bit(0, 0, 255)
|
||||
|
||||
s := NewStyledParagraph("This styled paragraph should ", style)
|
||||
s := c.NewStyledParagraph()
|
||||
s.SetEnableWrap(false)
|
||||
|
||||
chunk := s.Append("This styled paragraph should ")
|
||||
chunk.Style = style
|
||||
|
||||
style.Color = ColorRGBFrom8bit(255, 0, 0)
|
||||
s.Append("fit", style)
|
||||
chunk = s.Append("fit")
|
||||
chunk.Style = style
|
||||
|
||||
style.Color = ColorRGBFrom8bit(0, 255, 0)
|
||||
style.Font = fontBold
|
||||
s.Append(" in.", style)
|
||||
chunk = s.Append(" in.")
|
||||
chunk.Style = style
|
||||
|
||||
div.Add(s)
|
||||
|
||||
@ -170,7 +178,7 @@ func TestDivNumberMatrix(t *testing.T) {
|
||||
c.NewPage()
|
||||
|
||||
// Draw section title.
|
||||
p := NewParagraph("A list of numbers in an inline division")
|
||||
p := c.NewParagraph("A list of numbers in an inline division")
|
||||
p.SetMargins(0, 0, 20, 10)
|
||||
p.SetFont(fontBold)
|
||||
|
||||
@ -180,7 +188,7 @@ func TestDivNumberMatrix(t *testing.T) {
|
||||
}
|
||||
|
||||
// Draw division.
|
||||
div := NewDivision()
|
||||
div := c.NewDivision()
|
||||
div.SetInline(true)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
@ -188,7 +196,7 @@ func TestDivNumberMatrix(t *testing.T) {
|
||||
g := byte(seed.Intn(200))
|
||||
b := byte(seed.Intn(200))
|
||||
|
||||
p := NewParagraph(strconv.Itoa(i) + " ")
|
||||
p := c.NewParagraph(strconv.Itoa(i) + " ")
|
||||
p.SetEnableWrap(false)
|
||||
p.SetColor(ColorRGBFrom8bit(r, g, b))
|
||||
|
||||
@ -221,7 +229,7 @@ func TestDivRandomSequences(t *testing.T) {
|
||||
c.NewPage()
|
||||
|
||||
// Draw section title.
|
||||
p := NewParagraph("Inline division of random sequences on multiple pages")
|
||||
p := c.NewParagraph("Inline division of random sequences on multiple pages")
|
||||
p.SetMargins(0, 0, 20, 10)
|
||||
p.SetFont(fontBold)
|
||||
|
||||
@ -231,10 +239,10 @@ func TestDivRandomSequences(t *testing.T) {
|
||||
}
|
||||
|
||||
// Draw division.
|
||||
div := NewDivision()
|
||||
div := c.NewDivision()
|
||||
div.SetInline(true)
|
||||
|
||||
style := NewTextStyle()
|
||||
style := c.NewTextStyle()
|
||||
|
||||
for i := 0; i < 350; i++ {
|
||||
r := byte(seed.Intn(200))
|
||||
@ -245,7 +253,7 @@ func TestDivRandomSequences(t *testing.T) {
|
||||
fontSize := float64(11 + seed.Intn(3))
|
||||
|
||||
if seed.Intn(2)%2 == 0 {
|
||||
p := NewParagraph(word)
|
||||
p := c.NewParagraph(word)
|
||||
p.SetEnableWrap(false)
|
||||
p.SetColor(ColorRGBFrom8bit(r, g, b))
|
||||
p.SetFontSize(fontSize)
|
||||
@ -267,8 +275,12 @@ func TestDivRandomSequences(t *testing.T) {
|
||||
style.Font = fontRegular
|
||||
}
|
||||
|
||||
s := NewStyledParagraph(word, style)
|
||||
s := c.NewStyledParagraph()
|
||||
s.SetEnableWrap(false)
|
||||
|
||||
chunk := s.Append(word)
|
||||
chunk.Style = style
|
||||
|
||||
div.Add(s)
|
||||
}
|
||||
}
|
||||
@ -293,7 +305,7 @@ func TestTableDivisions(t *testing.T) {
|
||||
c.NewPage()
|
||||
|
||||
// Draw section title.
|
||||
p := NewParagraph("Table containing division components")
|
||||
p := c.NewParagraph("Table containing division components")
|
||||
p.SetMargins(0, 0, 20, 10)
|
||||
p.SetFont(fontBold)
|
||||
|
||||
@ -302,17 +314,17 @@ func TestTableDivisions(t *testing.T) {
|
||||
t.Fatalf("Error drawing: %v", err)
|
||||
}
|
||||
|
||||
table := NewTable(2)
|
||||
table := c.NewTable(2)
|
||||
table.SetColumnWidths(0.35, 0.65)
|
||||
|
||||
// Add regular division to table.
|
||||
divRegular := NewDivision()
|
||||
divRegular := c.NewDivision()
|
||||
|
||||
p = NewParagraph("Components are stacked vertically ")
|
||||
p = c.NewParagraph("Components are stacked vertically ")
|
||||
p.SetFont(fontRegular)
|
||||
divRegular.Add(p)
|
||||
|
||||
p = NewParagraph("but not horizontally")
|
||||
p = c.NewParagraph("but not horizontally")
|
||||
p.SetFont(fontBold)
|
||||
divRegular.Add(p)
|
||||
|
||||
@ -321,25 +333,25 @@ func TestTableDivisions(t *testing.T) {
|
||||
cell.SetContent(divRegular)
|
||||
|
||||
// Add inline division to table.
|
||||
divInline := NewDivision()
|
||||
divInline := c.NewDivision()
|
||||
divInline.SetInline(true)
|
||||
|
||||
p = NewParagraph("Components are stacked vertically ")
|
||||
p = c.NewParagraph("Components are stacked vertically ")
|
||||
p.SetEnableWrap(false)
|
||||
p.SetFont(fontRegular)
|
||||
divInline.Add(p)
|
||||
|
||||
p = NewParagraph("and horizontally. ")
|
||||
p = c.NewParagraph("and horizontally. ")
|
||||
p.SetEnableWrap(false)
|
||||
p.SetFont(fontBold)
|
||||
divInline.Add(p)
|
||||
|
||||
p = NewParagraph("Only if they fit!")
|
||||
p = c.NewParagraph("Only if they fit!")
|
||||
p.SetEnableWrap(false)
|
||||
p.SetFont(fontRegular)
|
||||
divInline.Add(p)
|
||||
|
||||
p = NewParagraph("This one did not fit in the available line space")
|
||||
p = c.NewParagraph("This one did not fit in the available line space")
|
||||
p.SetEnableWrap(false)
|
||||
p.SetFont(fontBold)
|
||||
divInline.Add(p)
|
||||
|
@ -23,8 +23,8 @@ type Ellipse struct {
|
||||
borderWidth float64
|
||||
}
|
||||
|
||||
// NewEllipse creates a new ellipse centered at (xc,yc) with a width and height specified.
|
||||
func NewEllipse(xc, yc, width, height float64) *Ellipse {
|
||||
// newEllipse creates a new ellipse centered at (xc,yc) with a width and height specified.
|
||||
func newEllipse(xc, yc, width, height float64) *Ellipse {
|
||||
ell := &Ellipse{}
|
||||
|
||||
ell.xc = xc
|
||||
|
@ -22,8 +22,8 @@ type FilledCurve struct {
|
||||
borderColor *pdf.PdfColorDeviceRGB
|
||||
}
|
||||
|
||||
// NewFilledCurve returns a instance of filled curve.
|
||||
func NewFilledCurve() *FilledCurve {
|
||||
// newFilledCurve returns a instance of filled curve.
|
||||
func newFilledCurve() *FilledCurve {
|
||||
curve := FilledCurve{}
|
||||
curve.curves = []draw.CubicBezierCurve{}
|
||||
return &curve
|
||||
|
@ -16,7 +16,9 @@ func CreateFillCurve(x0, y0, x1, y1, x2, y2, x3, y3 float64) draw.CubicBezierCur
|
||||
}
|
||||
|
||||
func TestNewFilledCurve(t *testing.T) {
|
||||
filledCurve := NewFilledCurve()
|
||||
creator := New()
|
||||
|
||||
filledCurve := creator.NewFilledCurve()
|
||||
filledCurve.FillEnabled = true
|
||||
filledCurve.BorderEnabled = true
|
||||
filledCurve.BorderWidth = 2
|
||||
@ -34,7 +36,6 @@ func TestNewFilledCurve(t *testing.T) {
|
||||
// Leaf
|
||||
filledCurve.AppendCurve(CreateFillCurve(300, 300, 290, 350, 295, 370, 300, 390))
|
||||
|
||||
creator := New()
|
||||
creator.NewPage()
|
||||
creator.Draw(filledCurve)
|
||||
|
||||
|
@ -52,8 +52,8 @@ type Image struct {
|
||||
encoder core.StreamEncoder
|
||||
}
|
||||
|
||||
// NewImage create a new image from a unidoc image (model.Image).
|
||||
func NewImage(img *model.Image) (*Image, error) {
|
||||
// newImage create a new image from a unidoc image (model.Image).
|
||||
func newImage(img *model.Image) (*Image, error) {
|
||||
image := &Image{}
|
||||
image.img = img
|
||||
|
||||
@ -70,8 +70,8 @@ func NewImage(img *model.Image) (*Image, error) {
|
||||
return image, nil
|
||||
}
|
||||
|
||||
// NewImageFromData creates an Image from image data.
|
||||
func NewImageFromData(data []byte) (*Image, error) {
|
||||
// newImageFromData creates an Image from image data.
|
||||
func newImageFromData(data []byte) (*Image, error) {
|
||||
imgReader := bytes.NewReader(data)
|
||||
|
||||
// Load the image with default handler.
|
||||
@ -81,17 +81,17 @@ func NewImageFromData(data []byte) (*Image, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewImage(img)
|
||||
return newImage(img)
|
||||
}
|
||||
|
||||
// NewImageFromFile creates an Image from a file.
|
||||
func NewImageFromFile(path string) (*Image, error) {
|
||||
// newImageFromFile creates an Image from a file.
|
||||
func newImageFromFile(path string) (*Image, error) {
|
||||
imgData, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img, err := NewImageFromData(imgData)
|
||||
img, err := newImageFromData(imgData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -99,14 +99,14 @@ func NewImageFromFile(path string) (*Image, error) {
|
||||
return img, nil
|
||||
}
|
||||
|
||||
// NewImageFromGoImage creates an Image from a go image.Image datastructure.
|
||||
func NewImageFromGoImage(goimg goimage.Image) (*Image, error) {
|
||||
// newImageFromGoImage creates an Image from a go image.Image data structure.
|
||||
func newImageFromGoImage(goimg goimage.Image) (*Image, error) {
|
||||
img, err := model.ImageHandling.NewImageFromGoImage(goimg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewImage(img)
|
||||
return newImage(img)
|
||||
}
|
||||
|
||||
// SetEncoder sets the encoding/compression mechanism for the image.
|
||||
|
@ -24,8 +24,8 @@ type Line struct {
|
||||
lineWidth float64
|
||||
}
|
||||
|
||||
// NewLine creates a new Line with default parameters between (x1,y1) to (x2,y2).
|
||||
func NewLine(x1, y1, x2, y2 float64) *Line {
|
||||
// newLine creates a new Line with default parameters between (x1,y1) to (x2,y2).
|
||||
func newLine(x1, y1, x2, y2 float64) *Line {
|
||||
l := &Line{}
|
||||
|
||||
l.x1 = x1
|
||||
|
@ -4,8 +4,8 @@ package creator
|
||||
type PageBreak struct {
|
||||
}
|
||||
|
||||
// NewPageBreak create a new page break.
|
||||
func NewPageBreak() *PageBreak {
|
||||
// newPageBreak create a new page break.
|
||||
func newPageBreak() *PageBreak {
|
||||
return &PageBreak{}
|
||||
}
|
||||
|
||||
|
@ -66,9 +66,9 @@ type Paragraph struct {
|
||||
textLines []string
|
||||
}
|
||||
|
||||
// NewParagraph create a new text paragraph. Uses default parameters: Helvetica, WinAnsiEncoding and
|
||||
// newParagraph create a new text paragraph. Uses default parameters: Helvetica, WinAnsiEncoding and
|
||||
// wrap enabled with a wrap width of 100 points.
|
||||
func NewParagraph(text string) *Paragraph {
|
||||
func newParagraph(text string, style TextStyle) *Paragraph {
|
||||
p := &Paragraph{}
|
||||
p.text = text
|
||||
|
||||
@ -84,7 +84,6 @@ func NewParagraph(text string) *Paragraph {
|
||||
p.lineHeight = 1.0
|
||||
|
||||
// TODO: Can we wrap intellectually, only if given width is known?
|
||||
|
||||
p.enableWrap = true
|
||||
p.defaultWrap = true
|
||||
p.SetColor(ColorRGBFrom8bit(0, 0, 0))
|
||||
|
@ -23,8 +23,8 @@ type Rectangle struct {
|
||||
borderWidth float64
|
||||
}
|
||||
|
||||
// NewRectangle creates a new Rectangle with default parameters with left corner at (x,y) and width, height as specified.
|
||||
func NewRectangle(x, y, width, height float64) *Rectangle {
|
||||
// newRectangle creates a new Rectangle with default parameters with left corner at (x,y) and width, height as specified.
|
||||
func newRectangle(x, y, width, height float64) *Rectangle {
|
||||
rect := &Rectangle{}
|
||||
|
||||
rect.x = x
|
||||
|
@ -14,21 +14,17 @@ import (
|
||||
"github.com/unidoc/unidoc/common"
|
||||
"github.com/unidoc/unidoc/pdf/contentstream"
|
||||
"github.com/unidoc/unidoc/pdf/core"
|
||||
"github.com/unidoc/unidoc/pdf/model/textencoding"
|
||||
)
|
||||
|
||||
// StyledParagraph represents text drawn with a specified font and can wrap across lines and pages.
|
||||
// By default occupies the available width in the drawing context.
|
||||
type StyledParagraph struct {
|
||||
// Text chunks with styles that compose the paragraph.
|
||||
chunks []TextChunk
|
||||
chunks []*TextChunk
|
||||
|
||||
// Style used for the paragraph for spacing and offsets.
|
||||
defaultStyle TextStyle
|
||||
|
||||
// The text encoder which can convert the text (as runes) into a series of glyphs and get character metrics.
|
||||
encoder textencoding.TextEncoder
|
||||
|
||||
// Text alignment: Align left/right/center/justify.
|
||||
alignment TextAlignment
|
||||
|
||||
@ -62,25 +58,18 @@ type StyledParagraph struct {
|
||||
scaleY float64
|
||||
|
||||
// Text chunk lines after wrapping to available width.
|
||||
lines [][]TextChunk
|
||||
lines [][]*TextChunk
|
||||
|
||||
// Before render callback.
|
||||
beforeRender func(p *StyledParagraph, ctx DrawContext)
|
||||
}
|
||||
|
||||
// NewStyledParagraph creates a new styled paragraph.
|
||||
// Uses default parameters: Helvetica, WinAnsiEncoding and wrap enabled
|
||||
// with a wrap width of 100 points.
|
||||
func NewStyledParagraph(text string, style TextStyle) *StyledParagraph {
|
||||
// newStyledParagraph creates a new styled paragraph.
|
||||
func newStyledParagraph(style TextStyle) *StyledParagraph {
|
||||
// TODO: Can we wrap intellectually, only if given width is known?
|
||||
p := &StyledParagraph{
|
||||
chunks: []TextChunk{
|
||||
TextChunk{
|
||||
Text: text,
|
||||
Style: style,
|
||||
},
|
||||
},
|
||||
defaultStyle: NewTextStyle(),
|
||||
chunks: []*TextChunk{},
|
||||
defaultStyle: style,
|
||||
lineHeight: 1.0,
|
||||
alignment: TextAlignmentLeft,
|
||||
enableWrap: true,
|
||||
@ -91,44 +80,43 @@ func NewStyledParagraph(text string, style TextStyle) *StyledParagraph {
|
||||
positioning: positionRelative,
|
||||
}
|
||||
|
||||
p.SetEncoder(textencoding.NewWinAnsiTextEncoder())
|
||||
return p
|
||||
}
|
||||
|
||||
// Append adds a new text chunk with a specified style to the paragraph.
|
||||
func (p *StyledParagraph) Append(text string, style TextStyle) {
|
||||
chunk := TextChunk{
|
||||
// Append adds a new text chunk to the paragraph.
|
||||
func (p *StyledParagraph) Append(text string) *TextChunk {
|
||||
chunk := &TextChunk{
|
||||
Text: text,
|
||||
Style: style,
|
||||
Style: p.defaultStyle,
|
||||
}
|
||||
chunk.Style.Font.SetEncoder(p.encoder)
|
||||
|
||||
p.chunks = append(p.chunks, chunk)
|
||||
p.wrapText()
|
||||
|
||||
return chunk
|
||||
}
|
||||
|
||||
// Insert adds a new text chunk at the specified position in the paragraph.
|
||||
func (p *StyledParagraph) Insert(index uint, text string, style TextStyle) {
|
||||
func (p *StyledParagraph) Insert(index uint, text string) *TextChunk {
|
||||
l := uint(len(p.chunks))
|
||||
if index > l {
|
||||
index = l
|
||||
}
|
||||
|
||||
chunk := TextChunk{
|
||||
chunk := &TextChunk{
|
||||
Text: text,
|
||||
Style: style,
|
||||
Style: p.defaultStyle,
|
||||
}
|
||||
chunk.Style.Font.SetEncoder(p.encoder)
|
||||
|
||||
p.chunks = append(p.chunks[:index], append([]TextChunk{chunk}, p.chunks[index:]...)...)
|
||||
p.chunks = append(p.chunks[:index], append([]*TextChunk{chunk}, p.chunks[index:]...)...)
|
||||
p.wrapText()
|
||||
|
||||
return chunk
|
||||
}
|
||||
|
||||
// Reset sets the entire text and also the style of the paragraph
|
||||
// to those specified. It behaves as if the paragraph was a new one.
|
||||
func (p *StyledParagraph) Reset(text string, style TextStyle) {
|
||||
p.chunks = []TextChunk{}
|
||||
p.Append(text, style)
|
||||
// Reset removes all the text chunks the paragraph contains.
|
||||
func (p *StyledParagraph) Reset() {
|
||||
p.chunks = []*TextChunk{}
|
||||
}
|
||||
|
||||
// SetTextAlignment sets the horizontal alignment of the text within the space provided.
|
||||
@ -136,18 +124,6 @@ func (p *StyledParagraph) SetTextAlignment(align TextAlignment) {
|
||||
p.alignment = align
|
||||
}
|
||||
|
||||
// SetEncoder sets the text encoding.
|
||||
func (p *StyledParagraph) SetEncoder(encoder textencoding.TextEncoder) {
|
||||
p.encoder = encoder
|
||||
p.defaultStyle.Font.SetEncoder(encoder)
|
||||
|
||||
// Sync with the text font too.
|
||||
// XXX/FIXME: Keep in 1 place only.
|
||||
for _, chunk := range p.chunks {
|
||||
chunk.Style.Font.SetEncoder(encoder)
|
||||
}
|
||||
}
|
||||
|
||||
// SetLineHeight sets the line height (1.0 default).
|
||||
func (p *StyledParagraph) SetLineHeight(lineheight float64) {
|
||||
p.lineHeight = lineheight
|
||||
@ -230,7 +206,7 @@ func (p *StyledParagraph) getTextWidth() float64 {
|
||||
style := &chunk.Style
|
||||
|
||||
for _, rune := range chunk.Text {
|
||||
glyph, found := p.encoder.RuneToGlyph(rune)
|
||||
glyph, found := style.Font.Encoder().RuneToGlyph(rune)
|
||||
if !found {
|
||||
common.Log.Debug("Error! Glyph not found for rune: %s\n", rune)
|
||||
|
||||
@ -259,13 +235,13 @@ func (p *StyledParagraph) getTextWidth() float64 {
|
||||
}
|
||||
|
||||
// getTextLineWidth calculates the text width of a provided collection of text chunks.
|
||||
func (p *StyledParagraph) getTextLineWidth(line []TextChunk) float64 {
|
||||
func (p *StyledParagraph) getTextLineWidth(line []*TextChunk) float64 {
|
||||
var width float64
|
||||
for _, chunk := range line {
|
||||
style := &chunk.Style
|
||||
|
||||
for _, r := range chunk.Text {
|
||||
glyph, found := p.encoder.RuneToGlyph(r)
|
||||
glyph, found := style.Font.Encoder().RuneToGlyph(r)
|
||||
if !found {
|
||||
common.Log.Debug("Error! Glyph not found for rune: %s\n", r)
|
||||
|
||||
@ -328,12 +304,12 @@ func (p *StyledParagraph) getTextHeight() float64 {
|
||||
// XXX/TODO: Consider the Knuth/Plass algorithm or an alternative.
|
||||
func (p *StyledParagraph) wrapText() error {
|
||||
if !p.enableWrap || int(p.wrapWidth) <= 0 {
|
||||
p.lines = [][]TextChunk{p.chunks}
|
||||
p.lines = [][]*TextChunk{p.chunks}
|
||||
return nil
|
||||
}
|
||||
|
||||
p.lines = [][]TextChunk{}
|
||||
var line []TextChunk
|
||||
p.lines = [][]*TextChunk{}
|
||||
var line []*TextChunk
|
||||
var lineWidth float64
|
||||
|
||||
for _, chunk := range p.chunks {
|
||||
@ -344,7 +320,7 @@ func (p *StyledParagraph) wrapText() error {
|
||||
var widths []float64
|
||||
|
||||
for _, r := range chunk.Text {
|
||||
glyph, found := p.encoder.RuneToGlyph(r)
|
||||
glyph, found := style.Font.Encoder().RuneToGlyph(r)
|
||||
if !found {
|
||||
common.Log.Debug("Error! Glyph not found for rune: %v\n", r)
|
||||
|
||||
@ -355,12 +331,12 @@ func (p *StyledParagraph) wrapText() error {
|
||||
// newline wrapping.
|
||||
if glyph == "controlLF" {
|
||||
// moves to next line.
|
||||
line = append(line, TextChunk{
|
||||
line = append(line, &TextChunk{
|
||||
Text: strings.TrimRightFunc(string(part), unicode.IsSpace),
|
||||
Style: style,
|
||||
})
|
||||
p.lines = append(p.lines, line)
|
||||
line = []TextChunk{}
|
||||
line = []*TextChunk{}
|
||||
|
||||
lineWidth = 0
|
||||
part = []rune{}
|
||||
@ -413,12 +389,12 @@ func (p *StyledParagraph) wrapText() error {
|
||||
widths = []float64{w}
|
||||
}
|
||||
|
||||
line = append(line, TextChunk{
|
||||
line = append(line, &TextChunk{
|
||||
Text: strings.TrimRightFunc(string(text), unicode.IsSpace),
|
||||
Style: style,
|
||||
})
|
||||
p.lines = append(p.lines, line)
|
||||
line = []TextChunk{}
|
||||
line = []*TextChunk{}
|
||||
} else {
|
||||
lineWidth += w
|
||||
part = append(part, r)
|
||||
@ -428,7 +404,7 @@ func (p *StyledParagraph) wrapText() error {
|
||||
}
|
||||
|
||||
if len(part) > 0 {
|
||||
line = append(line, TextChunk{
|
||||
line = append(line, &TextChunk{
|
||||
Text: string(part),
|
||||
Style: style,
|
||||
})
|
||||
@ -588,7 +564,7 @@ func drawStyledParagraphOnBlock(blk *Block, p *StyledParagraph, ctx DrawContext)
|
||||
|
||||
var chunkSpaces uint
|
||||
for _, r := range chunk.Text {
|
||||
glyph, found := p.encoder.RuneToGlyph(r)
|
||||
glyph, found := style.Font.Encoder().RuneToGlyph(r)
|
||||
if !found {
|
||||
common.Log.Debug("Rune 0x%x not supported by text encoder", r)
|
||||
return ctx, errors.New("Unsupported rune in text encoding")
|
||||
@ -661,7 +637,7 @@ func drawStyledParagraphOnBlock(blk *Block, p *StyledParagraph, ctx DrawContext)
|
||||
|
||||
var encStr []byte
|
||||
for _, rn := range chunk.Text {
|
||||
glyph, found := p.encoder.RuneToGlyph(rn)
|
||||
glyph, found := style.Font.Encoder().RuneToGlyph(rn)
|
||||
if !found {
|
||||
common.Log.Debug("Rune 0x%x not supported by text encoder", r)
|
||||
return ctx, errors.New("Unsupported rune in text encoding")
|
||||
@ -686,7 +662,7 @@ func drawStyledParagraphOnBlock(blk *Block, p *StyledParagraph, ctx DrawContext)
|
||||
Add_TL(fontSize * p.lineHeight).
|
||||
Add_TJ([]core.PdfObject{core.MakeFloat(-spaceWidth)}...)
|
||||
} else {
|
||||
encStr = append(encStr, p.encoder.Encode(string(rn))...)
|
||||
encStr = append(encStr, style.Font.Encoder().Encode(string(rn))...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
c.NewPage()
|
||||
|
||||
// Draw section title.
|
||||
p := NewParagraph("Regular paragraph vs styled paragraph (should be identical)")
|
||||
p := c.NewParagraph("Regular paragraph vs styled paragraph (should be identical)")
|
||||
p.SetMargins(0, 0, 20, 10)
|
||||
p.SetFont(fontBold)
|
||||
|
||||
@ -28,11 +28,11 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
t.Fatalf("Error drawing: %v", err)
|
||||
}
|
||||
|
||||
table := NewTable(2)
|
||||
table := c.NewTable(2)
|
||||
table.SetColumnWidths(0.5, 0.5)
|
||||
|
||||
// Add regular paragraph to table.
|
||||
p = NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
p = c.NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
p.SetMargins(10, 10, 5, 10)
|
||||
p.SetFont(fontBold)
|
||||
p.SetEnableWrap(true)
|
||||
@ -43,20 +43,23 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
cell.SetContent(p)
|
||||
|
||||
// Add styled paragraph to table.
|
||||
style := NewTextStyle()
|
||||
style := c.NewTextStyle()
|
||||
style.Font = fontBold
|
||||
|
||||
s := NewStyledParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.", style)
|
||||
s := c.NewStyledParagraph()
|
||||
s.SetMargins(10, 10, 5, 10)
|
||||
s.SetEnableWrap(true)
|
||||
s.SetTextAlignment(TextAlignmentLeft)
|
||||
|
||||
chunk := s.Append("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetContent(s)
|
||||
|
||||
// Add regular paragraph to table.
|
||||
p = NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
p = c.NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
p.SetMargins(10, 10, 5, 10)
|
||||
p.SetFont(fontRegular)
|
||||
p.SetEnableWrap(true)
|
||||
@ -71,17 +74,20 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
style.Font = fontRegular
|
||||
style.Color = ColorRGBFrom8bit(0, 0, 255)
|
||||
|
||||
s = NewStyledParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.", style)
|
||||
s = c.NewStyledParagraph()
|
||||
s.SetMargins(10, 10, 5, 10)
|
||||
s.SetEnableWrap(true)
|
||||
s.SetTextAlignment(TextAlignmentJustify)
|
||||
|
||||
chunk = s.Append("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetContent(s)
|
||||
|
||||
// Add regular paragraph to table.
|
||||
p = NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
p = c.NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
p.SetMargins(10, 10, 5, 10)
|
||||
p.SetFont(fontRegular)
|
||||
p.SetEnableWrap(true)
|
||||
@ -95,17 +101,20 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
style.Font = fontRegular
|
||||
style.Color = ColorRGBFrom8bit(0, 0, 0)
|
||||
|
||||
s = NewStyledParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.", style)
|
||||
s = c.NewStyledParagraph()
|
||||
s.SetMargins(10, 10, 5, 10)
|
||||
s.SetEnableWrap(true)
|
||||
s.SetTextAlignment(TextAlignmentRight)
|
||||
|
||||
chunk = s.Append("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetContent(s)
|
||||
|
||||
// Add regular paragraph to table.
|
||||
p = NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
p = c.NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
p.SetMargins(10, 10, 5, 10)
|
||||
p.SetFont(fontBold)
|
||||
p.SetEnableWrap(true)
|
||||
@ -119,20 +128,23 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
style.Font = fontBold
|
||||
style.Color = ColorRGBFrom8bit(0, 0, 0)
|
||||
|
||||
s = NewStyledParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.", style)
|
||||
s = c.NewStyledParagraph()
|
||||
s.SetMargins(10, 10, 5, 10)
|
||||
s.SetEnableWrap(true)
|
||||
s.SetTextAlignment(TextAlignmentCenter)
|
||||
|
||||
chunk = s.Append("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetContent(s)
|
||||
|
||||
// Test table cell alignment.
|
||||
style = NewTextStyle()
|
||||
style = c.NewTextStyle()
|
||||
|
||||
// Test left alignment with paragraph wrapping enabled.
|
||||
p = NewParagraph("Wrap enabled. This text should be left aligned.")
|
||||
p = c.NewParagraph("Wrap enabled. This text should be left aligned.")
|
||||
p.SetEnableWrap(true)
|
||||
|
||||
cell = table.NewCell()
|
||||
@ -140,16 +152,19 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentLeft)
|
||||
cell.SetContent(p)
|
||||
|
||||
s = NewStyledParagraph("Wrap enabled. This text should be left aligned.", style)
|
||||
s = c.NewStyledParagraph()
|
||||
s.SetEnableWrap(true)
|
||||
|
||||
chunk = s.Append("Wrap enabled. This text should be left aligned.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentLeft)
|
||||
cell.SetContent(s)
|
||||
|
||||
// Test left alignment with paragraph wrapping disabled.
|
||||
p = NewParagraph("Wrap disabled. This text should be left aligned.")
|
||||
p = c.NewParagraph("Wrap disabled. This text should be left aligned.")
|
||||
p.SetEnableWrap(false)
|
||||
|
||||
cell = table.NewCell()
|
||||
@ -157,16 +172,19 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentLeft)
|
||||
cell.SetContent(p)
|
||||
|
||||
s = NewStyledParagraph("Wrap disabled. This text should be left aligned.", style)
|
||||
s = c.NewStyledParagraph()
|
||||
s.SetEnableWrap(false)
|
||||
|
||||
chunk = s.Append("Wrap disabled. This text should be left aligned.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentLeft)
|
||||
cell.SetContent(s)
|
||||
|
||||
// Test center alignment with paragraph wrapping enabled.
|
||||
p = NewParagraph("Wrap enabled. This text should be center aligned.")
|
||||
p = c.NewParagraph("Wrap enabled. This text should be center aligned.")
|
||||
p.SetEnableWrap(true)
|
||||
|
||||
cell = table.NewCell()
|
||||
@ -174,16 +192,19 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentCenter)
|
||||
cell.SetContent(p)
|
||||
|
||||
s = NewStyledParagraph("Wrap enabled. This text should be center aligned.", style)
|
||||
s = c.NewStyledParagraph()
|
||||
s.SetEnableWrap(true)
|
||||
|
||||
chunk = s.Append("Wrap enabled. This text should be center aligned.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentCenter)
|
||||
cell.SetContent(s)
|
||||
|
||||
// Test center alignment with paragraph wrapping disabled.
|
||||
p = NewParagraph("Wrap disabled. This text should be center aligned.")
|
||||
p = c.NewParagraph("Wrap disabled. This text should be center aligned.")
|
||||
p.SetEnableWrap(false)
|
||||
|
||||
cell = table.NewCell()
|
||||
@ -191,16 +212,19 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentCenter)
|
||||
cell.SetContent(p)
|
||||
|
||||
s = NewStyledParagraph("Wrap disabled. This text should be center aligned.", style)
|
||||
s = c.NewStyledParagraph()
|
||||
s.SetEnableWrap(false)
|
||||
|
||||
chunk = s.Append("Wrap disabled. This text should be center aligned.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentCenter)
|
||||
cell.SetContent(s)
|
||||
|
||||
// Test right alignment with paragraph wrapping enabled.
|
||||
p = NewParagraph("Wrap enabled. This text should be right aligned.")
|
||||
p = c.NewParagraph("Wrap enabled. This text should be right aligned.")
|
||||
p.SetEnableWrap(true)
|
||||
|
||||
cell = table.NewCell()
|
||||
@ -208,16 +232,19 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentRight)
|
||||
cell.SetContent(p)
|
||||
|
||||
s = NewStyledParagraph("Wrap enabled. This text should be right aligned.", style)
|
||||
s = c.NewStyledParagraph()
|
||||
s.SetEnableWrap(true)
|
||||
|
||||
chunk = s.Append("Wrap enabled. This text should be right aligned.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentRight)
|
||||
cell.SetContent(s)
|
||||
|
||||
// Test right alignment with paragraph wrapping disabled.
|
||||
p = NewParagraph("Wrap disabled. This text should be right aligned.")
|
||||
p = c.NewParagraph("Wrap disabled. This text should be right aligned.")
|
||||
p.SetEnableWrap(false)
|
||||
|
||||
cell = table.NewCell()
|
||||
@ -225,9 +252,12 @@ func TestParagraphRegularVsStyled(t *testing.T) {
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentRight)
|
||||
cell.SetContent(p)
|
||||
|
||||
s = NewStyledParagraph("Wrap disabled. This text should be right aligned.", style)
|
||||
s = c.NewStyledParagraph()
|
||||
s.SetEnableWrap(false)
|
||||
|
||||
chunk = s.Append("Wrap disabled. This text should be right aligned.")
|
||||
chunk.Style = style
|
||||
|
||||
cell = table.NewCell()
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentRight)
|
||||
@ -255,7 +285,7 @@ func TestStyledParagraph(t *testing.T) {
|
||||
c.NewPage()
|
||||
|
||||
// Draw section title.
|
||||
p := NewParagraph("Styled paragraph")
|
||||
p := c.NewParagraph("Styled paragraph")
|
||||
p.SetMargins(0, 0, 20, 10)
|
||||
p.SetFont(fontBold)
|
||||
|
||||
@ -264,38 +294,47 @@ func TestStyledParagraph(t *testing.T) {
|
||||
t.Fatalf("Error drawing: %v", err)
|
||||
}
|
||||
|
||||
style := NewTextStyle()
|
||||
style := c.NewTextStyle()
|
||||
style.Font = fontRegular
|
||||
|
||||
s := NewStyledParagraph("This is a paragraph ", style)
|
||||
s := c.NewStyledParagraph()
|
||||
s.SetEnableWrap(true)
|
||||
s.SetTextAlignment(TextAlignmentJustify)
|
||||
s.SetMargins(0, 0, 10, 0)
|
||||
|
||||
chunk := s.Append("This is a paragraph ")
|
||||
chunk.Style = style
|
||||
|
||||
style.Color = ColorRGBFrom8bit(255, 0, 0)
|
||||
s.Append("with different colors ", style)
|
||||
chunk = s.Append("with different colors ")
|
||||
chunk.Style = style
|
||||
|
||||
style.Color = ColorRGBFrom8bit(0, 0, 0)
|
||||
style.FontSize = 14
|
||||
s.Append("and with different font sizes ", style)
|
||||
chunk = s.Append("and with different font sizes ")
|
||||
chunk.Style = style
|
||||
|
||||
style.FontSize = 10
|
||||
style.Font = fontBold
|
||||
s.Append("and with different font styles ", style)
|
||||
chunk = s.Append("and with different font styles ")
|
||||
chunk.Style = style
|
||||
|
||||
style.Font = fontHelvetica
|
||||
style.FontSize = 13
|
||||
s.Append("and with different fonts ", style)
|
||||
chunk = s.Append("and with different fonts ")
|
||||
chunk.Style = style
|
||||
|
||||
style.Font = fontBold
|
||||
style.Color = ColorRGBFrom8bit(0, 0, 255)
|
||||
style.FontSize = 15
|
||||
s.Append("and with the changed properties all at once. ", style)
|
||||
chunk = s.Append("and with the changed properties all at once. ")
|
||||
chunk.Style = style
|
||||
|
||||
style.Color = ColorRGBFrom8bit(127, 255, 0)
|
||||
style.FontSize = 12
|
||||
style.Font = fontHelvetica
|
||||
s.Append("And maybe try a different color again.", style)
|
||||
chunk = s.Append("And maybe try a different color again.")
|
||||
chunk.Style = style
|
||||
|
||||
err = c.Draw(s)
|
||||
if err != nil {
|
||||
@ -306,13 +345,17 @@ func TestStyledParagraph(t *testing.T) {
|
||||
style.Color = ColorRGBFrom8bit(255, 0, 0)
|
||||
style.Font = fontRegular
|
||||
|
||||
s.Reset("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar. ", style)
|
||||
s.Reset()
|
||||
s.SetTextAlignment(TextAlignmentJustify)
|
||||
|
||||
chunk = s.Append("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacus viverra vitae congue eu consequat. Cras adipiscing enim eu turpis. Lectus magna fringilla urna porttitor. Condimentum id venenatis a condimentum. Quis ipsum suspendisse ultrices gravida dictum fusce. In fermentum posuere urna nec tincidunt. Dis parturient montes nascetur ridiculus mus. Pharetra diam sit amet nisl suscipit adipiscing. Proin fermentum leo vel orci porta. Id diam vel quam elementum pulvinar. ")
|
||||
chunk.Style = style
|
||||
|
||||
style.Color = ColorRGBFrom8bit(0, 0, 255)
|
||||
style.FontSize = 15
|
||||
style.Font = fontHelvetica
|
||||
s.Append("And maybe try a different color again.", style)
|
||||
chunk = s.Append("And maybe try a different color again.")
|
||||
chunk.Style = style
|
||||
|
||||
err = c.Draw(s)
|
||||
if err != nil {
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/unidoc/unidoc/common"
|
||||
"github.com/unidoc/unidoc/pdf/model"
|
||||
)
|
||||
|
||||
// Subchapter simply represents a sub chapter pertaining to a specific Chapter. It can contain
|
||||
@ -42,37 +41,30 @@ type Subchapter struct {
|
||||
toc *TOC
|
||||
}
|
||||
|
||||
// NewSubchapter creates a new Subchapter under Chapter ch with specified title.
|
||||
// newSubchapter creates a new Subchapter under Chapter ch with specified title.
|
||||
// All other parameters are set to their defaults.
|
||||
func (c *Creator) NewSubchapter(ch *Chapter, title string) *Subchapter {
|
||||
subchap := &Subchapter{}
|
||||
|
||||
func newSubchapter(ch *Chapter, title string, style TextStyle) *Subchapter {
|
||||
ch.subchapters++
|
||||
subchap.subchapterNum = ch.subchapters
|
||||
|
||||
subchap.chapterNum = ch.number
|
||||
subchap.title = title
|
||||
|
||||
heading := fmt.Sprintf("%d.%d %s", subchap.chapterNum, subchap.subchapterNum, title)
|
||||
p := NewParagraph(heading)
|
||||
|
||||
p := newParagraph(fmt.Sprintf("%d.%d %s", ch.number, ch.subchapters, title), style)
|
||||
p.SetFont(style.Font) // bold?
|
||||
p.SetFontSize(14)
|
||||
helvetica := model.NewStandard14FontMustCompile(model.Helvetica)
|
||||
p.SetFont(helvetica) // bold?
|
||||
|
||||
subchap.showNumbering = true
|
||||
subchap.includeInTOC = true
|
||||
subchapter := &Subchapter{
|
||||
subchapterNum: ch.subchapters,
|
||||
chapterNum: ch.number,
|
||||
title: title,
|
||||
showNumbering: true,
|
||||
includeInTOC: true,
|
||||
heading: p,
|
||||
contents: []Drawable{},
|
||||
toc: ch.toc,
|
||||
}
|
||||
|
||||
subchap.heading = p
|
||||
subchap.contents = []Drawable{}
|
||||
// Add subchapter to chapter.
|
||||
ch.Add(subchapter)
|
||||
|
||||
// Add subchapter to ch.
|
||||
ch.Add(subchap)
|
||||
|
||||
// Keep a reference for toc.
|
||||
subchap.toc = c.toc
|
||||
|
||||
return subchap
|
||||
return subchapter
|
||||
}
|
||||
|
||||
// SetShowNumbering sets a flag to indicate whether or not to show chapter numbers as part of title.
|
||||
|
@ -47,8 +47,8 @@ type Table struct {
|
||||
margins margins
|
||||
}
|
||||
|
||||
// NewTable create a new Table with a specified number of columns.
|
||||
func NewTable(cols int) *Table {
|
||||
// newTable create a new Table with a specified number of columns.
|
||||
func newTable(cols int) *Table {
|
||||
t := &Table{}
|
||||
t.rows = 0
|
||||
t.cols = cols
|
||||
@ -454,12 +454,19 @@ const (
|
||||
type CellBorderSide int
|
||||
|
||||
const (
|
||||
// Left side border.
|
||||
// CellBorderSideLeft adds border on the left side of the table.
|
||||
CellBorderSideLeft CellBorderSide = iota
|
||||
|
||||
// CellBorderSideRight adds a border on the right side of the table.
|
||||
CellBorderSideRight
|
||||
|
||||
// CellBorderSideTop adds a border on the top side of the table.
|
||||
CellBorderSideTop
|
||||
|
||||
// CellBorderSideBottom adds a border on the bottom side of the table.
|
||||
CellBorderSideBottom
|
||||
// Border on all sides.
|
||||
|
||||
// CellBorderSideAll adds borders on all sides of the table.
|
||||
CellBorderSideAll
|
||||
)
|
||||
|
||||
|
@ -21,7 +21,7 @@ var (
|
||||
func TestTableMultiParagraphWrapped(t *testing.T) {
|
||||
c := New()
|
||||
|
||||
pageHistoryTable := NewTable(4)
|
||||
pageHistoryTable := c.NewTable(4)
|
||||
pageHistoryTable.SetColumnWidths(0.1, 0.6, 0.15, 0.15)
|
||||
content := [][]string{
|
||||
{"1", "FullText Search Highlight the Term in Results \n\nissues 60", "120", "130"},
|
||||
@ -33,7 +33,7 @@ func TestTableMultiParagraphWrapped(t *testing.T) {
|
||||
|
||||
for _, rows := range content {
|
||||
for _, txt := range rows {
|
||||
p := NewParagraph(txt)
|
||||
p := c.NewParagraph(txt)
|
||||
p.SetFontSize(12)
|
||||
p.SetFont(fontHelvetica)
|
||||
p.SetColor(ColorBlack)
|
||||
@ -59,7 +59,7 @@ func TestTableMultiParagraphWrapped(t *testing.T) {
|
||||
func TestTableWithImage(t *testing.T) {
|
||||
c := New()
|
||||
|
||||
pageHistoryTable := NewTable(4)
|
||||
pageHistoryTable := c.NewTable(4)
|
||||
pageHistoryTable.SetColumnWidths(0.1, 0.6, 0.15, 0.15)
|
||||
content := [][]string{
|
||||
{"1", "FullText Search Highlight the Term in Results \n\nissues 60", "120", "130"},
|
||||
@ -70,7 +70,7 @@ func TestTableWithImage(t *testing.T) {
|
||||
}
|
||||
for _, rows := range content {
|
||||
for _, txt := range rows {
|
||||
p := NewParagraph(txt)
|
||||
p := c.NewParagraph(txt)
|
||||
p.SetFontSize(12)
|
||||
p.SetFont(fontHelvetica)
|
||||
p.SetColor(ColorBlack)
|
||||
@ -93,7 +93,7 @@ func TestTableWithImage(t *testing.T) {
|
||||
t.Errorf("Fail: %v\n", err)
|
||||
return
|
||||
}
|
||||
img, err := NewImageFromData(imgData)
|
||||
img, err := c.NewImageFromData(imgData)
|
||||
if err != nil {
|
||||
t.Errorf("Fail: %v\n", err)
|
||||
return
|
||||
@ -124,7 +124,7 @@ func TestTableWithImage(t *testing.T) {
|
||||
func TestTableWithDiv(t *testing.T) {
|
||||
c := New()
|
||||
|
||||
pageHistoryTable := NewTable(4)
|
||||
pageHistoryTable := c.NewTable(4)
|
||||
pageHistoryTable.SetColumnWidths(0.1, 0.6, 0.15, 0.15)
|
||||
|
||||
headings := []string{
|
||||
@ -155,7 +155,7 @@ func TestTableWithDiv(t *testing.T) {
|
||||
}
|
||||
for _, rows := range content {
|
||||
for colIdx, txt := range rows {
|
||||
p := NewParagraph(txt)
|
||||
p := c.NewParagraph(txt)
|
||||
p.SetFontSize(12)
|
||||
p.SetFont(fontHelvetica)
|
||||
p.SetColor(ColorBlack)
|
||||
@ -167,10 +167,10 @@ func TestTableWithDiv(t *testing.T) {
|
||||
}
|
||||
|
||||
// Place cell contents (header and text) inside a div.
|
||||
div := NewDivision()
|
||||
div := c.NewDivision()
|
||||
|
||||
if len(headings[colIdx]) > 0 {
|
||||
heading := NewParagraph(headings[colIdx])
|
||||
heading := c.NewParagraph(headings[colIdx])
|
||||
heading.SetFontSize(14)
|
||||
heading.SetFont(fontHelveticaBold)
|
||||
heading.SetColor(ColorRed)
|
||||
@ -203,7 +203,7 @@ func TestTableWithDiv(t *testing.T) {
|
||||
t.Errorf("Fail: %v\n", err)
|
||||
return
|
||||
}
|
||||
img, err := NewImageFromData(imgData)
|
||||
img, err := c.NewImageFromData(imgData)
|
||||
if err != nil {
|
||||
t.Errorf("Fail: %v\n", err)
|
||||
return
|
||||
|
@ -6,8 +6,7 @@
|
||||
package creator
|
||||
|
||||
import (
|
||||
"github.com/unidoc/unidoc/pdf/model/fonts"
|
||||
"github.com/unidoc/unidoc/pdf/model/textencoding"
|
||||
"github.com/unidoc/unidoc/pdf/model"
|
||||
)
|
||||
|
||||
// TextStyle is a collection of properties that can be assigned to a chunk of text.
|
||||
@ -16,19 +15,14 @@ type TextStyle struct {
|
||||
Color Color
|
||||
|
||||
// The font the text will use.
|
||||
Font fonts.Font
|
||||
Font *model.PdfFont
|
||||
|
||||
// The size of the font.
|
||||
FontSize float64
|
||||
}
|
||||
|
||||
// NewTextStyle creates a new text style object which can be used with chunks
|
||||
// of text. Uses default parameters: Helvetica, WinAnsiEncoding and wrap
|
||||
// enabled with a wrap width of 100 points.
|
||||
func NewTextStyle() TextStyle {
|
||||
font := fonts.NewFontHelvetica()
|
||||
font.SetEncoder(textencoding.NewWinAnsiTextEncoder())
|
||||
|
||||
// newTextStyle creates a new text style object using the specified font.
|
||||
func newTextStyle(font *model.PdfFont) TextStyle {
|
||||
return TextStyle{
|
||||
Color: ColorRGBFrom8bit(0, 0, 0),
|
||||
Font: font,
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
package creator
|
||||
|
||||
import "github.com/unidoc/unidoc/pdf/model/fonts"
|
||||
|
||||
// TOC represents a table of contents component.
|
||||
// It consists of a paragraph heading and a collection of
|
||||
// table of contents lines.
|
||||
@ -43,32 +41,36 @@ type TOC struct {
|
||||
|
||||
// Positioning: relative/absolute.
|
||||
positioning positioning
|
||||
|
||||
// Default style used for internal operations.
|
||||
defaultStyle TextStyle
|
||||
}
|
||||
|
||||
// NewTOC creates a new table of contents.
|
||||
func NewTOC(title string) *TOC {
|
||||
headingStyle := NewTextStyle()
|
||||
headingStyle.Font = fonts.NewFontHelveticaBold()
|
||||
// newTOC creates a new table of contents.
|
||||
func newTOC(title string, style, styleHeading TextStyle) *TOC {
|
||||
headingStyle := styleHeading
|
||||
headingStyle.FontSize = 14
|
||||
|
||||
heading := NewStyledParagraph(title, headingStyle)
|
||||
heading := newStyledParagraph(headingStyle)
|
||||
heading.SetEnableWrap(true)
|
||||
heading.SetTextAlignment(TextAlignmentLeft)
|
||||
heading.SetMargins(0, 0, 0, 5)
|
||||
|
||||
lineStyle := NewTextStyle()
|
||||
chunk := heading.Append(title)
|
||||
chunk.Style = headingStyle
|
||||
|
||||
return &TOC{
|
||||
heading: heading,
|
||||
lines: []*TOCLine{},
|
||||
lineNumberStyle: lineStyle,
|
||||
lineTitleStyle: lineStyle,
|
||||
lineSeparatorStyle: lineStyle,
|
||||
linePageStyle: lineStyle,
|
||||
lineNumberStyle: style,
|
||||
lineTitleStyle: style,
|
||||
lineSeparatorStyle: style,
|
||||
linePageStyle: style,
|
||||
lineSeparator: ".",
|
||||
lineLevelOffset: 10,
|
||||
lineMargins: margins{0, 0, 2, 2},
|
||||
positioning: positionRelative,
|
||||
defaultStyle: style,
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,12 +86,16 @@ func (t *TOC) Lines() []*TOCLine {
|
||||
|
||||
// SetHeading sets the text and the style of the heading of the TOC component.
|
||||
func (t *TOC) SetHeading(text string, style TextStyle) {
|
||||
t.heading.Reset(text, style)
|
||||
h := t.Heading()
|
||||
|
||||
h.Reset()
|
||||
chunk := h.Append(text)
|
||||
chunk.Style = style
|
||||
}
|
||||
|
||||
// Add adds a new line with the default style to the table of contents.
|
||||
func (t *TOC) Add(number, title, page string, level uint) *TOCLine {
|
||||
tl := t.AddLine(NewStyledTOCLine(
|
||||
tl := t.AddLine(newStyledTOCLine(
|
||||
TextChunk{
|
||||
Text: number,
|
||||
Style: t.lineNumberStyle,
|
||||
@ -103,6 +109,7 @@ func (t *TOC) Add(number, title, page string, level uint) *TOCLine {
|
||||
Style: t.linePageStyle,
|
||||
},
|
||||
level,
|
||||
t.defaultStyle,
|
||||
))
|
||||
|
||||
if tl == nil {
|
||||
|
@ -44,11 +44,9 @@ type TOCLine struct {
|
||||
positioning positioning
|
||||
}
|
||||
|
||||
// NewTOCLine creates a new table of contents line with the default style.
|
||||
func NewTOCLine(number, title, page string, level uint) *TOCLine {
|
||||
style := NewTextStyle()
|
||||
|
||||
return NewStyledTOCLine(
|
||||
// newTOCLine creates a new table of contents line with the default style.
|
||||
func newTOCLine(number, title, page string, level uint, style TextStyle) *TOCLine {
|
||||
return newStyledTOCLine(
|
||||
TextChunk{
|
||||
Text: number,
|
||||
Style: style,
|
||||
@ -62,14 +60,13 @@ func NewTOCLine(number, title, page string, level uint) *TOCLine {
|
||||
Style: style,
|
||||
},
|
||||
level,
|
||||
style,
|
||||
)
|
||||
}
|
||||
|
||||
// NewStyledTOCLine creates a new table of contents line with the provided style.
|
||||
func NewStyledTOCLine(number, title, page TextChunk, level uint) *TOCLine {
|
||||
style := NewTextStyle()
|
||||
|
||||
sp := NewStyledParagraph("", style)
|
||||
// newStyledTOCLine creates a new table of contents line with the provided style.
|
||||
func newStyledTOCLine(number, title, page TextChunk, level uint, style TextStyle) *TOCLine {
|
||||
sp := newStyledParagraph(style)
|
||||
sp.SetEnableWrap(true)
|
||||
sp.SetTextAlignment(TextAlignmentLeft)
|
||||
sp.SetMargins(0, 0, 2, 2)
|
||||
@ -157,19 +154,18 @@ func (tl *TOCLine) prepareParagraph(sp *StyledParagraph, ctx DrawContext) {
|
||||
page = " " + page
|
||||
}
|
||||
|
||||
sp.chunks = []TextChunk{
|
||||
tl.Number,
|
||||
TextChunk{
|
||||
sp.chunks = []*TextChunk{
|
||||
&tl.Number,
|
||||
&TextChunk{
|
||||
Text: title,
|
||||
Style: tl.Title.Style,
|
||||
},
|
||||
TextChunk{
|
||||
&TextChunk{
|
||||
Text: page,
|
||||
Style: tl.Page.Style,
|
||||
},
|
||||
}
|
||||
|
||||
sp.SetEncoder(sp.encoder)
|
||||
sp.wrapText()
|
||||
|
||||
// Insert separator.
|
||||
@ -179,12 +175,13 @@ func (tl *TOCLine) prepareParagraph(sp *StyledParagraph, ctx DrawContext) {
|
||||
}
|
||||
|
||||
availWidth := ctx.Width*1000 - sp.getTextLineWidth(sp.lines[l-1])
|
||||
sepWidth := sp.getTextLineWidth([]TextChunk{tl.Separator})
|
||||
sepWidth := sp.getTextLineWidth([]*TextChunk{&tl.Separator})
|
||||
sepCount := int(availWidth / sepWidth)
|
||||
sepText := strings.Repeat(tl.Separator.Text, sepCount)
|
||||
sepStyle := tl.Separator.Style
|
||||
|
||||
sp.Insert(2, sepText, sepStyle)
|
||||
chunk := sp.Insert(2, sepText)
|
||||
chunk.Style = sepStyle
|
||||
|
||||
// Push page numbers to the end of the line.
|
||||
availWidth = availWidth - float64(sepCount)*sepWidth
|
||||
@ -195,7 +192,9 @@ func (tl *TOCLine) prepareParagraph(sp *StyledParagraph, ctx DrawContext) {
|
||||
if spaces > 0 {
|
||||
style := sepStyle
|
||||
style.FontSize = 1
|
||||
sp.Insert(2, strings.Repeat(" ", spaces), style)
|
||||
|
||||
chunk = sp.Insert(2, strings.Repeat(" ", spaces))
|
||||
chunk.Style = style
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,17 +7,17 @@ package creator
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/unidoc/unidoc/pdf/model/fonts"
|
||||
"github.com/unidoc/unidoc/pdf/model"
|
||||
)
|
||||
|
||||
func TestTOCAdvanced(t *testing.T) {
|
||||
fontHelvetica := fonts.NewFontHelvetica()
|
||||
fontHelveticaBold := fonts.NewFontHelveticaBold()
|
||||
fontHelvetica := model.NewStandard14FontMustCompile(model.Helvetica)
|
||||
fontHelveticaBold := model.NewStandard14FontMustCompile(model.HelveticaBold)
|
||||
|
||||
c := New()
|
||||
c.NewPage()
|
||||
|
||||
toc := NewTOC("Table of Contents")
|
||||
toc := c.NewTOC("Table of Contents")
|
||||
|
||||
// Set separator and margins for all the lines.
|
||||
toc.SetLineSeparator(".")
|
||||
@ -25,7 +25,7 @@ func TestTOCAdvanced(t *testing.T) {
|
||||
toc.SetLineLevelOffset(12)
|
||||
|
||||
// Set style for all line numbers.
|
||||
style := NewTextStyle()
|
||||
style := c.NewTextStyle()
|
||||
style.Font = fontHelveticaBold
|
||||
style.Color = ColorRGBFrom8bit(100, 100, 100)
|
||||
toc.SetLineNumberStyle(style)
|
||||
|
Loading…
x
Reference in New Issue
Block a user