Merge branch 'master' into v3

This commit is contained in:
Gunnsteinn Hall 2018-08-01 22:04:27 +00:00
commit cc44dd2552
6 changed files with 173 additions and 18 deletions

View File

@ -2,12 +2,11 @@ package core
import (
"testing"
"github.com/unidoc/unidoc/common"
)
func init() {
common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
// Uncomment when debugging to get trace logging output - to follow flow.
// common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
}
// Fuzz tests based on findings with go-fuzz.
@ -74,7 +73,7 @@ endstream
// Slightly more complex case where the reference number is incorrect, but still points to the same object.
func TestFuzzSelfReference2(t *testing.T) {
common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
// common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
rawText := `13 0 obj
<< /Length 12 0 R >>

View File

@ -1043,6 +1043,96 @@ func TestTable(t *testing.T) {
}
}
func TestTableCellWrapping(t *testing.T) {
c := New()
c.NewPage()
table := NewTable(4) // Mx4 table
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.5, 0.2, 0.2, 0.1)
cell := table.NewCell()
p := NewParagraph("A Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
p.SetEnableWrap(true)
p.SetWidth(cell.Width(c.Context()))
p.SetTextAlignment(TextAlignmentJustify)
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
p = NewParagraph("B Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.")
p.SetEnableWrap(true)
p.SetTextAlignment(TextAlignmentRight)
cell.SetContent(p)
cell = table.NewCell()
p = NewParagraph("C Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
p.SetEnableWrap(true)
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("1,4")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,1")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,2")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,2")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
//table.SkipCells(1) // Skip over 2,3.
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
//p = NewParagraph("D Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
p = NewParagraph("X")
p.SetEnableWrap(true)
cell.SetContent(p)
// Skip over two rows.
table.SkipRows(2)
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
p = NewParagraph("4,4")
cell.SetContent(p)
// Move down 3 rows, 2 to the left.
table.SkipOver(3, -2)
cell = table.NewCell()
p = NewParagraph("7,2")
cell.SetContent(p)
cell.SetBackgroundColor(ColorRGBFrom8bit(255, 0, 0))
table.SkipRows(1)
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
p = NewParagraph("This is\nnewline\nwrapped\n\nmulti")
p.SetEnableWrap(true)
cell.SetContent(p)
err := c.Draw(table)
if err != nil {
t.Fatalf("Error drawing: %v", err)
}
err = c.WriteToFile("/tmp/tablecell_wrap.pdf")
if err != nil {
t.Fatalf("Fail: %v\n", err)
}
}
// Test creating and drawing a table.
func TestBorderedTable(t *testing.T) {
table := NewTable(4) // Mx4 table

View File

@ -42,6 +42,11 @@ type Paragraph struct {
enableWrap bool
wrapWidth float64
// defaultWrap defines whether wrapping has been defined explictly or whether default behavior should
// be observed. Default behavior depends on context: normally wrap is expected, except for example in
// table cells wrapping is off by default.
defaultWrap bool
// Rotation angle (degrees).
angle float64
@ -74,6 +79,7 @@ func NewParagraph(text string) *Paragraph {
// TODO: Can we wrap intellectually, only if given width is known?
p.enableWrap = true
p.defaultWrap = true
p.SetColor(ColorRGBFrom8bit(0, 0, 0))
p.alignment = TextAlignmentLeft
p.angle = 0
@ -124,6 +130,7 @@ func (p *Paragraph) Text() string {
// SetEnableWrap sets the line wrapping enabled flag.
func (p *Paragraph) SetEnableWrap(enableWrap bool) {
p.enableWrap = enableWrap
p.defaultWrap = false
}
// SetColor set the color of the Paragraph text.
@ -207,6 +214,11 @@ func (p *Paragraph) getTextWidth() float64 {
return -1 // XXX/FIXME: return error.
}
// Ignore newline for this.. Handles as if all in one line.
if glyph == "controlLF" {
continue
}
metrics, found := p.textFont.GetGlyphCharMetrics(glyph)
if !found {
common.Log.Debug("Glyph char metrics not found! %s\n", glyph)
@ -241,6 +253,17 @@ func (p *Paragraph) wrapText() error {
return errors.New("Glyph not found for rune") // XXX/FIXME: return error.
}
// Newline wrapping.
if glyph == "controlLF" {
// Moves to next line.
p.textLines = append(p.textLines, string(line))
line = []rune{}
lineWidth = 0
widths = []float64{}
glyphs = []string{}
continue
}
metrics, found := p.textFont.GetGlyphCharMetrics(glyph)
if !found {
common.Log.Debug("Glyph char metrics not found! %s (%s)\n", glyph, string(val))
@ -417,6 +440,9 @@ func drawParagraphOnBlock(blk *Block, p *Paragraph, ctx DrawContext) (DrawContex
spaces++
continue
}
if glyph == "controlLF" {
continue
}
metrics, found := p.textFont.GetGlyphCharMetrics(glyph)
if !found {
common.Log.Debug("Unsupported glyph %s in font\n", glyph)

View File

@ -168,6 +168,50 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
// Start row keeps track of starting row (wraps to 0 on new page).
startrow := 0
// Prepare for drawing: Calculate cell dimensions, row, cell heights.
for _, cell := range table.cells {
// Get total width fraction
wf := float64(0.0)
for i := 0; i < cell.colspan; i++ {
wf += table.colWidths[cell.col+i-1]
}
// Get x pos relative to table upper left corner.
xrel := float64(0.0)
for i := 0; i < cell.col-1; i++ {
xrel += table.colWidths[i] * tableWidth
}
// Get y pos relative to table upper left corner.
yrel := float64(0.0)
for i := startrow; i < cell.row-1; i++ {
yrel += table.rowHeights[i]
}
// Calculate the width out of available width.
w := wf * tableWidth
// Get total height.
h := float64(0.0)
for i := 0; i < cell.rowspan; i++ {
h += table.rowHeights[cell.row+i-1]
}
// For text: Calculate width, height, wrapping within available space if specified.
if p, isp := cell.content.(*Paragraph); isp {
if p.enableWrap {
p.SetWidth(w - cell.indent)
}
newh := p.Height() + p.margins.bottom + p.margins.bottom
newh += 0.5 * p.fontSize * p.lineHeight // TODO: Make the top margin configurable?
if newh > h {
diffh := newh - h
// Add diff to last row
table.rowHeights[cell.row+cell.rowspan-2] += diffh
}
}
}
// Draw cells.
// row height, cell height
for _, cell := range table.cells {
// Get total width fraction
@ -505,14 +549,11 @@ func (cell *TableCell) Width(ctx DrawContext) float64 {
func (cell *TableCell) SetContent(vd VectorDrawable) error {
switch t := vd.(type) {
case *Paragraph:
// Default paragraph settings in table:
t.SetEnableWrap(false) // No wrapping.
h := cell.table.rowHeights[cell.row-1]
nh := t.Height() * 1.5 // Default multiplier 1.5.
// Increase height if needed.
if nh > h {
cell.table.SetRowHeight(cell.row, nh)
if t.defaultWrap {
// Default paragraph settings in table: no wrapping.
t.enableWrap = false // No wrapping.
}
cell.content = vd
default:
common.Log.Debug("Error: unsupported cell content type %T\n", vd)

View File

@ -12,8 +12,9 @@ import (
)
func init() {
// Uncomment when debugging to get debug or trace logging output.
//common.SetLogger(common.NewConsoleLogger(common.LogLevelDebug))
common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
//common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
}
// cmap1Data represents a basic CMap.
@ -58,8 +59,6 @@ const cmap1Data = `
// TestCMapParser tests basic loading of a simple CMap.
func TestCMapParser1(t *testing.T) {
common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
cmap, err := LoadCmapFromDataCID([]byte(cmap1Data))
if err != nil {
t.Error("Failed: ", err)
@ -152,7 +151,7 @@ const cmap2Data = `
// TestCMapParser2 tests a bug that came up when 2-byte character codes had the higher byte set to 0,
// e.g. 0x0080, and the character map was not taking the number of bytes of the input codemap into account.
func TestCMapParser2(t *testing.T) {
common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
//common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
cmap, err := LoadCmapFromDataCID([]byte(cmap2Data))
if err != nil {
@ -245,7 +244,7 @@ const cmapData3 = `
// TestCMapParser3 test case of a CMap with mixed number of 1 and 2 bytes in the codespace range.
func TestCMapParser3(t *testing.T) {
common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
//common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
cmap, err := LoadCmapFromDataCID([]byte(cmapData3))
if err != nil {

View File

@ -8,12 +8,12 @@ package model
import (
"testing"
"github.com/unidoc/unidoc/common"
"github.com/unidoc/unidoc/pdf/core"
)
func init() {
common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
// Uncomment when debugging to get trace logging output - to follow flow.
// common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
}
// Test for an endless recursive loop in