mirror of
https://github.com/foliojs/pdfkit.git
synced 2025-12-08 20:15:54 +00:00
Merge branch 'master' into fontkit
Conflicts: lib/font/tables/name.coffee lib/font/ttf.coffee
This commit is contained in:
commit
944cbc6cbc
@ -80,7 +80,7 @@ If you forget to install it, Browserify will print an error message.
|
||||
## Adding pages
|
||||
|
||||
The first page of a PDFKit document is added for you automatically when you
|
||||
create the document. Subsequent pages must be added by you. Luckily, it is
|
||||
create the document unless you provide `autoFirstPage: false`. Subsequent pages must be added by you. Luckily, it is
|
||||
quite simple!
|
||||
|
||||
doc.addPage()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Images in PDFKit
|
||||
|
||||
Adding images to PDFKit documents is an easy task. Just pass an image path to
|
||||
Adding images to PDFKit documents is an easy task. Just pass an image path, buffer, or data uri with base64 encoded data to
|
||||
the `image` method along with some optional arguments. PDFKit supports the
|
||||
JPEG and PNG formats. If an X and Y position are not provided, the image is
|
||||
rendered at the current point in the text flow (below the last line of text).
|
||||
@ -41,4 +41,4 @@ This example produces the following output:
|
||||

|
||||
|
||||
That is all there is to adding images to your PDF documents with PDFKit. Now
|
||||
let's look at adding annotations.
|
||||
let's look at adding annotations.
|
||||
|
||||
@ -63,7 +63,8 @@ class PDFDocument extends stream.Readable
|
||||
@_write "%\xFF\xFF\xFF\xFF"
|
||||
|
||||
# Add the first page
|
||||
@addPage()
|
||||
if @options.autoFirstPage isnt false
|
||||
@addPage()
|
||||
|
||||
mixin = (methods) =>
|
||||
for name, method of methods
|
||||
@ -172,7 +173,7 @@ class PDFDocument extends stream.Readable
|
||||
@_info = @ref()
|
||||
for key, val of @info
|
||||
if typeof val is 'string'
|
||||
val = PDFObject.s val, true
|
||||
val = new String val
|
||||
|
||||
@_info.data[key] = val
|
||||
|
||||
@ -203,7 +204,7 @@ class PDFDocument extends stream.Readable
|
||||
# trailer
|
||||
@_write 'trailer'
|
||||
@_write PDFObject.convert
|
||||
Size: @_offsets.length
|
||||
Size: @_offsets.length + 1
|
||||
Root: @_root
|
||||
Info: @_info
|
||||
|
||||
|
||||
@ -3,29 +3,29 @@ fs = require 'fs'
|
||||
class JPEG
|
||||
MARKERS = [0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC5, 0xFFC6, 0xFFC7,
|
||||
0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF]
|
||||
|
||||
constructor: (@data, @label) ->
|
||||
if data.readUInt16BE(0) isnt 0xFFD8
|
||||
|
||||
constructor: (@data, @label) ->
|
||||
if @data.readUInt16BE(0) isnt 0xFFD8
|
||||
throw "SOI not found in JPEG"
|
||||
|
||||
pos = 2
|
||||
while pos < data.length
|
||||
marker = data.readUInt16BE(pos)
|
||||
while pos < @data.length
|
||||
marker = @data.readUInt16BE(pos)
|
||||
pos += 2
|
||||
break if marker in MARKERS
|
||||
pos += data.readUInt16BE(pos)
|
||||
|
||||
pos += @data.readUInt16BE(pos)
|
||||
|
||||
throw "Invalid JPEG." unless marker in MARKERS
|
||||
pos += 2
|
||||
|
||||
@bits = data[pos++]
|
||||
@height = data.readUInt16BE(pos)
|
||||
|
||||
@bits = @data[pos++]
|
||||
@height = @data.readUInt16BE(pos)
|
||||
pos += 2
|
||||
|
||||
@width = data.readUInt16BE(pos)
|
||||
|
||||
@width = @data.readUInt16BE(pos)
|
||||
pos += 2
|
||||
|
||||
channels = data[pos++]
|
||||
|
||||
channels = @data[pos++]
|
||||
@colorSpace = switch channels
|
||||
when 1 then 'DeviceGray'
|
||||
when 3 then 'DeviceRGB'
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
PDFObject = require '../object'
|
||||
|
||||
module.exports =
|
||||
annotate: (x, y, w, h, options) ->
|
||||
options.Type = 'Annot'
|
||||
@ -9,7 +7,7 @@ module.exports =
|
||||
delete options.color
|
||||
|
||||
if typeof options.Dest is 'string'
|
||||
options.Dest = PDFObject.s options.Dest
|
||||
options.Dest = new String options.Dest
|
||||
|
||||
# Capitalize keys
|
||||
for key, val of options
|
||||
@ -22,7 +20,7 @@ module.exports =
|
||||
|
||||
note: (x, y, w, h, contents, options = {}) ->
|
||||
options.Subtype = 'Text'
|
||||
options.Contents = PDFObject.s contents, true
|
||||
options.Contents = new String contents
|
||||
options.Name = 'Comment'
|
||||
options.color ?= [243, 223, 92]
|
||||
@annotate x, y, w, h, options
|
||||
@ -31,7 +29,7 @@ module.exports =
|
||||
options.Subtype = 'Link'
|
||||
options.A = @ref
|
||||
S: 'URI'
|
||||
URI: PDFObject.s url
|
||||
URI: new String url
|
||||
|
||||
options.A.end()
|
||||
@annotate x, y, w, h, options
|
||||
@ -39,7 +37,7 @@ module.exports =
|
||||
_markup: (x, y, w, h, options = {}) ->
|
||||
[x1, y1, x2, y2] = @_convertRect x, y, w, h
|
||||
options.QuadPoints = [x1, y2, x2, y2, x1, y1, x2, y1]
|
||||
options.Contents = PDFObject.s ''
|
||||
options.Contents = new String
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
highlight: (x, y, w, h, options = {}) ->
|
||||
@ -57,24 +55,24 @@ module.exports =
|
||||
|
||||
lineAnnotation: (x1, y1, x2, y2, options = {}) ->
|
||||
options.Subtype = 'Line'
|
||||
options.Contents = PDFObject.s ''
|
||||
options.Contents = new String
|
||||
options.L = [x1, @page.height - y1, x2, @page.height - y2]
|
||||
@annotate x1, y1, x2, y2, options
|
||||
|
||||
rectAnnotation: (x, y, w, h, options = {}) ->
|
||||
options.Subtype = 'Square'
|
||||
options.Contents = PDFObject.s ''
|
||||
options.Contents = new String
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
ellipseAnnotation: (x, y, w, h, options = {}) ->
|
||||
options.Subtype = 'Circle'
|
||||
options.Contents = PDFObject.s ''
|
||||
options.Contents = new String
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
textAnnotation: (x, y, w, h, text, options = {}) ->
|
||||
options.Subtype = 'FreeText'
|
||||
options.Contents = PDFObject.s text, true
|
||||
options.DA = PDFObject.s ''
|
||||
options.Contents = new String text
|
||||
options.DA = new String
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
_convertRect: (x1, y1, w, h) ->
|
||||
|
||||
@ -6,30 +6,75 @@ By Devon Govett
|
||||
class PDFObject
|
||||
pad = (str, length) ->
|
||||
(Array(length + 1).join('0') + str).slice(-length)
|
||||
|
||||
escapableRe = /[\n\r\t\b\f\(\)\\]/g
|
||||
escapable =
|
||||
'\n': '\\n'
|
||||
'\r': '\\r'
|
||||
'\t': '\\t'
|
||||
'\b': '\\b'
|
||||
'\f': '\\f'
|
||||
'\\': '\\\\'
|
||||
'(': '\\('
|
||||
')': '\\)'
|
||||
|
||||
# Convert little endian UTF-16 to big endian
|
||||
swapBytes = (buff) ->
|
||||
l = buff.length
|
||||
if l & 0x01
|
||||
throw new Error("Buffer length must be even")
|
||||
else
|
||||
for i in [0...l - 1] by 2
|
||||
a = buff[i]
|
||||
buff[i] = buff[i + 1]
|
||||
buff[i+1] = a
|
||||
|
||||
return buff
|
||||
|
||||
@convert: (object) ->
|
||||
if Array.isArray object
|
||||
items = (PDFObject.convert e for e in object).join(' ')
|
||||
'[' + items + ']'
|
||||
|
||||
else if typeof object is 'string'
|
||||
# String literals are converted to the PDF name type
|
||||
if typeof object is 'string'
|
||||
'/' + object
|
||||
|
||||
else if object?.isString
|
||||
'(' + object + ')'
|
||||
|
||||
# String objects are converted to PDF strings (UTF-16)
|
||||
else if object instanceof String
|
||||
# Escape characters as required by the spec
|
||||
string = object.replace escapableRe, (c) ->
|
||||
return escapable[c]
|
||||
|
||||
# Detect if this is a unicode string
|
||||
isUnicode = false
|
||||
for i in [0...string.length] by 1
|
||||
if string.charCodeAt(i) > 0x7f
|
||||
isUnicode = true
|
||||
break
|
||||
|
||||
# If so, encode it as big endian UTF-16
|
||||
if isUnicode
|
||||
string = swapBytes(new Buffer('\ufeff' + string, 'utf16le')).toString('binary')
|
||||
|
||||
'(' + string + ')'
|
||||
|
||||
# Buffers are converted to PDF hex strings
|
||||
else if Buffer.isBuffer(object)
|
||||
'<' + object.toString('hex') + '>'
|
||||
|
||||
else if object instanceof PDFReference
|
||||
object.toString()
|
||||
|
||||
|
||||
else if object instanceof Date
|
||||
'(D:' + pad(object.getUTCFullYear(), 4) +
|
||||
pad(object.getUTCMonth(), 2) +
|
||||
pad(object.getUTCDate(), 2) +
|
||||
pad(object.getUTCHours(), 2) +
|
||||
pad(object.getUTCMinutes(), 2) +
|
||||
pad(object.getUTCSeconds(), 2) +
|
||||
'(D:' + pad(object.getUTCFullYear(), 4) +
|
||||
pad(object.getUTCMonth(), 2) +
|
||||
pad(object.getUTCDate(), 2) +
|
||||
pad(object.getUTCHours(), 2) +
|
||||
pad(object.getUTCMinutes(), 2) +
|
||||
pad(object.getUTCSeconds(), 2) +
|
||||
'Z)'
|
||||
|
||||
else if Array.isArray object
|
||||
items = (PDFObject.convert e for e in object).join(' ')
|
||||
'[' + items + ']'
|
||||
|
||||
else if {}.toString.call(object) is '[object Object]'
|
||||
out = ['<<']
|
||||
for key, val of object
|
||||
@ -40,34 +85,6 @@ class PDFObject
|
||||
|
||||
else
|
||||
'' + object
|
||||
|
||||
# Convert Big-endian UCS-2 to Little-endian to support most PDFRreaders
|
||||
swapBytes = (buff) ->
|
||||
l = buff.length
|
||||
if l & 0x01
|
||||
throw new Error("Buffer length must be even")
|
||||
else
|
||||
for i in [0...l - 1] by 2
|
||||
a = buff[i]
|
||||
buff[i] = buff[i+1]
|
||||
buff[i+1] = a
|
||||
return buff
|
||||
|
||||
@s: (string, swap = false) ->
|
||||
string = string.replace(/\\/g, '\\\\\\\\')
|
||||
.replace(/\(/g, '\\(')
|
||||
.replace(/\)/g, '\\)')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/&/g, '&')
|
||||
|
||||
if swap
|
||||
string = swapBytes(new Buffer('\ufeff' + string, 'ucs-2')).toString('binary')
|
||||
|
||||
return {
|
||||
isString: yes
|
||||
toString: -> string
|
||||
}
|
||||
|
||||
|
||||
module.exports = PDFObject
|
||||
PDFReference = require './reference'
|
||||
PDFReference = require './reference'
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
"document",
|
||||
"vector"
|
||||
],
|
||||
"version": "0.7.0",
|
||||
"version": "0.7.1",
|
||||
"homepage": "http://pdfkit.org/",
|
||||
"author": {
|
||||
"name": "Devon Govett",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user