Text baseline & oblique option (#585)

This commit is contained in:
alafr 2018-02-02 18:39:57 +01:00 committed by GitHub
parent 8859fdb11c
commit 34cf8d5fa6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 4 deletions

View File

@ -91,6 +91,8 @@ below.
* `link` - a URL to link this text to (shortcut to create an annotation)
* `underline` - whether to underline the text
* `strike` - whether to strike out the text
* `oblique` - whether to slant the text (angle in degrees or `true`)
* `baseline` - the vertical alignment of the text with respect to its insertion point (values as [canvas textBaseline](https://www.w3schools.com/tags/canvas_textbaseline.asp))
* `continued` - whether the text segment will be followed immediately by another segment. Useful for changing styling in the middle of a paragraph.
* `features` - an array of [OpenType feature tags](https://www.microsoft.com/typography/otspec/featuretags.htm) to apply. If not provided, a set of defaults is used.

View File

@ -16,6 +16,8 @@ class AFMFont
@bbox = (+e for e in @attributes['FontBBox'].split /\s+/)
@ascender = +(@attributes['Ascender'] or 0)
@descender = +(@attributes['Descender'] or 0)
@xHeight = +(@attributes['XHeight'] or 0)
@capHeight = +(@attributes['CapHeight'] or 0)
@lineGap = (@bbox[3] - @bbox[1]) - (@ascender - @descender)
parse: ->
@ -192,4 +194,4 @@ class AFMFont
udieresis yacute thorn ydieresis
'''.split(/\s+/)
module.exports = AFMFont
module.exports = AFMFont

View File

@ -11,6 +11,8 @@ class EmbeddedFont extends PDFFont
@scale = 1000 / @font.unitsPerEm
@ascender = @font.ascent * @scale
@descender = @font.descent * @scale
@xHeight = @font.xHeight * @scale
@capHeight = @font.capHeight * @scale
@lineGap = @font.lineGap * @scale
@bbox = @font.bbox

View File

@ -5,7 +5,7 @@ fs = require 'fs'
class StandardFont extends PDFFont
constructor: (@document, @name, @id) ->
@font = new AFMFont STANDARD_FONTS[@name]()
{@ascender,@descender,@bbox,@lineGap} = @font
{@ascender,@descender,@bbox,@lineGap,@xHeight,@capHeight} = @font
embed: ->
@dictionary.data =

View File

@ -207,6 +207,29 @@ module.exports =
spaceWidth = @widthOfString(' ') + characterSpacing
wordSpacing = Math.max 0, (options.lineWidth - textWidth) / Math.max(1, words.length - 1) - spaceWidth
# text baseline alignments based on http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
if typeof options.baseline is 'number'
dy = -options.baseline
else
switch options.baseline
when 'svg-middle'
dy = 0.5 * @_font.xHeight
when 'middle', 'svg-central'
dy = 0.5 * (@_font.descender + @_font.ascender)
when 'bottom', 'ideographic'
dy = @_font.descender
when 'alphabetic'
dy = 0;
when 'mathematical'
dy = 0.5 * @_font.ascender
when 'hanging'
dy = 0.8 * @_font.ascender
when 'top'
dy = @_font.ascender
else
dy = @_font.ascender
dy = dy / 1000 * @_fontSize
# calculate the actual rendered width of the string after word and character spacing
renderedWidth = options.textWidth + (wordSpacing * (options.wordCount - 1)) + (characterSpacing * (text.length - 1))
@ -231,10 +254,21 @@ module.exports =
@stroke()
@restore()
# flip coordinate system
@save()
# oblique (angle in degrees or boolean)
if options.oblique
if typeof options.oblique is 'number'
skew = -Math.tan(options.oblique * Math.PI / 180)
else
skew = -0.25
@transform 1, 0, 0, 1, x, y
@transform 1, 0, skew, 1, -skew * dy, 0
@transform 1, 0, 0, 1, -x, -y
# flip coordinate system
@transform 1, 0, 0, -1, 0, @page.height
y = @page.height - y - (@_font.ascender / 1000 * @_fontSize)
y = @page.height - y - dy
# add current font to page if necessary
@page.fonts[@_font.id] ?= @_font.ref()