Merge branch 'master' of github.com:devongovett/pdfkit into fontkit

Conflicts:
	lib/font/table.coffee
	lib/font/tables/cmap.coffee
	lib/font/tables/glyf.coffee
	lib/font/tables/head.coffee
	lib/font/tables/hhea.coffee
	lib/font/tables/hmtx.coffee
	lib/font/tables/loca.coffee
	lib/font/tables/maxp.coffee
	lib/font/tables/name.coffee
	lib/font/tables/os2.coffee
	lib/font/tables/post.coffee
This commit is contained in:
Devon Govett 2014-11-27 20:51:58 -08:00
commit 6b2bea9835
11 changed files with 1109 additions and 997 deletions

View File

@ -1,5 +1,5 @@
MIT LICENSE
Copyright (c) 2011 Devon Govett
Copyright (c) 2014 Devon Govett
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -2,6 +2,8 @@
A JavaScript PDF generation library for Node and the browser.
[![](https://img.shields.io/gratipay/devongovett.svg)](https://gratipay.com/devongovett)
## Description
PDFKit is a PDF document generation library for Node and the browser that makes creating complex, multi-page, printable documents easy.
@ -158,4 +160,4 @@ For complete API documentation and more examples, see the [PDFKit website](http:
## License
PDFKit is available under the MIT license.
PDFKit is available under the MIT license.

View File

@ -117,6 +117,48 @@ For example:
bottom: 50
left: 72
right: 72
## Switching to previous pages
PDFKit normally flushes pages to the output file immediately when a new page is created, making
it impossible to jump back and add content to previous pages. This is normally not an issue, but
in some circumstances it can be useful to add content to pages after the whole document, or a part
of the document, has been created already. Examples include adding page numbers, or filling in other
parts of information you don't have until the rest of the document has been created.
PDFKit has a `bufferPages` option in versions v0.7.0 and later that allows you to control when
pages are flushed to the output file yourself rather than letting PDFKit handle that for you. To use
it, just pass `bufferPages: true` as an option to the `PDFDocument` constructor. Then, you can call
`doc.switchToPage(pageNumber)` to switch to a previous page (page numbers start at 0).
When you're ready to flush the buffered pages to the output file, call `flushPages`.
This method is automatically called by `doc.end()`, so if you just want to buffer all pages in the document, you
never need to call it. Finally, there is a `bufferedPageRange` method, which returns the range
of pages that are currently buffered. Here is a small example that shows how you might add page
numbers to a document.
# create a document, and enable bufferPages mode
doc = new PDFDocument
bufferPages: true
# add some content...
doc.addPage()
# ...
doc.addPage()
# see the range of buffered pages
range = doc.bufferedPageRange() # => { start: 0, count: 2 }
for i in [range.start...range.start + range.count]
doc.switchToPage(i)
doc.text "Page #{i + 1} of #{range.count}"
# manually flush pages that have been buffered
doc.flushPages()
# or, if you are at the end of the document anyway,
# doc.end() will call it for you automatically.
doc.end()
## Setting document metadata

File diff suppressed because it is too large Load Diff

View File

@ -19,11 +19,11 @@ class Data
@writeByte if val then 1 else 0
readUInt32: ->
b1 = @readByte() << 24
b1 = @readByte() * 0x1000000
b2 = @readByte() << 16
b3 = @readByte() << 8
b4 = @readByte()
b1 | b2 | b3 | b4
b1 + b2 + b3 + b4
writeUInt32: (val) ->
@writeByte (val >>> 24) & 0xff
@ -137,4 +137,4 @@ class Data
for byte in bytes
@writeByte byte
module.exports = Data
module.exports = Data

View File

@ -19,6 +19,9 @@ class PDFDocument extends stream.Readable
# Whether streams should be compressed
@compress = @options.compress ? yes
@_pageBuffer = []
@_pageBufferStart = 0
# The PDF object store
@_offsets = []
@_waiting = 0
@ -76,11 +79,12 @@ class PDFDocument extends stream.Readable
addPage: (options = @options) ->
# end the current page if needed
@page?.end()
@flushPages() unless @options.bufferPages
# create a page object
@page = new PDFPage(this, options)
@_pageBuffer.push(@page)
# add the page to the object store
pages = @_root.data.Pages.data
pages.Kids.push @page.dictionary
@ -96,7 +100,27 @@ class PDFDocument extends stream.Readable
@transform 1, 0, 0, -1, 0, @page.height
return this
bufferedPageRange: ->
return { start: @_pageBufferStart, count: @_pageBuffer.length }
switchToPage: (n) ->
unless page = @_pageBuffer[n - @_pageBufferStart]
throw new Error "switchToPage(#{n}) out of bounds, current buffer covers pages #{@_pageBufferStart} to #{@_pageBufferStart + @_pageBuffer.length - 1}"
@page = page
flushPages: ->
# this local variable exists so we're future-proof against
# reentrant calls to flushPages.
pages = @_pageBuffer
@_pageBuffer = []
@_pageBufferStart += pages.length
for page in pages
page.end()
return
ref: (data) ->
ref = new PDFReference(this, @_offsets.length + 1, data)
@_offsets.push null # placeholder for this object's offset once it is finalized
@ -144,8 +168,7 @@ class PDFDocument extends stream.Readable
'
end: ->
@page.end()
@flushPages()
@_info = @ref()
for key, val of @info
if typeof val is 'string'

View File

@ -14,8 +14,8 @@ class AFMFont
@charWidths = (@glyphWidths[characters[i]] for i in [0..255])
@bbox = (+e for e in @attributes['FontBBox'].split /\s+/)
@ascender = +@attributes['Ascender']
@decender = +@attributes['Descender']
@ascender = +(@attributes['Ascender'] or 0)
@decender = +(@attributes['Descender'] or 0)
@lineGap = (@bbox[3] - @bbox[1]) - (@ascender - @decender)
parse: ->

View File

@ -4,16 +4,18 @@ LineBreaker = require 'linebreak'
class LineWrapper extends EventEmitter
constructor: (@document, options) ->
@indent = options.indent or 0
@charSpacing = options.characterSpacing or 0
@characterSpacing = options.characterSpacing or 0
@wordSpacing = options.wordSpacing is 0
@columns = options.columns or 1
@columnGap = options.columnGap ? 18 # 1/4 inch
@lineWidth = (options.width - (@columnGap * (@columns - 1))) / @columns
@spaceLeft = @lineWidth
@startX = @document.x
@startY = @document.y
@column = 1
@ellipsis = options.ellipsis
@continuedX = 0
@features = options.features
# calculate the maximum Y position the text can appear at
if options.height?
@ -34,6 +36,8 @@ class LineWrapper extends EventEmitter
@once 'line', =>
@document.x -= indent
@lineWidth += indent
if options.continued and not @continuedX
@continuedX = @indent
@continuedX = 0 unless options.continued
# handle left aligning last lines of paragraphs
@ -48,7 +52,7 @@ class LineWrapper extends EventEmitter
@lastLine = false
wordWidth: (word) ->
return @document.widthOfString(word, this) + @charSpacing + @wordSpacing
return @document.widthOfString(word, this) + @characterSpacing + @wordSpacing
eachWord: (text, fn) ->
# setup a unicode line breaker
@ -62,7 +66,7 @@ class LineWrapper extends EventEmitter
# if the word is longer than the whole line, chop it up
# TODO: break by grapheme clusters, not JS string characters
if w > @lineWidth
if w > @lineWidth + @continuedX
# make some fake break objects
lbk = last
fbk = {}
@ -95,7 +99,7 @@ class LineWrapper extends EventEmitter
wrap: (text, options) ->
# override options from previous continued fragments
@indent = options.indent if options.indent?
@charSpacing = options.characterSpacing if options.characterSpacing?
@characterSpacing = options.characterSpacing if options.characterSpacing?
@wordSpacing = options.wordSpacing if options.wordSpacing?
@ellipsis = options.ellipsis if options.ellipsis?

View File

@ -22,7 +22,7 @@ module.exports =
note: (x, y, w, h, contents, options = {}) ->
options.Subtype = 'Text'
options.Contents = PDFObject.s contents
options.Contents = PDFObject.s contents, true
options.Name = 'Comment'
options.color ?= [243, 223, 92]
@annotate x, y, w, h, options
@ -73,7 +73,7 @@ module.exports =
textAnnotation: (x, y, w, h, text, options = {}) ->
options.Subtype = 'FreeText'
options.Contents = PDFObject.s text
options.Contents = PDFObject.s text, true
options.DA = PDFObject.s ''
@annotate x, y, w, h, options

View File

@ -117,7 +117,6 @@ module.exports =
wrapper.wrap items.join('\n'), options
@x -= indent
return this
_initOptions: (x = {}, y, options = {}) ->

View File

@ -9,7 +9,7 @@
"document",
"vector"
],
"version": "0.6.3",
"version": "0.7.0",
"homepage": "http://pdfkit.org/",
"author": {
"name": "Devon Govett",