mirror of
https://github.com/foliojs/pdfkit.git
synced 2025-12-08 20:15:54 +00:00
Merge pull request #572 from alafr/numbers
Pdf corruption with small numbers
This commit is contained in:
commit
e1a4f490b3
@ -129,7 +129,12 @@ class PDFDocument extends stream.Readable
|
||||
@_offsets.push null # placeholder for this object's offset once it is finalized
|
||||
@_waiting++
|
||||
return ref
|
||||
|
||||
|
||||
number: (n) ->
|
||||
if n > -1e21 and n < 1e21
|
||||
return Math.round(n * 1e6) / 1e6
|
||||
throw new Error "unsupported number: #{n}"
|
||||
|
||||
_read: ->
|
||||
# do nothing, but this method is required by node
|
||||
|
||||
|
||||
@ -223,17 +223,17 @@ module.exports =
|
||||
@addContent "BT"
|
||||
|
||||
# text position
|
||||
@addContent "1 0 0 1 #{x} #{y} Tm"
|
||||
@addContent "1 0 0 1 #{@number(x)} #{@number(y)} Tm"
|
||||
|
||||
# font and font size
|
||||
@addContent "/#{@_font.id} #{@_fontSize} Tf"
|
||||
@addContent "/#{@_font.id} #{@number(@_fontSize)} Tf"
|
||||
|
||||
# rendering mode
|
||||
mode = if options.fill and options.stroke then 2 else if options.stroke then 1 else 0
|
||||
@addContent "#{mode} Tr" if mode
|
||||
|
||||
# Character spacing
|
||||
@addContent "#{characterSpacing} Tc" if characterSpacing
|
||||
@addContent "#{@number(characterSpacing)} Tc" if characterSpacing
|
||||
|
||||
# Add the actual text
|
||||
# If we have a word spacing value, we need to encode each word separately
|
||||
@ -266,7 +266,7 @@ module.exports =
|
||||
if last < cur
|
||||
hex = encoded.slice(last, cur).join ''
|
||||
advance = positions[cur - 1].xAdvance - positions[cur - 1].advanceWidth
|
||||
commands.push "<#{hex}> #{-advance}"
|
||||
commands.push "<#{hex}> #{@number(-advance)}"
|
||||
|
||||
last = cur
|
||||
|
||||
@ -286,14 +286,14 @@ module.exports =
|
||||
flush i
|
||||
|
||||
# Move the text position and flush just the current character
|
||||
@addContent "1 0 0 1 #{x + pos.xOffset * scale} #{y + pos.yOffset * scale} Tm"
|
||||
@addContent "1 0 0 1 #{@number(x + pos.xOffset * scale)} #{@number(y + pos.yOffset * scale)} Tm"
|
||||
flush i + 1
|
||||
|
||||
hadOffset = yes
|
||||
else
|
||||
# If the last character had an offset, reset the text position
|
||||
if hadOffset
|
||||
@addContent "1 0 0 1 #{x} #{y} Tm"
|
||||
@addContent "1 0 0 1 #{@number(x)} #{@number(y)} Tm"
|
||||
hadOffset = no
|
||||
|
||||
# Group segments that don't have any advance adjustments
|
||||
|
||||
@ -21,7 +21,7 @@ module.exports =
|
||||
@addContent 'h'
|
||||
|
||||
lineWidth: (w) ->
|
||||
@addContent "#{w} w"
|
||||
@addContent "#{@number(w)} w"
|
||||
|
||||
_CAP_STYLES:
|
||||
BUTT: 0
|
||||
@ -42,36 +42,36 @@ module.exports =
|
||||
@addContent "#{j} j"
|
||||
|
||||
miterLimit: (m) ->
|
||||
@addContent "#{m} M"
|
||||
@addContent "#{@number(m)} M"
|
||||
|
||||
dash: (length, options = {}) ->
|
||||
return this unless length?
|
||||
if Array.isArray length
|
||||
length = length.join ' '
|
||||
length = (@number(v) for v in length).join(' ')
|
||||
phase = options.phase or 0
|
||||
@addContent "[#{length}] #{phase} d"
|
||||
@addContent "[#{length}] #{@number(phase)} d"
|
||||
else
|
||||
space = options.space ? length
|
||||
phase = options.phase or 0
|
||||
@addContent "[#{length} #{space}] #{phase} d"
|
||||
@addContent "[#{@number(length)} #{@number(space)}] #{@number(phase)} d"
|
||||
|
||||
undash: ->
|
||||
@addContent "[] 0 d"
|
||||
|
||||
moveTo: (x, y) ->
|
||||
@addContent "#{x} #{y} m"
|
||||
@addContent "#{@number(x)} #{@number(y)} m"
|
||||
|
||||
lineTo: (x, y) ->
|
||||
@addContent "#{x} #{y} l"
|
||||
@addContent "#{@number(x)} #{@number(y)} l"
|
||||
|
||||
bezierCurveTo: (cp1x, cp1y, cp2x, cp2y, x, y) ->
|
||||
@addContent "#{cp1x} #{cp1y} #{cp2x} #{cp2y} #{x} #{y} c"
|
||||
@addContent "#{@number(cp1x)} #{@number(cp1y)} #{@number(cp2x)} #{@number(cp2y)} #{@number(x)} #{@number(y)} c"
|
||||
|
||||
quadraticCurveTo: (cpx, cpy, x, y) ->
|
||||
@addContent "#{cpx} #{cpy} #{x} #{y} v"
|
||||
@addContent "#{@number(cpx)} #{@number(cpy)} #{@number(x)} #{@number(y)} v"
|
||||
|
||||
rect: (x, y, w, h) ->
|
||||
@addContent "#{x} #{y} #{w} #{h} re"
|
||||
@addContent "#{@number(x)} #{@number(y)} #{@number(w)} #{@number(h)} re"
|
||||
|
||||
roundedRect: (x, y, w, h, r = 0) ->
|
||||
r = Math.min(r, 0.5 * w, 0.5 * h)
|
||||
@ -168,7 +168,7 @@ module.exports =
|
||||
m[4] = m0 * dx + m2 * dy + m4
|
||||
m[5] = m1 * dx + m3 * dy + m5
|
||||
|
||||
values = (+v.toFixed(5) for v in [m11, m12, m21, m22, dx, dy]).join(' ')
|
||||
values = (@number(v) for v in [m11, m12, m21, m22, dx, dy]).join(' ')
|
||||
@addContent "#{values} cm"
|
||||
|
||||
translate: (x, y) ->
|
||||
|
||||
@ -310,12 +310,12 @@ class SVGPath
|
||||
|
||||
th_half = 0.5 * (th1 - th0)
|
||||
t = (8 / 3) * Math.sin(th_half * 0.5) * Math.sin(th_half * 0.5) / Math.sin(th_half)
|
||||
x1 = fixRoundingError(cx + Math.cos(th0) - t * Math.sin(th0))
|
||||
y1 = fixRoundingError(cy + Math.sin(th0) + t * Math.cos(th0))
|
||||
x3 = fixRoundingError(cx + Math.cos(th1))
|
||||
y3 = fixRoundingError(cy + Math.sin(th1))
|
||||
x2 = fixRoundingError(x3 + t * Math.sin(th1))
|
||||
y2 = fixRoundingError(y3 - t * Math.cos(th1))
|
||||
x1 = cx + Math.cos(th0) - t * Math.sin(th0)
|
||||
y1 = cy + Math.sin(th0) + t * Math.cos(th0)
|
||||
x3 = cx + Math.cos(th1)
|
||||
y3 = cy + Math.sin(th1)
|
||||
x2 = x3 + t * Math.sin(th1)
|
||||
y2 = y3 - t * Math.cos(th1)
|
||||
|
||||
return [
|
||||
a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
|
||||
@ -323,9 +323,4 @@ class SVGPath
|
||||
a00 * x3 + a01 * y3, a10 * x3 + a11 * y3
|
||||
]
|
||||
|
||||
fixRoundingError = (x) ->
|
||||
if Math.abs(Math.round(x) - x) < 0.0000000000001
|
||||
return Math.round(x);
|
||||
return x
|
||||
|
||||
module.exports = SVGPath
|
||||
module.exports = SVGPath
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user