mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-26 13:48:55 +08:00
Add support for vertical alignment of styled paragraphs inside table cells (#69)
This commit is contained in:
parent
8425bf7c8f
commit
3bae2f6035
@ -226,6 +226,49 @@ func (p *StyledParagraph) Height() float64 {
|
||||
return height
|
||||
}
|
||||
|
||||
// getLineHeight returns both the capheight and the font size based height of
|
||||
// the line with the specified index.
|
||||
func (p *StyledParagraph) getLineHeight(idx int) (capHeight, height float64) {
|
||||
if p.lines == nil || len(p.lines) == 0 {
|
||||
p.wrapText()
|
||||
}
|
||||
if idx < 0 || idx > len(p.lines)-1 {
|
||||
common.Log.Debug("ERROR: invalid paragraph line index %d. Returning 0, 0", idx)
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
line := p.lines[idx]
|
||||
for _, chunk := range line {
|
||||
descriptor, err := chunk.Style.Font.GetFontDescriptor()
|
||||
if err != nil {
|
||||
common.Log.Debug("ERROR: Unable to get font descriptor")
|
||||
}
|
||||
|
||||
var fontCapHeight float64
|
||||
if descriptor != nil {
|
||||
if fontCapHeight, err = descriptor.GetCapHeight(); err != nil {
|
||||
common.Log.Debug("ERROR: Unable to get font CapHeight: %v", err)
|
||||
}
|
||||
}
|
||||
if int(fontCapHeight) <= 0 {
|
||||
common.Log.Debug("WARN: CapHeight not available - setting to 1000")
|
||||
fontCapHeight = 1000
|
||||
}
|
||||
|
||||
h := fontCapHeight / 1000.0 * chunk.Style.FontSize * p.lineHeight
|
||||
if h > capHeight {
|
||||
capHeight = h
|
||||
}
|
||||
|
||||
h = p.lineHeight * chunk.Style.FontSize
|
||||
if h > height {
|
||||
height = h
|
||||
}
|
||||
}
|
||||
|
||||
return capHeight, height
|
||||
}
|
||||
|
||||
// getTextWidth calculates the text width as if all in one line (not taking
|
||||
// wrapping into account).
|
||||
func (p *StyledParagraph) getTextWidth() float64 {
|
||||
|
@ -798,3 +798,66 @@ func TestStyledLinkRotation(t *testing.T) {
|
||||
t.Fatalf("Fail: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStyledParagraphTableVerticalAlignment(t *testing.T) {
|
||||
c := New()
|
||||
|
||||
fontRegular := newStandard14Font(t, model.CourierName)
|
||||
|
||||
createTable := func(c *Creator, text string, align CellVerticalAlignment, fontSize float64) {
|
||||
textStyle := c.NewTextStyle()
|
||||
textStyle.Font = fontRegular
|
||||
textStyle.FontSize = fontSize
|
||||
|
||||
table := c.NewTable(1)
|
||||
table.SetMargins(0, 0, 5, 5)
|
||||
|
||||
cell := table.NewCell()
|
||||
sp := c.NewStyledParagraph()
|
||||
textChunk := sp.Append(text)
|
||||
textChunk.Style = textStyle
|
||||
|
||||
cell.SetVerticalAlignment(align)
|
||||
cell.SetContent(sp)
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
|
||||
if err := c.Draw(table); err != nil {
|
||||
t.Fatalf("Error drawing: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
chunks := []string{
|
||||
"TR",
|
||||
"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.",
|
||||
}
|
||||
|
||||
alignments := []struct {
|
||||
Label string
|
||||
Alignment CellVerticalAlignment
|
||||
}{
|
||||
{"Top alignment", CellVerticalAlignmentTop},
|
||||
{"Middle alignment", CellVerticalAlignmentMiddle},
|
||||
{"Bottom alignment", CellVerticalAlignmentBottom},
|
||||
}
|
||||
|
||||
for _, chunk := range chunks {
|
||||
for _, alignment := range alignments {
|
||||
c.NewPage()
|
||||
|
||||
sp := c.NewStyledParagraph()
|
||||
sp.Append(alignment.Label).Style.FontSize = 16
|
||||
sp.SetMargins(0, 0, 0, 5)
|
||||
|
||||
if err := c.Draw(sp); err != nil {
|
||||
t.Fatalf("Error drawing: %v", err)
|
||||
}
|
||||
|
||||
for i := 4; i <= 20; i += 2 {
|
||||
createTable(c, chunk, alignment.Alignment, float64(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write output file.
|
||||
testWriteAndRender(t, c, "styled_paragraph_table_vertical_align.pdf")
|
||||
}
|
||||
|
@ -516,8 +516,10 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
|
||||
}
|
||||
|
||||
if cell.content != nil {
|
||||
// content width.
|
||||
cw := cell.content.Width()
|
||||
cw := cell.content.Width() // content width.
|
||||
ch := cell.content.Height() // content height.
|
||||
vertOffset := 0.0
|
||||
|
||||
switch t := cell.content.(type) {
|
||||
case *Paragraph:
|
||||
if t.enableWrap {
|
||||
@ -527,6 +529,26 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
|
||||
if t.enableWrap {
|
||||
cw = t.getMaxLineWidth() / 1000.0
|
||||
}
|
||||
|
||||
// Calculate the height of the paragraph.
|
||||
lineCapHeight, lineHeight := t.getLineHeight(0)
|
||||
if len(t.lines) == 1 {
|
||||
ch = lineCapHeight
|
||||
} else {
|
||||
ch = ch - lineHeight + lineCapHeight
|
||||
}
|
||||
|
||||
// Account for the top offset the paragraph adds.
|
||||
vertOffset = lineCapHeight - t.defaultStyle.FontSize*t.lineHeight
|
||||
|
||||
switch cell.verticalAlignment {
|
||||
case CellVerticalAlignmentTop:
|
||||
// Add a bit of space from the top border of the cell.
|
||||
vertOffset += lineCapHeight * 0.5
|
||||
case CellVerticalAlignmentBottom:
|
||||
// Add a bit of space from the bottom border of the cell.
|
||||
vertOffset -= lineCapHeight * 0.5
|
||||
}
|
||||
case *Table:
|
||||
cw = w
|
||||
case *List:
|
||||
@ -553,8 +575,9 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Y += vertOffset
|
||||
|
||||
// Account for vertical alignment.
|
||||
ch := cell.content.Height() // content height.
|
||||
switch cell.verticalAlignment {
|
||||
case CellVerticalAlignmentTop:
|
||||
// Default: do nothing.
|
||||
@ -567,7 +590,7 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
|
||||
case CellVerticalAlignmentBottom:
|
||||
if h > ch {
|
||||
ctx.Y = ctx.Y + h - ch
|
||||
ctx.Height = ch
|
||||
ctx.Height = h
|
||||
}
|
||||
}
|
||||
|
||||
@ -575,6 +598,8 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
|
||||
if err != nil {
|
||||
common.Log.Debug("ERROR: %v", err)
|
||||
}
|
||||
|
||||
ctx.Y -= vertOffset
|
||||
}
|
||||
|
||||
ctx.Y += h
|
||||
|
Loading…
x
Reference in New Issue
Block a user