porting
parent
4dae0a97e3
commit
3f36e2ce2c
@ -0,0 +1,8 @@
|
||||
MIT LICENSE
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -0,0 +1,30 @@
|
||||
.PHONY: js
|
||||
|
||||
js:
|
||||
./node_modules/.bin/coffee -o js -c lib/
|
||||
cp -r lib/font/data js/font/data
|
||||
|
||||
browser: lib/**/*.coffee
|
||||
mkdir -p build/
|
||||
./node_modules/.bin/browserify \
|
||||
--standalone PDFDocument \
|
||||
--debug \
|
||||
--transform coffeeify \
|
||||
--extension .coffee \
|
||||
lib/document.coffee \
|
||||
| ./node_modules/.bin/exorcist build/pdfkit.js.map > build/pdfkit.js
|
||||
|
||||
browser-demo: js demo/browser.js
|
||||
./node_modules/.bin/browserify demo/browser.js > demo/bundle.js
|
||||
|
||||
docs: pdf-guide website browser-demo
|
||||
|
||||
pdf-guide:
|
||||
./node_modules/.bin/coffee docs/generate.coffee
|
||||
|
||||
website:
|
||||
mkdir -p docs/img
|
||||
./node_modules/.bin/coffee docs/generate_website.coffee
|
||||
|
||||
clean:
|
||||
rm -rf js build demo/bundle.js
|
@ -0,0 +1,171 @@
|
||||
# PDFKit
|
||||
|
||||
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.
|
||||
It's written in CoffeeScript, but you can choose to use the API in plain 'ol JavaScript if you like. The API embraces
|
||||
chainability, and includes both low level functions as well as abstractions for higher level functionality. The PDFKit API
|
||||
is designed to be simple, so generating complex documents is often as simple as a few function calls.
|
||||
|
||||
Check out some of the [documentation and examples](http://pdfkit.org/docs/getting_started.html) to see for yourself!
|
||||
You can also read the guide as a [self-generated PDF](http://pdfkit.org/docs/guide.pdf) with example output displayed inline.
|
||||
If you'd like to see how it was generated, check out the README in the [docs](https://github.com/devongovett/pdfkit/tree/master/docs)
|
||||
folder.
|
||||
|
||||
You can also try out an interactive in-browser demo of PDFKit [here](http://pdfkit.org/demo/browser.html).
|
||||
|
||||
## Installation
|
||||
|
||||
Installation uses the [npm](http://npmjs.org/) package manager. Just type the following command after installing npm.
|
||||
|
||||
npm install pdfkit
|
||||
|
||||
## Features
|
||||
|
||||
* Vector graphics
|
||||
* HTML5 canvas-like API
|
||||
* Path operations
|
||||
* SVG path parser for easy path creation
|
||||
* Transformations
|
||||
* Linear and radial gradients
|
||||
* Text
|
||||
* Line wrapping
|
||||
* Text alignments
|
||||
* Bulleted lists
|
||||
* Font embedding
|
||||
* Supports TrueType (.ttf), OpenType (.otf), WOFF, WOFF2, TrueType Collections (.ttc), and Datafork TrueType (.dfont) fonts
|
||||
* Font subsetting
|
||||
* See [fontkit](http://github.com/devongovett/fontkit) for more details on advanced glyph layout support.
|
||||
* Image embedding
|
||||
* Supports JPEG and PNG files (including indexed PNGs, and PNGs with transparency)
|
||||
* Annotations
|
||||
* Links
|
||||
* Notes
|
||||
* Highlights
|
||||
* Underlines
|
||||
* etc.
|
||||
|
||||
## Coming soon!
|
||||
|
||||
* Patterns fills
|
||||
* Outlines
|
||||
* PDF Security
|
||||
* Higher level APIs for creating tables and laying out content
|
||||
* More performance optimizations
|
||||
* Even more awesomeness, perhaps written by you! Please fork this repository and send me pull requests.
|
||||
|
||||
## Example
|
||||
|
||||
```coffeescript
|
||||
PDFDocument = require 'pdfkit'
|
||||
|
||||
# Create a document
|
||||
doc = new PDFDocument
|
||||
|
||||
# Pipe its output somewhere, like to a file or HTTP response
|
||||
# See below for browser usage
|
||||
doc.pipe fs.createWriteStream('output.pdf')
|
||||
|
||||
# Embed a font, set the font size, and render some text
|
||||
doc.font('fonts/PalatinoBold.ttf')
|
||||
.fontSize(25)
|
||||
.text('Some text with an embedded font!', 100, 100)
|
||||
|
||||
# Add an image, constrain it to a given size, and center it vertically and horizontally
|
||||
doc.image('path/to/image.png', {
|
||||
fit: [250, 300],
|
||||
align: 'center',
|
||||
valign: 'center'
|
||||
});
|
||||
|
||||
# Add another page
|
||||
doc.addPage()
|
||||
.fontSize(25)
|
||||
.text('Here is some vector graphics...', 100, 100)
|
||||
|
||||
# Draw a triangle
|
||||
doc.save()
|
||||
.moveTo(100, 150)
|
||||
.lineTo(100, 250)
|
||||
.lineTo(200, 250)
|
||||
.fill("#FF3300")
|
||||
|
||||
# Apply some transforms and render an SVG path with the 'even-odd' fill rule
|
||||
doc.scale(0.6)
|
||||
.translate(470, -380)
|
||||
.path('M 250,75 L 323,301 131,161 369,161 177,301 z')
|
||||
.fill('red', 'even-odd')
|
||||
.restore()
|
||||
|
||||
# Add some text with annotations
|
||||
doc.addPage()
|
||||
.fillColor("blue")
|
||||
.text('Here is a link!', 100, 100)
|
||||
.underline(100, 100, 160, 27, color: "#0000FF")
|
||||
.link(100, 100, 160, 27, 'http://google.com/')
|
||||
|
||||
# Finalize PDF file
|
||||
doc.end()
|
||||
```
|
||||
|
||||
[The PDF output from this example](http://pdfkit.org/demo/out.pdf) (with a few additions) shows the power of PDFKit — producing
|
||||
complex documents with a very small amount of code. For more, see the `demo` folder and the
|
||||
[PDFKit programming guide](http://pdfkit.org/docs/getting_started.html).
|
||||
|
||||
## Browser Usage
|
||||
|
||||
There are two ways to use PDFKit in the browser. The first is to use [Browserify](http://browserify.org/),
|
||||
which is a Node module packager for the browser with the familiar `require` syntax. The second is to use
|
||||
a prebuilt version of PDFKit, which you can [download from Github](https://github.com/devongovett/pdfkit/releases).
|
||||
|
||||
In addition to PDFKit, you'll need somewhere to stream the output to. HTML5 has a
|
||||
[Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object which can be used to store binary data, and
|
||||
get URLs to this data in order to display PDF output inside an iframe, or upload to a server, etc. In order to
|
||||
get a Blob from the output of PDFKit, you can use the [blob-stream](https://github.com/devongovett/blob-stream)
|
||||
module.
|
||||
|
||||
The following example uses Browserify to load `PDFKit` and `blob-stream`, but if you're not using Browserify,
|
||||
you can load them in whatever way you'd like (e.g. script tags).
|
||||
|
||||
```coffeescript
|
||||
# require dependencies
|
||||
PDFDocument = require 'pdfkit'
|
||||
blobStream = require 'blob-stream'
|
||||
|
||||
# create a document the same way as above
|
||||
doc = new PDFDocument
|
||||
|
||||
# pipe the document to a blob
|
||||
stream = doc.pipe(blobStream())
|
||||
|
||||
# add your content to the document here, as usual
|
||||
|
||||
# get a blob when you're done
|
||||
doc.end()
|
||||
stream.on 'finish', ->
|
||||
# get a blob you can do whatever you like with
|
||||
blob = stream.toBlob('application/pdf')
|
||||
|
||||
# or get a blob URL for display in the browser
|
||||
url = stream.toBlobURL('application/pdf')
|
||||
iframe.src = url
|
||||
```
|
||||
|
||||
You can see an interactive in-browser demo of PDFKit [here](http://pdfkit.org/demo/browser.html).
|
||||
|
||||
Note that in order to Browserify a project using PDFKit, you need to install the `brfs` module with npm,
|
||||
which is used to load built-in font data into the package. It is listed as a `devDependency` in
|
||||
PDFKit's `package.json`, so it isn't installed by default for Node users.
|
||||
If you forget to install it, Browserify will print an error message.
|
||||
|
||||
## Documentation
|
||||
|
||||
For complete API documentation and more examples, see the [PDFKit website](http://pdfkit.org/).
|
||||
|
||||
## License
|
||||
|
||||
PDFKit is available under the MIT license.
|
@ -0,0 +1,47 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
body {
|
||||
width: 1230px;
|
||||
margin: 20px auto;
|
||||
font-family: Georgia;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
#editor {
|
||||
width: 600px;
|
||||
height: 775px;
|
||||
margin-right: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>PDFKit Browser Demo</h1>
|
||||
<p><a href="http://pdfkit.org/">Website</a> | <a href="http://github.com/devongovett/pdfkit">Github</a></p>
|
||||
<div id="editor"></div>
|
||||
<iframe width="600" height="775"></iframe>
|
||||
<script src="bundle.js"></script>
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-48340245-1', 'pdfkit.org');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,76 @@
|
||||
var PDFDocument = require('../');
|
||||
var blobStream = require('blob-stream');
|
||||
var ace = require('brace');
|
||||
require('brace/mode/javascript');
|
||||
require('brace/theme/monokai');
|
||||
|
||||
var lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl. Suspendisse rhoncus nisl posuere tortor tempus et dapibus elit porta. Cras leo neque, elementum a rhoncus ut, vestibulum non nibh. Phasellus pretium justo turpis. Etiam vulputate, odio vitae tincidunt ultricies, eros odio dapibus nisi, ut tincidunt lacus arcu eu elit. Aenean velit erat, vehicula eget lacinia ut, dignissim non tellus. Aliquam nec lacus mi, sed vestibulum nunc. Suspendisse potenti. Curabitur vitae sem turpis. Vestibulum sed neque eget dolor dapibus porttitor at sit amet sem. Fusce a turpis lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;\nMauris at ante tellus. Vestibulum a metus lectus. Praesent tempor purus a lacus blandit eget gravida ante hendrerit. Cras et eros metus. Sed commodo malesuada eros, vitae interdum augue semper quis. Fusce id magna nunc. Curabitur sollicitudin placerat semper. Cras et mi neque, a dignissim risus. Nulla venenatis porta lacus, vel rhoncus lectus tempor vitae. Duis sagittis venenatis rutrum. Curabitur tempor massa tortor.';
|
||||
|
||||
function makePDF(PDFDocument, blobStream, lorem, iframe) {
|
||||
// create a document and pipe to a blob
|
||||
var doc = new PDFDocument();
|
||||
var stream = doc.pipe(blobStream());
|
||||
|
||||
// draw some text
|
||||
doc.fontSize(25)
|
||||
.text('Here is some vector graphics...', 100, 80);
|
||||
|
||||
// some vector graphics
|
||||
doc.save()
|
||||
.moveTo(100, 150)
|
||||
.lineTo(100, 250)
|
||||
.lineTo(200, 250)
|
||||
.fill("#FF3300");
|
||||
|
||||
doc.circle(280, 200, 50)
|
||||
.fill("#6600FF");
|
||||
|
||||
// an SVG path
|
||||
doc.scale(0.6)
|
||||
.translate(470, 130)
|
||||
.path('M 250,75 L 323,301 131,161 369,161 177,301 z')
|
||||
.fill('red', 'even-odd')
|
||||
.restore();
|
||||
|
||||
// and some justified text wrapped into columns
|
||||
doc.text('And here is some wrapped text...', 100, 300)
|
||||
.font('Times-Roman', 13)
|
||||
.moveDown()
|
||||
.text(lorem, {
|
||||
width: 412,
|
||||
align: 'justify',
|
||||
indent: 30,
|
||||
columns: 2,
|
||||
height: 300,
|
||||
ellipsis: true
|
||||
});
|
||||
|
||||
// end and display the document in the iframe to the right
|
||||
doc.end();
|
||||
stream.on('finish', function() {
|
||||
iframe.src = stream.toBlobURL('application/pdf');
|
||||
});
|
||||
}
|
||||
|
||||
var editor = ace.edit('editor');
|
||||
editor.setTheme('ace/theme/monokai');
|
||||
editor.getSession().setMode('ace/mode/javascript');
|
||||
editor.setValue(
|
||||
makePDF
|
||||
.toString()
|
||||
.split('\n').slice(1, -1).join('\n')
|
||||
.replace(/^ /mg, '')
|
||||
);
|
||||
editor.getSession().getSelection().clearSelection();
|
||||
|
||||
var iframe = document.querySelector('iframe');
|
||||
makePDF(PDFDocument, blobStream, lorem, iframe);
|
||||
|
||||
editor.getSession().on('change', function() {
|
||||
try {
|
||||
var fn = new Function("PDFDocument", "blobStream", "lorem", "iframe", editor.getValue());
|
||||
fn(PDFDocument, blobStream, lorem, iframe);
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
};
|
||||
});
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 2.3 MiB |
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
Binary file not shown.
After Width: | Height: | Size: 340 KiB |
Binary file not shown.
After Width: | Height: | Size: 391 KiB |
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
Binary file not shown.
@ -0,0 +1,92 @@
|
||||
PDFDocument = require '../'
|
||||
tiger = require './tiger'
|
||||
fs = require 'fs'
|
||||
|
||||
# Create a new PDFDocument
|
||||
doc = new PDFDocument
|
||||
doc.pipe fs.createWriteStream('out.pdf')
|
||||
|
||||
# Set some meta data
|
||||
doc.info['Title'] = 'Test Document'
|
||||
doc.info['Author'] = 'Devon Govett'
|
||||
|
||||
# Register a font name for use later
|
||||
doc.registerFont('Palatino', 'fonts/PalatinoBold.ttf')
|
||||
|
||||
# Set the font, draw some text, and embed an image
|
||||
doc.font('Palatino')
|
||||
.fontSize(25)
|
||||
.text('Some text with an embedded font!', 100, 100)
|
||||
.fontSize(18)
|
||||
.text('PNG and JPEG images:')
|
||||
.image('images/test.png', 100, 160, width: 412)
|
||||
.image('images/test.jpeg', 190, 400, height: 300)
|
||||
|
||||
# Add another page
|
||||
doc.addPage()
|
||||
.fontSize(25)
|
||||
.text 'Here is some vector graphics...', 100, 100
|
||||
|
||||
# Draw a triangle and a circle
|
||||
doc.save()
|
||||
.moveTo(100, 150)
|
||||
.lineTo(100, 250)
|
||||
.lineTo(200, 250)
|
||||
.fill("#FF3300")
|
||||
|
||||
doc.circle(280, 200, 50)
|
||||
.fill("#6600FF")
|
||||
|
||||
doc.scale(0.6)
|
||||
.translate(470, -380)
|
||||
.path('M 250,75 L 323,301 131,161 369,161 177,301 z') # render an SVG path
|
||||
.fill('red', 'even-odd') # fill using the even-odd winding rule
|
||||
.restore()
|
||||
|
||||
loremIpsum = '''
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl. Suspendisse rhoncus nisl posuere tortor tempus et dapibus elit porta. Cras leo neque, elementum a rhoncus ut, vestibulum non nibh. Phasellus pretium justo turpis. Etiam vulputate, odio vitae tincidunt ultricies, eros odio dapibus nisi, ut tincidunt lacus arcu eu elit. Aenean velit erat, vehicula eget lacinia ut, dignissim non tellus. Aliquam nec lacus mi, sed vestibulum nunc. Suspendisse potenti. Curabitur vitae sem turpis. Vestibulum sed neque eget dolor dapibus porttitor at sit amet sem. Fusce a turpis lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;
|
||||
Mauris at ante tellus. Vestibulum a metus lectus. Praesent tempor purus a lacus blandit eget gravida ante hendrerit. Cras et eros metus. Sed commodo malesuada eros, vitae interdum augue semper quis. Fusce id magna nunc. Curabitur sollicitudin placerat semper. Cras et mi neque, a dignissim risus. Nulla venenatis porta lacus, vel rhoncus lectus tempor vitae. Duis sagittis venenatis rutrum. Curabitur tempor massa tortor.
|
||||
'''
|
||||
|
||||
# Draw some text wrapped to 412 points wide
|
||||
doc.text('And here is some wrapped text...', 100, 300)
|
||||
.font('Helvetica', 13)
|
||||
.moveDown() # move down 1 line
|
||||
.text(loremIpsum, width: 412, align: 'justify', indent: 30, paragraphGap: 5)
|
||||
|
||||
# Add another page, and set the font back
|
||||
doc.addPage()
|
||||
.font('Palatino', 25)
|
||||
.text('Rendering some SVG paths...', 100, 100)
|
||||
.translate(220, 300)
|
||||
|
||||
# Render each path that makes up the tiger image
|
||||
for part in tiger
|
||||
doc.save()
|
||||
doc.path(part.path) # render an SVG path
|
||||
|
||||
if part['stroke-width']
|
||||
doc.lineWidth part['stroke-width']
|
||||
|
||||
if part.fill isnt 'none' and part.stroke isnt 'none'
|
||||
doc.fillAndStroke(part.fill, part.stroke)
|
||||
else
|
||||
unless part.fill is 'none'
|
||||
doc.fill(part.fill)
|
||||
|
||||
unless part.stroke is 'none'
|
||||
doc.stroke(part.stroke)
|
||||
|
||||
doc.restore()
|
||||
|
||||
# Add some text with annotations
|
||||
doc.addPage()
|
||||
.fillColor("blue")
|
||||
.text('Here is a link!', 100, 100, { link: 'http://google.com/', underline: true })
|
||||
|
||||
# Add a list with a font loaded from a TrueType collection file
|
||||
doc.fillColor('#000')
|
||||
.font('fonts/Chalkboard.ttc', 'Chalkboard', 16)
|
||||
.list(['One', 'Two', 'Three'], 100, 150)
|
||||
|
||||
doc.end()
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,4 @@
|
||||
*.html
|
||||
css/
|
||||
img/
|
||||
js/
|
@ -0,0 +1,22 @@
|
||||
# PDFKit Guide
|
||||
|
||||
The PDFKit guide can be read a number of ways. The first is online at [pdfkit.org](http://pdfkit.org/).
|
||||
You can also read the guide in PDF form, in this directory or [online](http://pdfkit.org/docs/guide.pdf).
|
||||
|
||||
Both the website and the PDF guide are generated from the Literate CoffeeScript (runnable Markdown) files
|
||||
in this directory. The examples are actually run when generating the PDF in order to show the results inline.
|
||||
The `generate.coffee` file in this directory is actually quite short. It parses the markdown files into a
|
||||
tree structure using [markdown-js](https://github.com/evilstreak/markdown-js), syntax highlights the code
|
||||
examples using [codemirror](https://github.com/marijnh/codemirror), compiles and runs the code examples and puts the results
|
||||
inline, and generates the PDF using PDFKit. You can read the generator script source code to get a feeling for
|
||||
how you might do something slightly more complex than the guide itself shows.
|
||||
|
||||
The markdown syntax used is pretty much standard, with a couple tweaks.
|
||||
|
||||
1. Code example output is references using the image notation, using the alt text as the example number starting from
|
||||
zero in the current file, and the title as the example output height. E.g. `![x](name "height")`.
|
||||
|
||||
2. Page breaks are added before `h1` and `h2`s, unless there are two in a row. `h3` is treated the same as `h2` but
|
||||
can be used to avoid this in the case you need multiple `h2`s on the same page.
|
||||
|
||||
3. The horizontal rule syntax (`* * *`) denotes an explicit page break
|
@ -0,0 +1,97 @@
|
||||
# Annotations in PDFKit
|
||||
|
||||
Annotations are interactive features of the PDF format, and they make it
|
||||
possible to include things like links and attached notes, or to highlight,
|
||||
underline or strikeout portions of text. Annotations are added using the
|
||||
various helper methods, and each type of annotation is defined by a rectangle
|
||||
and some other properties. Here is a list of the available annotation methods:
|
||||
|
||||
* `note(x, y, width, height, contents, options)`
|
||||
* `link(x, y, width, height, url, options)`
|
||||
* `highlight(x, y, width, height, options)`
|
||||
* `underline(x, y, width, height, options)`
|
||||
* `strike(x, y, width, height, options)`
|
||||
* `lineAnnotation(x1, y1, x2, y2, options)`
|
||||
* `rectAnnotation(x, y, width, height, options)`
|
||||
* `ellipseAnnotation(x, y, width, height, options)`
|
||||
* `textAnnotation(x, y, width, height, text, options)`
|
||||
|
||||
Many of the annotations have a `color` option that you can specify. You can
|
||||
use an array of RGB values, a hex color, or a named CSS color value for that
|
||||
option.
|
||||
|
||||
If you are adding an annotation to a piece of text, such as a link or
|
||||
underline, you will need to know the width and height of the text in order to
|
||||
create the required rectangle for the annotation. There are two methods that
|
||||
you can use to do that. To get the width of any piece of text in the current
|
||||
font, just call the `widthOfString` method with the string you want to
|
||||
measure. To get the line height in the current font, just call the
|
||||
`currentLineHeight` method.
|
||||
|
||||
You must remember that annotations have a stacking order. If you are putting
|
||||
more than one annotation on a single area and one of those annotations is a
|
||||
link, make sure that the link is the last one you add, otherwise it will be
|
||||
covered by another annotation and the user won't be able to click it.
|
||||
|
||||
* * *
|
||||
|
||||
Here is an example that uses a few of the annotation types.
|
||||
|
||||
# Add the link text
|
||||
doc.fontSize(25)
|
||||
.fillColor('blue')
|
||||
.text('This is a link!', 20, 0)
|
||||
|
||||
# Measure the text
|
||||
width = doc.widthOfString('This is a link!')
|
||||
height = doc.currentLineHeight()
|
||||
|
||||
# Add the underline and link annotations
|
||||
doc.underline(20, 0, width, height, color: 'blue')
|
||||
.link(20, 0, width, height, 'http://google.com/')
|
||||
|
||||
# Create the highlighted text
|
||||
doc.moveDown()
|
||||
.fillColor('black')
|
||||
.highlight(20, doc.y, doc.widthOfString('This text is highlighted!'), height)
|
||||
.text('This text is highlighted!')
|
||||
|
||||
# Create the crossed out text
|
||||
doc.moveDown()
|
||||
.strike(20, doc.y, doc.widthOfString('STRIKE!'), height)
|
||||
.text('STRIKE!')
|
||||
|
||||
The output of this example looks like this.
|
||||
|
||||
![0](images/annotations.png)
|
||||
|
||||
Annotations are currently not the easiest things to add to PDF documents, but
|
||||
that is the fault of the PDF spec itself. Calculating a rectangle manually isn't
|
||||
fun, but PDFKit makes it easier for a few common annotations applied to text, including
|
||||
links, underlines, and strikes. Here's an example showing two of them:
|
||||
|
||||
doc.fontSize 20
|
||||
.fillColor 'red'
|
||||
.text 'Another link!', 20, 0,
|
||||
link: 'http://apple.com/',
|
||||
underline: true
|
||||
|
||||
The output is as you'd expect:
|
||||
|
||||
![1]()
|
||||
|
||||
# You made it!
|
||||
|
||||
That's all there is to creating PDF documents in PDFKit. It's really quite
|
||||
simple to create beautiful multi-page printable documents using Node.js!
|
||||
|
||||
This guide was generated from Markdown/Literate CoffeeScript files using a
|
||||
PDFKit generation script. The examples are actually run to generate the output shown
|
||||
inline. The script generates both the website and the PDF guide, and
|
||||
can be found [on Github](http://github.com/devongovett/pdfkit/tree/master/docs/generate.coffee).
|
||||
Check it out if you want to see an example of a slightly more complicated renderer using
|
||||
a parser for Markdown and a syntax highlighter.
|
||||
|
||||
If you have any questions about what you've learned in this guide, please don't
|
||||
hesitate to [ask the author](http://twitter.com/devongovett) or post an issue
|
||||
on [Github](http://github.com/devongovett/pdfkit/issues). Enjoy!
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,254 @@
|
||||
fs = require 'fs'
|
||||
vm = require 'vm'
|
||||
md = require('markdown').markdown
|
||||
coffee = require 'coffee-script'
|
||||
CodeMirror = require 'codemirror/addon/runmode/runmode.node'
|
||||
PDFDocument = require '../'
|
||||
|
||||
process.chdir(__dirname)
|
||||
|
||||
# setup code mirror coffeescript mode
|
||||
filename = require.resolve('codemirror/mode/coffeescript/coffeescript')
|
||||
coffeeMode = fs.readFileSync filename, 'utf8'
|
||||
vm.runInNewContext coffeeMode, CodeMirror: CodeMirror
|
||||
|
||||
# style definitions for markdown
|
||||
styles =
|
||||
h1:
|
||||
font: 'fonts/Alegreya-Bold.ttf'
|
||||
fontSize: 25
|
||||
padding: 15
|
||||
h2:
|
||||
font: 'fonts/Alegreya-Bold.ttf'
|
||||
fontSize: 18
|
||||
padding: 10
|
||||
h3:
|
||||
font: 'fonts/Alegreya-Bold.ttf'
|
||||
fontSize: 18
|
||||
padding: 10
|
||||
para:
|
||||
font: 'fonts/Merriweather-Regular.ttf'
|
||||
fontSize: 10
|
||||
padding: 10
|
||||
code:
|
||||
font: 'fonts/SourceCodePro-Regular.ttf'
|
||||
fontSize: 9
|
||||
code_block:
|
||||
padding: 10
|
||||
background: '#2c2c2c'
|
||||
inlinecode:
|
||||
font: 'fonts/SourceCodePro-Bold.ttf'
|
||||
fontSize: 10
|
||||
listitem:
|
||||
font: 'fonts/Merriweather-Regular.ttf'
|
||||
fontSize: 10
|
||||
padding: 6
|
||||
link:
|
||||
font: 'fonts/Merriweather-Regular.ttf'
|
||||
fontSize: 10
|
||||
color: 'blue'
|
||||
underline: true
|
||||
example:
|
||||
font: 'Helvetica'
|
||||
fontSize: 9
|
||||
color: 'black'
|
||||
padding: 10
|
||||
|
||||
# syntax highlighting colors
|
||||
# based on Github's theme
|
||||
colors =
|
||||
keyword: '#cb4b16'
|
||||
atom: '#d33682'
|
||||
number: '#009999'
|
||||
def: '#2aa198'
|
||||
variable: '#108888'
|
||||
'variable-2': '#b58900'
|
||||
'variable-3': '#6c71c4'
|
||||
property: '#2aa198'
|
||||
operator: '#6c71c4'
|
||||
comment: '#999988'
|
||||
string: '#dd1144'
|
||||
'string-2': '#009926'
|
||||
meta: '#768E04'
|
||||
qualifier: '#b58900'
|
||||
builtin: '#d33682'
|
||||
bracket: '#cb4b16'
|
||||
tag: '#93a1a1'
|
||||
attribute: '#2aa198'
|
||||
header: '#586e75'
|
||||
quote: '#93a1a1'
|
||||
link: '#93a1a1'
|
||||
special: '#6c71c4'
|
||||
default: '#002b36'
|
||||
|
||||
# shared lorem ipsum text so we don't need to copy it into every example
|
||||
lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl. Suspendisse rhoncus nisl posuere tortor tempus et dapibus elit porta. Cras leo neque, elementum a rhoncus ut, vestibulum non nibh. Phasellus pretium justo turpis. Etiam vulputate, odio vitae tincidunt ultricies, eros odio dapibus nisi, ut tincidunt lacus arcu eu elit. Aenean velit erat, vehicula eget lacinia ut, dignissim non tellus. Aliquam nec lacus mi, sed vestibulum nunc. Suspendisse potenti. Curabitur vitae sem turpis. Vestibulum sed neque eget dolor dapibus porttitor at sit amet sem. Fusce a turpis lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;'
|
||||
|
||||
codeBlocks = []
|
||||
lastType = null
|
||||
|
||||
# This class represents a node in the markdown tree, and can render it to pdf
|
||||
class Node
|
||||
constructor: (tree) ->
|
||||
# special case for text nodes
|
||||
if typeof tree is 'string'
|
||||
@type = 'text'
|
||||
@text = tree
|
||||
return
|
||||
|
||||
@type = tree.shift()
|
||||
@attrs = {}
|
||||
|
||||
if typeof tree[0] is 'object' and not Array.isArray tree[0]
|
||||
@attrs = tree.shift()
|
||||
|
||||
# parse sub nodes
|
||||
@content = while tree.length
|
||||
new Node tree.shift()
|
||||
|
||||
switch @type
|
||||
when 'header'
|
||||
@type = 'h' + @attrs.level
|
||||
|
||||
when 'code_block'
|
||||
# use code mirror to syntax highlight the code block
|
||||
code = @content[0].text
|
||||
@content = []
|
||||
CodeMirror.runMode code, 'coffeescript', (text, style) =>
|
||||
color = colors[style] or colors.default
|
||||
opts =
|
||||
color: color
|
||||
continued: text isnt '\n'
|
||||
|
||||
@content.push new Node ['code', opts, text]
|
||||
|
||||
@content[@content.length - 1]?.attrs.continued = false
|
||||
codeBlocks.push code
|
||||
|
||||
when 'img'
|
||||
# images are used to generate inline example output
|
||||
# compiles the coffeescript to JS so it can be run
|
||||
# in the render method
|
||||
@type = 'example'
|
||||
code = codeBlocks[@attrs.alt]
|
||||
@code = coffee.compile code if code
|
||||
@height = +@attrs.title or 0
|
||||
|
||||
@style = styles[@type] or styles.para
|
||||
|
||||
# sets the styles on the document for this node
|
||||
setStyle: (doc) ->
|
||||
if @style.font
|
||||
doc.font @style.font
|
||||
|
||||
if @style.fontSize
|
||||
doc.fontSize @style.fontSize
|
||||
|
||||
if @style.color or @attrs.color
|
||||
doc.fillColor @style.color or @attrs.color
|
||||
else
|
||||
doc.fillColor 'black'
|
||||
|
||||
options = {}
|
||||
options.align = @style.align
|
||||
options.link = @attrs.href or false # override continued link
|
||||
options.continued = @attrs.continued if @attrs.continued?
|
||||
return options
|
||||
|
||||
# renders this node and its subnodes to the document
|
||||
render: (doc, continued = false) ->
|
||||
switch @type
|
||||
when 'example'
|
||||
@setStyle doc
|
||||
|
||||
# translate all points in the example code to
|
||||
# the current point in the document
|
||||
doc.moveDown()
|
||||
doc.save()
|
||||
doc.translate(doc.x, doc.y)
|
||||
x = doc.x
|
||||
y = doc.y
|
||||
doc.x = doc.y = 0
|
||||
|
||||
# run the example code with the document
|
||||
vm.runInNewContext @code,
|
||||
doc: doc
|
||||
lorem: lorem
|
||||
|
||||
# restore points and styles
|
||||
y += doc.y
|
||||
doc.restore()
|
||||
doc.x = x
|
||||
doc.y = y + @height
|
||||
when 'hr'
|
||||
doc.addPage()
|
||||
else
|
||||
# loop through subnodes and render them
|
||||
for fragment, index in @content
|
||||
if fragment.type is 'text'
|
||||
# add a new page for each heading, unless it follows another heading
|
||||
if @type in ['h1', 'h2'] and lastType? and lastType isnt 'h1'
|
||||
doc.addPage()
|
||||
|
||||
# set styles and whether this fragment is continued (for rich text wrapping)
|
||||
options = @setStyle doc
|
||||
options.continued ?= continued or index < @content.length - 1
|
||||
|
||||
# remove newlines unless this is code
|
||||
unless @type is 'code'
|
||||
fragment.text = fragment.text.replace(/[\r\n]\s*/g, ' ')
|
||||
|
||||
doc.text fragment.text, options
|
||||
else
|
||||
fragment.render doc, index < @content.length - 1 and @type isnt 'bulletlist'
|
||||
|
||||
lastType = @type
|
||||
|
||||
if @style.padding
|
||||
doc.y += @style.padding
|
||||
|
||||
# reads and renders a markdown/literate coffeescript file to the document
|
||||
render = (doc, filename) ->
|
||||
codeBlocks = []
|
||||
tree = md.parse fs.readFileSync(filename, 'utf8')
|
||||
tree.shift()
|
||||
|
||||
while tree.length
|
||||
node = new Node tree.shift()
|
||||
node.render(doc)
|
||||
|
||||
# renders the title page of the guide
|
||||
renderTitlePage = (doc) ->
|
||||
title = 'PDFKit Guide'
|
||||
author = 'By Devon Govett'
|
||||
version = 'Version ' + require('../package.json').version
|
||||
|
||||
doc.font 'fonts/AlegreyaSans-Light.ttf', 60
|
||||
doc.y = doc.page.height / 2 - doc.currentLineHeight()
|
||||
doc.text title, align: 'center'
|
||||
w = doc.widthOfString(title)
|
||||
|
||||
doc.fontSize 20
|
||||
doc.y -= 10
|
||||
doc.text author,
|
||||
align: 'center'
|
||||
indent: w - doc.widthOfString(author)
|
||||
|
||||
doc.font styles.para.font, 10
|
||||
doc.text version,
|
||||
align: 'center'
|
||||
indent: w - doc.widthOfString(version)
|
||||
|
||||
doc.addPage()
|
||||
|
||||
# render all sections of the guide and write the pdf file
|
||||
do ->
|
||||
doc = new PDFDocument
|
||||
doc.pipe fs.createWriteStream('guide.pdf')
|
||||
renderTitlePage doc
|
||||
render doc, 'getting_started.coffee.md'
|
||||
render doc, 'vector.coffee.md'
|
||||
render doc, 'text.coffee.md'
|
||||
render doc, 'images.coffee.md'
|
||||
render doc, 'annotations.coffee.md'
|
||||
doc.end()
|
@ -0,0 +1,108 @@
|
||||
jade = require 'jade'
|
||||
markdown = require('markdown').markdown
|
||||
fs = require 'fs'
|
||||
vm = require 'vm'
|
||||
coffee = require 'coffee-script'
|
||||
{exec} = require 'child_process'
|
||||
PDFDocument = require '../'
|
||||
|
||||
process.chdir(__dirname)
|
||||
|
||||
files = [
|
||||
'../README.md'
|
||||
'getting_started.coffee.md'
|
||||
'vector.coffee.md'
|
||||
'text.coffee.md'
|
||||
'images.coffee.md'
|
||||
'annotations.coffee.md'
|
||||
]
|
||||
|
||||
# shared lorem ipsum text so we don't need to copy it into every example
|
||||
lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl. Suspendisse rhoncus nisl posuere tortor tempus et dapibus elit porta. Cras leo neque, elementum a rhoncus ut, vestibulum non nibh. Phasellus pretium justo turpis. Etiam vulputate, odio vitae tincidunt ultricies, eros odio dapibus nisi, ut tincidunt lacus arcu eu elit. Aenean velit erat, vehicula eget lacinia ut, dignissim non tellus. Aliquam nec lacus mi, sed vestibulum nunc. Suspendisse potenti. Curabitur vitae sem turpis. Vestibulum sed neque eget dolor dapibus porttitor at sit amet sem. Fusce a turpis lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;'
|
||||
|
||||
extractHeaders = (tree) ->
|
||||
headers = []
|
||||
|
||||
for node, index in tree
|
||||
if node[0] is 'header' and (headers.length is 0 or node[1].level > 1)
|
||||
node[1].level = 2 if node[1].level > 2
|
||||
hash = node[2].toLowerCase().replace(/\s+/g, '_')
|
||||
node[1].id = hash
|
||||
headers.push
|
||||
hash: hash
|
||||
title: node[2]
|
||||
|
||||
return headers
|
||||
|
||||
imageIndex = 0
|
||||
generateImages = (tree) ->
|
||||
# find code blocks
|
||||
codeBlocks = []
|
||||
for node in tree
|
||||
if node[0] is 'code_block'
|
||||
codeBlocks.push node[1]
|
||||
|
||||
for node in tree
|
||||
if node[0] is 'para' and Array.isArray(node[1]) and node[1][0] is 'img'
|
||||
# compile the code
|
||||
attrs = node[1][1]
|
||||
code = codeBlocks[attrs.alt]
|
||||
code = coffee.compile code if code
|
||||
delete attrs.height # used for pdf generation
|
||||
|
||||
# create a PDF and run the example
|
||||
doc = new PDFDocument
|
||||
f = "img/#{imageIndex++}"
|
||||
file = fs.createWriteStream "#{f}.pdf"
|
||||
doc.pipe file
|
||||
|
||||
doc.translate doc.x, doc.y
|
||||
doc.scale 0.8
|
||||
doc.x = doc.y = 0
|
||||
|
||||
vm.runInNewContext code,
|
||||
doc: doc
|
||||
lorem: lorem
|
||||
|
||||
delete attrs.title
|
||||
delete attrs.alt
|
||||
attrs.href = "#{f}.png"
|
||||
|
||||
# write the PDF, convert to PNG using the mac `sips`
|
||||
# command line tool, and trim with graphicsmagick
|
||||
do (f) ->
|
||||
file.on 'finish', ->
|
||||
exec "sips -s format png #{f}.pdf --out #{f}.png", ->
|
||||
fs.unlink "#{f}.pdf"
|
||||
exec "gm convert #{f}.png -trim #{f}.png"
|
||||
|
||||
doc.end()
|
||||
|
||||
pages = []
|
||||
for file in files
|
||||
content = fs.readFileSync file, 'utf8'
|
||||
|
||||
# turn github highlighted code blocks into normal markdown code blocks
|
||||
content = content.replace /^```coffeescript\n((:?.|\n)*?)\n```/mg, (m, $1) ->
|
||||
' ' + $1.split('\n').join('\n ')
|
||||
|
||||
tree = markdown.parse(content)
|
||||
headers = extractHeaders(tree)
|
||||
generateImages(tree)
|
||||
|
||||
file = file
|
||||
.replace(/\.coffee\.md$/, '')
|
||||
.replace(/README\.md/, 'index')
|
||||
|
||||
pages.push
|
||||
file: file
|
||||
url: '/docs/' + file + '.html'
|
||||
title: headers[0].title
|
||||
headers: headers.slice(1)
|
||||
content: markdown.toHTML(tree)
|
||||
|
||||
for page, index in pages
|
||||
page.pages = pages
|
||||
page.index = index
|
||||
html = jade.renderFile 'template.jade', page
|
||||
fs.writeFileSync page.file + '.html', html, 'utf8'
|
@ -0,0 +1,193 @@
|
||||
# Getting Started with PDFKit
|
||||
|
||||
### Installation
|
||||
|
||||
Installation uses the [npm](http://npmjs.org/) package manager. Just type the
|
||||
following command after installing npm.
|
||||
|
||||
npm install pdfkit
|
||||
|
||||
### Creating a document
|
||||
|
||||
Creating a PDFKit document is quite simple. Just require the `pdfkit` module
|
||||
in your CoffeeScript or JavaScript source file and create an instance of the
|
||||
`PDFDocument` class.
|
||||
|
||||
PDFDocument = require 'pdfkit'
|
||||
doc = new PDFDocument
|
||||
|
||||
`PDFDocument` instances are readable Node streams. They don't get saved anywhere automatically,
|
||||
but you can call the `pipe` method to send the output of the PDF document to another
|
||||
writable Node stream as it is being written. When you're done with your document, call
|
||||
the `end` method to finalize it. Here is an example showing how to pipe to a file or an HTTP response.
|
||||
|
||||
doc.pipe fs.createWriteStream('/path/to/file.pdf') # write to PDF
|
||||
doc.pipe res # HTTP response
|
||||
|
||||
# add stuff to PDF here using methods described below...
|
||||
|
||||
# finalize the PDF and end the stream
|
||||
doc.end()
|
||||
|
||||
The `write` and `output` methods found in PDFKit before version 0.5 are now deprecated.
|
||||
|
||||
## Using PDFKit in the browser
|
||||
|
||||
As of version 0.6, PDFKit can be used in the browser as well as in Node!
|
||||
There are two ways to use PDFKit in the browser. The first is to use [Browserify](http://browserify.org/),
|
||||
which is a Node module packager for the browser with the familiar `require` syntax. The second is to use
|
||||
a prebuilt version of PDFKit, which you can [download from Github](https://github.com/devongovett/pdfkit/releases).
|
||||
|
||||
Using PDFKit in the browser is exactly the same as using it in Node, except you'll want to pipe the
|
||||
output to a destination supported in the browser, such as a
|
||||
[Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob). Blobs can be used
|
||||
to generate a URL to allow display of generated PDFs directly in the browser via an `iframe`, or they can
|
||||
be used to upload the PDF to a server, or trigger a download in the user's browser.
|
||||
|
||||
To get a Blob from a `PDFDocument`, you should pipe it to a [blob-stream](https://github.com/devongovett/blob-stream),
|
||||
which is a module that generates a Blob from any Node-style stream. The following example uses Browserify to load
|
||||
`PDFKit` and `blob-stream`, but if you're not using Browserify, you can load them in whatever way you'd like (e.g. script tags).
|
||||
|
||||
# require dependencies
|
||||
PDFDocument = require 'pdfkit'
|
||||
blobStream = require 'blob-stream'
|
||||
|
||||
# create a document the same way as above
|
||||
doc = new PDFDocument
|
||||
|
||||
# pipe the document to a blob
|
||||
stream = doc.pipe(blobStream())
|
||||
|
||||
# add your content to the document here, as usual
|
||||
|
||||
# get a blob when you're done
|
||||
doc.end()
|
||||
stream.on 'finish', ->
|
||||
# get a blob you can do whatever you like with
|
||||
blob = stream.toBlob('application/pdf')
|
||||
|
||||
# or get a blob URL for display in the browser
|
||||
url = stream.toBlobURL('application/pdf')
|
||||
iframe.src = url
|
||||
|
||||
You can see an interactive in-browser demo of PDFKit [here](http://pdfkit.org/demo/browser.html).
|
||||
|
||||
Note that in order to Browserify a project using PDFKit, you need to install the `brfs` module with npm,
|
||||
which is used to load built-in font data into the package. It is listed as a `devDependency` in
|
||||
PDFKit's `package.json`, so it isn't installed by default for Node users.
|
||||
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 unless you provide `autoFirstPage: false`. Subsequent pages must be added by you. Luckily, it is
|
||||
quite simple!
|
||||
|
||||
doc.addPage()
|
||||
|
||||
To add some content every time a page is created, either by calling `addPage()` or automatically, you can use the `pageAdded` event.
|
||||
|
||||
doc.on 'pageAdded', ->
|
||||
doc.text "Page Title"
|
||||
|
||||
You can also set some options for the page, such as it's size and orientation.
|
||||
|
||||
The `layout` property can be either `portrait` (the default) or `landscape`.
|
||||
The `size` property can be either an array specifying `[width, height]` in PDF
|
||||
points (72 per inch), or a string specifying a predefined size. A
|
||||
list of the predefined paper sizes can be seen [here](https://github.com/devongovett/pdfkit/blob/b13423bf0a391ed1c33a2e277bc06c00cabd6bf9/lib/page.coffee#L72-L122). The
|
||||
default is `letter`.
|
||||
|
||||
Passing a page options object to the `PDFDocument` constructor will
|
||||
set the default paper size and layout for every page in the document, which is
|
||||
then overridden by individual options passed to the `addPage` method.
|
||||
|
||||
You can set the page margins in two ways. The first is by setting the `margin`
|
||||
property (singular) to a number, which applies that margin to all edges. The
|
||||
other way is to set the `margins` property (plural) to an object with `top`,
|
||||
`bottom`, `left`, and `right` values. The default is a 1 inch (72 point) margin
|
||||
on all sides.
|
||||
|
||||
For example:
|
||||
|
||||
# Add a 50 point margin on all sides
|
||||
doc.addPage
|
||||
margin: 50
|
||||
|
||||
|
||||
# Add different margins on each side
|
||||
doc.addPage
|
||||
margins:
|
||||
top: 50
|
||||
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
|
||||
|
||||
PDF documents can have various metadata associated with them, such as the
|
||||
title, or author of the document. You can add that information by adding it to
|
||||
the `doc.info` object, or by passing an info object into the document at
|
||||
creation time.
|
||||
|
||||
Here is a list of all of the properties you can add to the document metadata.
|
||||
According to the PDF spec, each property must have it's first letter
|
||||
capitalized.
|
||||
|
||||
* `Title` - the title of the document
|
||||
* `Author` - the name of the author
|
||||
* `Subject` - the subject of the document
|
||||
* `Keywords` - keywords associated with the document
|
||||
* `CreationDate` - the date the document was created (added automatically by PDFKit)
|
||||
* `ModDate` - the date the document was last modified
|
||||
|
||||
### Adding content
|
||||
|
||||
Once you've created a `PDFDocument` instance, you can add content to the
|
||||
document. Check out the other sections described in this document to
|
||||
learn about each type of content you can add.
|
||||
|
||||
That's the basics! Now let's move on to PDFKit's powerful vector graphics
|
||||
abilities.
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
|
||||
# Images in PDFKit
|
||||
|
||||
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).
|
||||
Otherwise, it is positioned absolutely at the specified point. The image will
|
||||
be scaled according to the following options.
|
||||
|
||||
* Neither `width` or `height` provided - image is rendered at full size
|
||||
* `width` provided but not `height` - image is scaled proportionally to fit in the provided `width`
|
||||
* `height` provided but not `width` - image is scaled proportionally to fit in the provided `height`
|
||||
* Both `width` and `height` provided - image is stretched to the dimensions provided
|
||||
* `scale` factor provided - image is scaled proportionally by the provided scale factor
|
||||
* `fit` array provided - image is scaled proportionally to fit within the passed width and height
|
||||
* `cover` array provided - image is scaled proportionally to completely cover the rectangle defined by the passed width and height
|
||||
|
||||
When a `fit` or `cover` array is provided, PDFKit accepts these additional options:
|
||||
* `align` - horizontally align the image, the possible values are `'left'`, `'center'` and `'right'`
|
||||
* `valign` - vertically align the image, the possible values are `'top'`, `'center'` and `'bottom'`
|
||||
|
||||
Here is an example showing some of these options.
|
||||
|
||||
# Scale proprotionally to the specified width
|
||||
doc.image('images/test.jpeg', 0, 15, width: 300)
|
||||
.text('Proportional to width', 0, 0)
|
||||
|
||||
# Fit the image within the dimensions
|
||||
doc.image('images/test.jpeg', 320, 15, fit: [100, 100])
|
||||
.rect(320, 15, 100, 100)
|
||||
.stroke()
|
||||
.text('Fit', 320, 0)
|
||||
|
||||
# Stretch the image
|
||||
doc.image('images/test.jpeg', 320, 145, width: 200, height: 100)
|
||||
.text('Stretch', 320, 130)
|
||||
|
||||
# Scale the image
|
||||
doc.image('images/test.jpeg', 320, 280, scale: 0.25)
|
||||
.text('Scale', 320, 265)
|
||||
|
||||
# Fit the image in the dimensions, and center it both horizontally and vertically
|
||||
doc.image('images/test.jpeg', 430, 15, fit: [100, 100], align: 'center', valign: 'center')
|
||||
.rect(430, 15, 100, 100)
|
||||
.stroke()
|
||||
.text('Centered', 430, 0)
|
||||
|
||||
* * *
|
||||
|
||||
This example produces the following output:
|
||||
|
||||
![0](images/images.png "150")
|
||||
|
||||
That is all there is to adding images to your PDF documents with PDFKit. Now
|
||||
let's look at adding annotations.
|
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
@ -0,0 +1,55 @@
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
title= title
|
||||
link(rel='stylesheet', href='http://fonts.googleapis.com/css?family=Source+Code+Pro:400,700|Alegreya:700|Merriweather')
|
||||
link(rel='stylesheet', href='/docs/css/index.css')
|
||||
link(rel='stylesheet', href='/docs/css/github.css')
|
||||
body
|
||||
nav(class='sidebar')
|
||||
ul
|
||||
li
|
||||
a(href='/', class=(/index/.test(url) ? 'selected' : '')) Home
|
||||
li
|
||||
a(href=pages[0].url) Documentation
|
||||
ul
|
||||
each page in pages.slice(1)
|
||||
li
|
||||
a(href=page.url, class=page.title == title ? 'selected' : '')
|
||||
= page.title.replace(/(with|in) PDFKit/, '')
|
||||
|
||||
- if (page.title == title && headers.length)
|
||||
ul
|
||||
each header in headers
|
||||
li
|
||||
a(href='#' + header.hash)= header.title
|
||||
|
||||
li
|
||||
a(href='/docs/guide.pdf') PDF Guide
|
||||
li
|
||||
a(href='/demo/out.pdf') Example PDF
|
||||
li
|
||||
a(href='/demo/browser.html') Interactive Browser Demo
|
||||
li
|
||||
a(href='http://github.com/devongovett/pdfkit') Source Code
|
||||
|
||||
.main
|
||||
!= content
|
||||
nav
|
||||
- if (index > 0)
|
||||
a(href=pages[index - 1].url, class='previous') Previous
|
||||
|
||||
- if (index < pages.length - 1)
|
||||
a(href=pages[index + 1].url, class='next') Next
|
||||
|
||||
script(src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js')
|
||||
script(src='/docs/js/scroll.js')
|
||||
script(src='/docs/js/highlight.pack.js')
|
||||
script.
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-48340245-1', 'pdfkit.org');
|
||||
ga('send', 'pageview');
|
@ -0,0 +1,221 @@
|
||||
# Text in PDFKit
|
||||
|
||||
## The basics
|
||||
|
||||
PDFKit makes adding text to documents quite simple, and includes many options
|
||||
to customize the display of the output. Adding text to a document is as simple
|
||||
as calling the `text` method.
|
||||
|
||||
doc.text 'Hello world!'
|
||||
|
||||
Internally, PDFKit keeps track of the current X and Y position of text as it
|
||||
is added to the document. This way, subsequent calls to the `text` method will
|
||||
automatically appear as new lines below the previous line. However, you can
|
||||
modify the position of text by passing X and Y coordinates to the `text`
|
||||
method after the text itself.
|
||||
|
||||
doc.text 'Hello world!', 100, 100
|
||||
|
||||
If you want to move down or up by lines, just call the `moveDown` or `moveUp`
|
||||
method with the number of lines you'd like to move (1 by default).
|
||||
|
||||
## Line wrapping and justification
|
||||
|
||||
PDFKit includes support for line wrapping out of the box! If no options are
|
||||
given, text is automatically wrapped within the page margins and placed in the
|
||||
document flow below any previous text, or at the top of the page. PDFKit
|
||||
automatically inserts new pages as necessary so you don't have to worry about
|
||||
doing that for long pieces of text. PDFKit can also automatically wrap text
|
||||
into multiple columns.
|
||||
|
||||
The text will automatically wrap unless you set the `lineBreak` option to `false`.
|
||||
By default it will wrap to the page margin, but the `width` option allows
|
||||
you to set a different width the text should be wrapped to.
|
||||
If you set the `height` option, the text will be clipped to the number of
|
||||
lines that can fit in that height.
|
||||
|
||||
When line wrapping is enabled, you can choose a text justification. There are
|
||||
four options: `left` (the default), `center`, `right`, and `justify`. They
|
||||
work just as they do in your favorite word processor, but here is an example
|
||||
showing their use in a text box.
|
||||
|
||||
lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl.'
|
||||
|
||||
doc.fontSize 8
|
||||
doc.text 'This text is left aligned. ' + lorem,
|
||||
width: 410
|
||||
align: 'left'
|
||||
|
||||
doc.moveDown()
|
||||
doc.text 'This text is centered. ' + lorem,
|
||||
width: 410
|
||||
align: 'center'
|
||||
|
||||
doc.moveDown()
|
||||
doc.text 'This text is right aligned. ' + lorem,
|
||||
width: 410
|
||||
align: 'right'
|
||||
|
||||
doc.moveDown()
|
||||
doc.text 'This text is justified. ' + lorem,
|
||||
width: 410
|
||||
align: 'justify'
|
||||
|
||||
# draw bounding rectangle
|
||||
doc.rect(doc.x, 0, 410, doc.y).stroke()
|
||||
|
||||
|
||||
The output of this example, looks like this:
|
||||
|
||||
![2](images/alignments.png)
|
||||
|
||||
## Text styling
|
||||
|
||||
PDFKit has many options for controlling the look of text added to PDF
|
||||
documents, which can be passed to the `text` method. They are enumerated
|
||||
below.
|
||||
|
||||
* `lineBreak` - set to `false` to disable line wrapping all together
|
||||
* `width` - the width that text should be wrapped to (by default, the page width minus the left and right margin)
|
||||
* `height` - the maximum height that text should be clipped to
|
||||
* `ellipsis` - the character to display at the end of the text when it is too long. Set to `true` to use the default character.
|
||||
* `columns` - the number of columns to flow the text into
|
||||
* `columnGap` - the amount of space between each column (1/4 inch by default)
|
||||
* `indent` - the amount in PDF points (72 per inch) to indent each paragraph of text
|
||||
* `paragraphGap` - the amount of space between each paragraph of text
|
||||
* `lineGap` - the amount of space between each line of text
|
||||
* `wordSpacing` - the amount of space between each word in the text
|
||||
* `characterSpacing` - the amount of space between each character in the text
|
||||
* `fill` - whether to fill the text (`true` by default)
|
||||
* `stroke` - whether to stroke the text
|
||||
* `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
|
||||
* `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.
|
||||
|
||||
Additionally, the fill and stroke color and opacity methods described in the
|
||||
[vector graphics section](vector.html) are applied to text content as well.
|
||||
|
||||
* * *
|
||||
|
||||
Here is an example combining some of the options above, wrapping a piece of text into three columns, in a specified width and height.
|
||||
|
||||
lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl. Suspendisse rhoncus nisl posuere tortor tempus et dapibus elit porta. Cras leo neque, elementum a rhoncus ut, vestibulum non nibh. Phasellus pretium justo turpis. Etiam vulputate, odio vitae tincidunt ultricies, eros odio dapibus nisi, ut tincidunt lacus arcu eu elit. Aenean velit erat, vehicula eget lacinia ut, dignissim non tellus. Aliquam nec lacus mi, sed vestibulum nunc. Suspendisse potenti. Curabitur vitae sem turpis. Vestibulum sed neque eget dolor dapibus porttitor at sit amet sem. Fusce a turpis lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;'
|
||||
|
||||
doc.text lorem,
|
||||
columns: 3
|
||||
columnGap: 15
|
||||
height: 100
|
||||
width: 465
|
||||
align: 'justify'
|
||||
|
||||
The output looks like this:
|
||||
|
||||
![3]()
|
||||
|
||||
## Text measurements
|
||||
|
||||
If you're working with documents that require precise layout, you may need to know the
|
||||
size of a piece of text. PDFKit has two methods to achieve this: `widthOfString(text, options)`
|
||||
and `heightOfString(text, options)`. Both methods use the same options described in the
|
||||
Text styling section, and take into account the eventual line wrapping.
|
||||
|
||||
## Lists
|
||||
|
||||
The `list` method creates a bulleted list. It accepts as arguments an array of strings,
|
||||
and the optional `x`, `y` position. You can create complex multilevel lists by using nested arrays.
|
||||
Lists use the following additional options:
|
||||
* `bulletRadius`
|
||||
* `textIndent`
|
||||
* `bulletIndent`
|
||||
|
||||
## Rich Text
|
||||
|
||||
As mentioned above, PDFKit supports a simple form of rich text via the `continued` option.
|
||||
When set to true, PDFKit will retain the text wrapping state between `text` calls. This way,
|
||||
when you call text again after changing the text styles, the wrapping will continue right
|
||||
where it left off.
|
||||
|
||||
The options given to the first `text` call are also retained for subsequent calls after a
|
||||
`continued` one, but of course you can override them. In the following example, the `width`
|
||||
option from the first `text` call is retained by the second call.
|
||||
|
||||
doc.fillColor 'green'
|
||||
.text lorem.slice(0, 500),
|
||||
width: 465
|
||||
continued: yes
|
||||
.fillColor 'red'
|
||||
.text lorem.slice(500)
|
||||
|
||||
Here is the output:
|
||||
|
||||
![4]()
|
||||
|
||||
## Fonts
|
||||
|
||||
The PDF format defines 14 standard fonts that can be used in PDF documents. PDFKit supports each of them out of the box.
|
||||
Besides Symbol and Zapf Dingbats this includes 4 styles (regular, bold, italic/oblique, bold+italic) of Helvetica,
|
||||
Courier, and Times. To switch between standard fonts, call the `font` method with the corresponding Label:
|
||||
* `'Courier'`
|
||||
* `'Courier-Bold'`
|
||||
* `'Courier-Oblique'`
|
||||
* `'Courier-BoldOblique'`
|
||||
* `'Helvetica'`
|
||||
* `'Helvetica-Bold'`
|
||||
* `'Helvetica-Oblique'`
|
||||
* `'Helvetica-BoldOblique'`
|
||||
* `'Symbol'`
|
||||
* `'Times-Roman'`
|
||||
* `'Times-Bold'`
|
||||
* `'Times-Italic'`
|
||||
* `'Times-BoldItalic'`
|
||||
* `'ZapfDingbats'`
|
||||
|
||||
The PDF format also allows fonts to be embedded right in the document. PDFKit supports
|
||||
embedding TrueType (`.ttf`), OpenType (`.otf`), WOFF, WOFF2, TrueType Collection (`.ttc`),
|
||||
and Datafork TrueType (`.dfont`) fonts.
|
||||
|
||||
To change the font used to render text, just call the `font` method. If you
|
||||
are using a standard PDF font, just pass the name to the `font` method.
|
||||
Otherwise, pass the path to the font file, or a `Buffer` containing the font data.
|
||||
If the font is a collection font (`.ttc` and `.dfont` files), meaning that it
|
||||
contains multiple styles in the same file, you should pass the name of the style
|
||||
to be extracted from the collection.
|
||||
|
||||
Here is an example showing how to set the font in each case.
|
||||
|
||||
# Set the font size
|
||||
doc.fontSize(18)
|
||||
|
||||
# Using a standard PDF font
|
||||
doc.font('Times-Roman')
|
||||
.text('Hello from Times Roman!')
|
||||
.moveDown(0.5)
|
||||
|
||||
# Using a TrueType font (.ttf)
|
||||
doc.font('fonts/GoodDog.ttf')
|
||||
.text('This is Good Dog!')
|
||||
.moveDown(0.5)
|
||||
|
||||
# Using a collection font (.ttc or .dfont)
|
||||
doc.font('fonts/Chalkboard.ttc', 'Chalkboard-Bold')
|
||||
.text('This is Chalkboard, not Comic Sans.')
|
||||
|
||||
The output of this example looks like this:
|
||||
|
||||
![5](images/fonts.png)
|
||||
|
||||
Another nice feature of the PDFKit font support, is the ability to register a
|
||||
font file under a name for use later rather than entering the path to the font
|
||||
every time you want to use it.
|
||||
|
||||
# Register a font
|
||||
doc.registerFont('Heading Font', 'fonts/Chalkboard.ttc', 'Chalkboard-Bold')
|
||||
|
||||
# Use the font later
|
||||
doc.font('Heading Font')
|
||||
.text('This is a heading.')
|
||||
|
||||
That's about all there is too it for text in PDFKit. Let's move on now to
|
||||
images.
|
@ -0,0 +1,326 @@
|
||||
# Vector Graphics in PDFKit
|
||||
|
||||
## An introduction to vector graphics
|
||||
|
||||
Unlike images which are defined by pixels, vector graphics are defined through
|
||||
a series of drawing commands. This makes vector graphics scalable to any size
|
||||
without a reduction in quality (pixelization). The PDF format was designed
|
||||
with vector graphics in mind, so creating vector drawings is very easy. The
|
||||
PDFKit vector graphics APIs are very similar to that of the HTML5 canvas
|
||||
element, so if you are familiar at all with that API, you will find PDFKit
|
||||
easy to pick up.
|
||||
|
||||
### Creating basic shapes
|
||||
|
||||
Shapes are defined by a series of lines and curves. `lineTo`, `bezierCurveTo`
|
||||
and `quadraticCurveTo` all draw from the current point (which you can set with
|
||||
`moveTo`) to the specified point (always the last two arguments). Bezier
|
||||
curves use two control points and quadratic curves use just one. Here is an
|
||||
example that illustrates defining a path.
|
||||
|
||||
doc.moveTo(0, 20) # set the current point
|
||||
.lineTo(100, 160) # draw a line
|
||||
.quadraticCurveTo(130, 200, 150, 120) # draw a quadratic curve
|
||||
.bezierCurveTo(190, -40, 200, 200, 300, 150) # draw a bezier curve
|
||||
.lineTo(400, 90) # draw another line
|
||||
.stroke() # stroke the path
|
||||
|
||||
The output of this example looks like this:
|
||||
|
||||
![0](images/path.png "170")
|
||||
|
||||
One thing to notice about this example is the use of method chaining. All
|
||||
methods in PDFKit are chainable, meaning that you can call one method right
|
||||
after the other without referencing the `doc` variable again. Of course, this
|
||||
is an option, so if you don't like how the code looks when chained, you don't
|
||||
have to write it that way.
|
||||
|
||||
## SVG paths
|
||||
|
||||
PDFKit includes an SVG path parser, so you can include paths written in the
|
||||
SVG path syntax in your PDF documents. This makes it simple to include vector
|
||||
graphics elements produced in many popular editors such as Inkscape or Adobe
|
||||
Illustrator. The previous example could also be written using the SVG path
|
||||
syntax like this.
|
||||
|
||||
doc.path('M 0,20 L 100,160 Q 130,200 150,120 C 190,-40 200,200 300,150 L 400,90')
|
||||
.stroke()
|
||||
|
||||
![1](images/path.png "170")
|
||||
|
||||
The PDFKit SVG parser supports all of the command types supported by SVG, so
|
||||
any valid SVG path you throw at it should work as expected.
|
||||
|
||||
## Shape helpers
|
||||
|
||||
PDFKit also includes some helpers that make defining common shapes much
|
||||
easier. Here is a list of the helpers.
|
||||
|
||||
* `rect(x, y, width, height)`
|
||||
* `roundedRect(x, y, width, height, cornerRadius)`
|
||||
* `ellipse(centerX, centerY, radiusX, radiusY = radiusX)`
|
||||
* `circle(centerX, centerY, radius)`
|
||||
* `polygon(points...)`
|
||||
|
||||
The last one, `polygon`, allows you to pass in a list of points (arrays of x,y
|
||||
pairs), and it will create the shape by moving to the first point, and then
|
||||
drawing lines to each consecutive point. Here is how you'd draw a triangle
|
||||
with the polygon helper.
|
||||
|
||||
doc.polygon [100, 0], [50, 100], [150, 100]
|
||||
doc.stroke()
|
||||
|
||||
The output of this example looks like this:
|
||||
|
||||
![2](images/triangle.png "100")
|
||||
|
||||
## Fill and stroke styles
|
||||
|
||||
So far we have only been stroking our paths, but you can also fill them with
|
||||
the `fill` method, and both fill and stroke the same path with the
|
||||
`fillAndStroke` method. Note that calling `fill` and then `stroke`
|
||||
consecutively will not work because of a limitation in the PDF spec. Use the
|
||||
`fillAndStroke` method if you want to accomplish both operations on the same
|
||||
path.
|
||||
|
||||
In order to make our drawings interesting, we really need to give them some
|
||||
style. PDFKit has many methods designed to do just that.
|
||||
|
||||
* `lineWidth`
|
||||
* `lineCap`
|
||||
* `lineJoin`
|
||||
* `miterLimit`
|
||||
* `dash`
|
||||
* `fillColor`
|
||||
* `strokeColor`
|
||||
* `opacity`
|
||||
* `fillOpacity`
|
||||
* `strokeOpacity`
|
||||
|
||||
Some of these are pretty self explanatory, but let's go through a few of them.
|
||||
|
||||
## Line cap and line join
|
||||
|
||||
The `lineCap` and `lineJoin` properties accept constants describing what they
|
||||
should do. This is best illustrated by an example.
|
||||
|
||||
# these examples are easier to see with a large line width
|
||||
doc.lineWidth(25)
|
||||
|
||||
# line cap settings
|
||||
doc.lineCap('butt')
|
||||
.moveTo(50, 20)
|
||||
.lineTo(100, 20)
|
||||
.stroke()
|
||||
|
||||
doc.lineCap('round')
|
||||
.moveTo(150, 20)
|
||||
.lineTo(200, 20)
|
||||
.stroke()
|
||||
|
||||
# square line cap shown with a circle instead of a line so you can see it
|
||||
doc.lineCap('square')
|
||||
.moveTo(250, 20)
|
||||
.circle(275, 30, 15)
|
||||
.stroke()
|
||||
|
||||
# line join settings
|
||||
doc.lineJoin('miter')
|
||||
.rect(50, 100, 50, 50)
|
||||
.stroke()
|
||||
|
||||
doc.lineJoin('round')
|
||||
.rect(150, 100, 50, 50)
|
||||
.stroke()
|
||||
|
||||
doc.lineJoin('bevel')
|
||||
.rect(250, 100, 50, 50)
|
||||
.stroke()
|
||||
|
||||
The output of this example looks like this.
|
||||
|
||||
![3](images/line_styles.png "220")
|
||||
|
||||
## Dashed lines
|
||||
|
||||
The `dash` method allows you to create non-continuous dashed lines. It takes a
|
||||
length specifying how long each dash should be, as well as an optional hash
|
||||
describing the additional properties `space` and `phase`.
|
||||
|
||||
The `space` option defines the length of the space between each dash, and the `phase` option
|
||||
defines the starting point of the sequence of dashes. By default the `space`
|
||||
attribute is equal to the `length` and the `phase` attribute is set to `0`.
|
||||
You can use the `undash` method to make the line solid again.
|
||||
|
||||
The following example draws a circle with a dashed line where the space
|
||||
between the dashes is double the length of each dash.
|
||||
|
||||
doc.circle(100, 50, 50)
|
||||
.dash(5, space: 10)
|
||||
.stroke()
|
||||
|
||||
The output of this example looks like this:
|
||||
|
||||
![4](images/dash.png "100")
|
||||
|
||||
## Color
|
||||
|
||||
What is a drawing without color? PDFKit makes it simple to set the fill and
|
||||
stroke color and opacity. You can pass an array specifying an RGB or CMYK
|
||||
color, a hex color string, or use any of the named CSS colors.
|
||||
|
||||
The `fillColor` and `strokeColor` methods accept an optional second argument as a shortcut for
|
||||
setting the `fillOpacity` and `strokeOpacity`. Finally, the `opacity` method
|
||||
is a convenience method that sets both the fill and stroke opacity to the same
|
||||
value.
|
||||
|
||||
The `fill` and `stroke` methods also accept a color as an argument so
|
||||
that you don't have to call `fillColor` or `strokeColor` beforehand. The
|
||||
`fillAndStroke` method accepts both fill and stroke colors as arguments.
|
||||
|
||||
doc.circle(100, 50, 50)
|
||||
.lineWidth(3)
|
||||
.fillOpacity(0.8)
|
||||
.fillAndStroke("red", "#900")
|
||||
|
||||
This example produces the following output:
|
||||
|
||||
![5](images/color.png "100")
|
||||
|
||||
## Gradients
|
||||
|
||||
PDFKit also supports gradient fills. Gradients can be used just like color fills,
|
||||
and are applied with the same methods (e.g. `fillColor`, or just `fill`). Before
|
||||
you can apply a gradient with these methods, however, you must create a gradient object.
|
||||
|
||||
There are two types of gradients: linear and radial. They are created by the `linearGradient`
|
||||
and `radialGradient` methods. Their function signatures are listed below:
|
||||
|
||||
* `linearGradient(x1, y1, x2, y2)` - `x1,y1` is the start point, `x2,y2` is the end point
|
||||
* `radialGradient(x1, y1, r1, x2, y2, r2)` - `r1` is the inner radius, `r2` is the outer radius
|
||||
|
||||
Once you have a gradient object, you need to create color stops at points along that gradient.
|
||||
Stops are defined at percentage values (0 to 1), and take a color value (any usable by the
|
||||
fillColor method), and an optional opacity.
|
||||
|
||||
You can see both linear and radial gradients in the following example:
|
||||
|
||||
# Create a linear gradient
|
||||
grad = doc.linearGradient(50, 0, 150, 100)
|
||||
grad.stop(0, 'green')
|
||||
.stop(1, 'red')
|
||||
|
||||
doc.rect 50, 0, 100, 100
|
||||
doc.fill grad
|
||||
|
||||
# Create a radial gradient
|
||||
grad = doc.radialGradient(300, 50, 0, 300, 50, 50)
|
||||
grad.stop(0, 'orange', 0)
|
||||
.stop(1, 'orange', 1)
|
||||
|
||||
doc.circle 300, 50, 50
|
||||
doc.fill grad
|
||||
|
||||
Here is the output from the this example:
|
||||
|
||||
![6]()
|
||||
|
||||
## Winding rules
|
||||
|
||||
Winding rules define how a path is filled and are best illustrated by an
|
||||
example. The winding rule is an optional attribute to the `fill` and
|
||||
`fillAndStroke` methods, and there are two values to choose from: `non-zero`
|
||||
and `even-odd`.
|
||||
|
||||
# Initial setup
|
||||
doc.fillColor('red')
|
||||
.translate(-100, -50)
|
||||
.scale(0.8)
|
||||
|
||||
# Draw the path with the non-zero winding rule
|
||||
doc.path('M 250,75 L 323,301 131,161 369,161 177,301 z')
|
||||
.fill('non-zero')
|
||||
|
||||
# Draw the path with the even-odd winding rule
|
||||
doc.translate(280, 0)
|
||||
.path('M 250,75 L 323,301 131,161 369,161 177,301 z')
|
||||
.fill('even-odd')
|
||||
|
||||
You'll notice that I used the `scale` and `translate` transformations in this
|
||||
example. We'll cover those in a minute. The output of this example, with some
|
||||
added labels, is below.
|
||||
|
||||
![7](images/winding_rules.png "200")
|
||||
|
||||
## Saving and restoring the graphics stack
|
||||
|
||||
Once you start producing more complex vector drawings, you will want to be
|
||||
able to save and restore the state of the graphics context. The graphics state
|
||||
is basically a snapshot of all the styles and transformations (see below) that
|
||||
have been applied, and many states can be created and stored on a stack. Every
|
||||
time the `save` method is called, the current graphics state is pushed onto
|
||||
the stack, and when you call `restore`, the last state on the stack is applied
|
||||
to the context again. This way, you can save the state, change some styles,
|
||||
and then restore it to how it was before you made those changes.
|
||||
|
||||
### Transformations
|
||||
|
||||
Transformations allow you to modify the look of a drawing without modifying
|
||||
the drawing itself. There are three types of transformations available, as
|
||||
well as a method for setting the transformation matrix yourself. They are
|
||||
`translate`, `rotate` and `scale`.
|
||||
|
||||
The `translate` transformation takes two arguments, x and y, and effectively
|
||||
moves the origin of the document which is (0, 0) by default, to the left and
|
||||
right x and y units.
|
||||
|
||||
The `rotate` transformation takes an angle and optionally, an object with an
|
||||
`origin` property. It rotates the document `angle` degrees around the passed
|
||||
`origin` or by default, the center of the page.
|
||||
|
||||
The `scale` transformation takes a scale factor and an optional `origin`
|
||||
passed in an options hash as with the `rotate` transformation. It is used to
|
||||
increase or decrease the size of the units in the drawing, or change it's
|
||||
size. For example, applying a scale of `0.5` would make the drawing appear at
|
||||
half size, and a scale of `2` would make it appear twice as large.
|
||||
|
||||
If you are feeling particularly smart, you can modify the transformation
|
||||
matrix yourself using the `transform` method.
|
||||
|
||||
We used the `scale` and `translate` transformations above, so here is an
|
||||
example of using the `rotate` transformation. We'll set the origin of the
|
||||
rotation to the center of the rectangle.
|
||||
|
||||
doc.rotate(20, origin: [150, 70])
|
||||
.rect(100, 20, 100, 100)
|
||||
.fill('gray')
|
||||
|
||||
This example produces the following effect.
|
||||
|
||||
![8](images/rotate.png "200")
|
||||
|
||||
## Clipping
|
||||
|
||||
A clipping path is a path defined using the normal path creation methods, but
|
||||
instead of being filled or stroked, it becomes a mask that hides unwanted
|
||||
parts of the drawing. Everything falling inside the clipping path after it is
|
||||
created is visible, and everything outside the path is invisible. Here is an
|
||||
example that clips a checkerboard pattern to the shape of a circle.
|
||||
|
||||
# Create a clipping path
|
||||
doc.circle(100, 100, 100)
|
||||
.clip()
|
||||
|
||||
# Draw a checkerboard pattern
|
||||
for row in [0...10]
|
||||
for col in [0...10]
|
||||
color = if (col % 2) - (row % 2) then '#eee' else '#4183C4'
|
||||
doc.rect(row * 20, col * 20, 20, 20)
|
||||
.fill(color)
|
||||
|
||||
The result of this example is the following:
|
||||
|
||||
![9](images/clipping.png "200")
|
||||
|
||||
That's it for vector graphics in PDFKit. Now let's move on to learning about
|
||||
PDFKit's text support!
|
@ -0,0 +1,3 @@
|
||||
// Load CoffeeScript, and the main PDFKit files
|
||||
require('coffee-script/register');
|
||||
module.exports = require('./lib/document');
|
@ -0,0 +1,140 @@
|
||||
class Data
|
||||
constructor: (@data = []) ->
|
||||
@pos = 0
|
||||
@length = @data.length
|
||||
|
||||
readByte: ->
|
||||
@data[@pos++]
|
||||
|
||||
writeByte: (byte) ->
|
||||
@data[@pos++] = byte
|
||||
|
||||
byteAt: (index) ->
|
||||
@data[index]
|
||||
|
||||
readBool: ->
|
||||
return !!@readByte()
|
||||
|
||||
writeBool: (val) ->
|
||||
@writeByte if val then 1 else 0
|
||||
|
||||
readUInt32: ->
|
||||
b1 = @readByte() * 0x1000000
|
||||
b2 = @readByte() << 16
|
||||
b3 = @readByte() << 8
|
||||
b4 = @readByte()
|
||||
b1 + b2 + b3 + b4
|
||||
|
||||
writeUInt32: (val) ->
|
||||
@writeByte (val >>> 24) & 0xff
|
||||
@writeByte (val >> 16) & 0xff
|
||||
@writeByte (val >> 8) & 0xff
|
||||
@writeByte val & 0xff
|
||||
|
||||
readInt32: ->
|
||||
int = @readUInt32()
|
||||
if int >= 0x80000000 then int - 0x100000000 else int
|
||||
|
||||
writeInt32: (val) ->
|
||||
val += 0x100000000 if val < 0
|
||||
@writeUInt32 val
|
||||
|
||||
readUInt16: ->
|
||||
b1 = @readByte() << 8
|
||||
b2 = @readByte()
|
||||
b1 | b2
|
||||
|
||||
writeUInt16: (val) ->
|
||||
@writeByte (val >> 8) & 0xff
|
||||
@writeByte val & 0xff
|
||||
|
||||
readInt16: ->
|
||||
int = @readUInt16()
|
||||
if int >= 0x8000 then int - 0x10000 else int
|
||||
|
||||
writeInt16: (val) ->
|
||||
val += 0x10000 if val < 0
|
||||
@writeUInt16 val
|
||||
|
||||
readString: (length) ->
|
||||
ret = []
|
||||
for i in [0...length]
|
||||
ret[i] = String.fromCharCode @readByte()
|
||||
|
||||
return ret.join ''
|
||||
|
||||
writeString: (val) ->
|
||||
for i in [0...val.length]
|
||||
@writeByte val.charCodeAt(i)
|
||||
|
||||
stringAt: (@pos, length) ->
|
||||
@readString length
|
||||
|
||||
readShort: ->
|
||||
@readInt16()
|
||||
|
||||
writeShort: (val) ->
|
||||
@writeInt16 val
|
||||
|
||||
readLongLong: ->
|
||||
b1 = @readByte()
|
||||
b2 = @readByte()
|
||||
b3 = @readByte()
|
||||
b4 = @readByte()
|
||||
b5 = @readByte()
|
||||
b6 = @readByte()
|
||||
b7 = @readByte()
|
||||
b8 = @readByte()
|
||||
|
||||
if b1 & 0x80 # sign -> avoid overflow
|
||||
return ((b1 ^ 0xff) * 0x100000000000000 +
|
||||
(b2 ^ 0xff) * 0x1000000000000 +
|
||||
(b3 ^ 0xff) * 0x10000000000 +
|
||||
(b4 ^ 0xff) * 0x100000000 +
|
||||
(b5 ^ 0xff) * 0x1000000 +
|
||||
(b6 ^ 0xff) * 0x10000 +
|
||||
(b7 ^ 0xff) * 0x100 +
|
||||
(b8 ^ 0xff) + 1) * -1
|
||||
|
||||
return b1 * 0x100000000000000 +
|
||||
b2 * 0x1000000000000 +
|
||||
b3 * 0x10000000000 +
|
||||
b4 * 0x100000000 +
|
||||
b5 * 0x1000000 +
|
||||
b6 * 0x10000 +
|
||||
b7 * 0x100 +
|
||||
b8
|
||||
|
||||
writeLongLong: (val) ->
|
||||
high = Math.floor(val / 0x100000000)
|
||||
low = val & 0xffffffff
|
||||
@writeByte (high >> 24) & 0xff
|
||||
@writeByte (high >> 16) & 0xff
|
||||
@writeByte (high >> 8) & 0xff
|
||||
@writeByte high & 0xff
|
||||
@writeByte (low >> 24) & 0xff
|
||||
@writeByte (low >> 16) & 0xff
|
||||
@writeByte (low >> 8) & 0xff
|
||||
@writeByte low & 0xff
|
||||
|
||||
readInt: ->
|
||||
@readInt32()
|
||||
|
||||
writeInt: (val) ->
|
||||
@writeInt32 val
|
||||
|
||||
slice: (start, end) ->
|
||||
@data.slice start, end
|
||||
|
||||
read: (bytes) ->
|
||||
buf = []
|
||||
for i in [0...bytes]
|
||||
buf.push @readByte()
|
||||
|
||||
return buf
|
||||
|
||||
write: (bytes) ->
|
||||
for byte in bytes
|
||||
@writeByte byte
|
||||
|
||||
module.exports = Data
|
@ -0,0 +1,192 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
(function() {
|
||||
var Data;
|
||||
|
||||
Data = (function() {
|
||||
function Data(data) {
|
||||
this.data = data != null ? data : [];
|
||||
this.pos = 0;
|
||||
this.length = this.data.length;
|
||||
}
|
||||
|
||||
Data.prototype.readByte = function() {
|
||||
return this.data[this.pos++];
|
||||
};
|
||||
|
||||
Data.prototype.writeByte = function(byte) {
|
||||
return this.data[this.pos++] = byte;
|
||||
};
|
||||
|
||||
Data.prototype.byteAt = function(index) {
|
||||
return this.data[index];
|
||||
};
|
||||
|
||||
Data.prototype.readBool = function() {
|
||||
return !!this.readByte();
|
||||
};
|
||||
|
||||
Data.prototype.writeBool = function(val) {
|
||||
return this.writeByte(val ? 1 : 0);
|
||||
};
|
||||
|
||||
Data.prototype.readUInt32 = function() {
|
||||
var b1, b2, b3, b4;
|
||||
b1 = this.readByte() * 0x1000000;
|
||||
b2 = this.readByte() << 16;
|
||||
b3 = this.readByte() << 8;
|
||||
b4 = this.readByte();
|
||||
return b1 + b2 + b3 + b4;
|
||||
};
|
||||
|
||||
Data.prototype.writeUInt32 = function(val) {
|
||||
this.writeByte((val >>> 24) & 0xff);
|
||||
this.writeByte((val >> 16) & 0xff);
|
||||
this.writeByte((val >> 8) & 0xff);
|
||||
return this.writeByte(val & 0xff);
|
||||
};
|
||||
|
||||
Data.prototype.readInt32 = function() {
|
||||
var int;
|
||||
int = this.readUInt32();
|
||||
if (int >= 0x80000000) {
|
||||
return int - 0x100000000;
|
||||
} else {
|
||||
return int;
|
||||
}
|
||||
};
|
||||
|
||||
Data.prototype.writeInt32 = function(val) {
|
||||
if (val < 0) {
|
||||
val += 0x100000000;
|
||||
}
|
||||
return this.writeUInt32(val);
|
||||
};
|
||||
|
||||
Data.prototype.readUInt16 = function() {
|
||||
var b1, b2;
|
||||
b1 = this.readByte() << 8;
|
||||
b2 = this.readByte();
|
||||
return b1 | b2;
|
||||
};
|
||||
|
||||
Data.prototype.writeUInt16 = function(val) {
|
||||
this.writeByte((val >> 8) & 0xff);
|
||||
return this.writeByte(val & 0xff);
|
||||
};
|
||||
|
||||
Data.prototype.readInt16 = function() {
|
||||
var int;
|
||||
int = this.readUInt16();
|
||||
if (int >= 0x8000) {
|
||||
return int - 0x10000;
|
||||
} else {
|
||||
return int;
|
||||
}
|
||||
};
|
||||
|
||||
Data.prototype.writeInt16 = function(val) {
|
||||
if (val < 0) {
|
||||
val += 0x10000;
|
||||
}
|
||||
return this.writeUInt16(val);
|
||||
};
|
||||
|
||||
Data.prototype.readString = function(length) {
|
||||
var i, j, ref, ret;
|
||||
ret = [];
|
||||
for (i = j = 0, ref = length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
|
||||
ret[i] = String.fromCharCode(this.readByte());
|
||||
}
|
||||
return ret.join('');
|
||||
};
|
||||
|
||||
Data.prototype.writeString = function(val) {
|
||||
var i, j, ref, results;
|
||||
results = [];
|
||||
for (i = j = 0, ref = val.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
|
||||
results.push(this.writeByte(val.charCodeAt(i)));
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
Data.prototype.stringAt = function(pos, length) {
|
||||
this.pos = pos;
|
||||
return this.readString(length);
|
||||
};
|
||||
|
||||
Data.prototype.readShort = function() {
|
||||
return this.readInt16();
|
||||
};
|
||||
|
||||
Data.prototype.writeShort = function(val) {
|
||||
return this.writeInt16(val);
|
||||
};
|
||||
|
||||
Data.prototype.readLongLong = function() {
|
||||
var b1, b2, b3, b4, b5, b6, b7, b8;
|
||||
b1 = this.readByte();
|
||||
b2 = this.readByte();
|
||||
b3 = this.readByte();
|
||||
b4 = this.readByte();
|
||||
b5 = this.readByte();
|
||||
b6 = this.readByte();
|
||||
b7 = this.readByte();
|
||||
b8 = this.readByte();
|
||||
if (b1 & 0x80) {
|
||||
return ((b1 ^ 0xff) * 0x100000000000000 + (b2 ^ 0xff) * 0x1000000000000 + (b3 ^ 0xff) * 0x10000000000 + (b4 ^ 0xff) * 0x100000000 + (b5 ^ 0xff) * 0x1000000 + (b6 ^ 0xff) * 0x10000 + (b7 ^ 0xff) * 0x100 + (b8 ^ 0xff) + 1) * -1;
|
||||
}
|
||||
return b1 * 0x100000000000000 + b2 * 0x1000000000000 + b3 * 0x10000000000 + b4 * 0x100000000 + b5 * 0x1000000 + b6 * 0x10000 + b7 * 0x100 + b8;
|
||||
};
|
||||
|
||||
Data.prototype.writeLongLong = function(val) {
|
||||
var high, low;
|
||||
high = Math.floor(val / 0x100000000);
|
||||
low = val & 0xffffffff;
|
||||
this.writeByte((high >> 24) & 0xff);
|
||||
this.writeByte((high >> 16) & 0xff);
|
||||
this.writeByte((high >> 8) & 0xff);
|
||||
this.writeByte(high & 0xff);
|
||||
this.writeByte((low >> 24) & 0xff);
|
||||
this.writeByte((low >> 16) & 0xff);
|
||||
this.writeByte((low >> 8) & 0xff);
|
||||
return this.writeByte(low & 0xff);
|
||||
};
|
||||
|
||||
Data.prototype.readInt = function() {
|
||||
return this.readInt32();
|
||||
};
|
||||
|
||||
Data.prototype.writeInt = function(val) {
|
||||
return this.writeInt32(val);
|
||||
};
|
||||
|
||||
Data.prototype.slice = function(start, end) {
|
||||
return this.data.slice(start, end);
|
||||
};
|
||||
|
||||
Data.prototype.read = function(bytes) {
|
||||
var buf, i, j, ref;
|
||||
buf = [];
|
||||
for (i = j = 0, ref = bytes; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
|
||||
buf.push(this.readByte());
|
||||
}
|
||||
return buf;
|
||||
};
|
||||
|
||||
Data.prototype.write = function(bytes) {
|
||||
var byte, j, len, results;
|
||||
results = [];
|
||||
for (j = 0, len = bytes.length; j < len; j++) {
|
||||
byte = bytes[j];
|
||||
results.push(this.writeByte(byte));
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
return Data;
|
||||
|
||||
})();
|
||||
|
||||
module.exports = Data;
|
||||
|
||||
}).call(this);
|
@ -0,0 +1,223 @@
|
||||
###
|
||||
PDFDocument - represents an entire PDF document
|
||||
By Devon Govett
|
||||
###
|
||||
|
||||
stream = require 'stream'
|
||||
fs = require 'fs'
|
||||
PDFObject = require './object'
|
||||
PDFReference = require './reference'
|
||||
PDFPage = require './page'
|
||||
|
||||
class PDFDocument extends stream.Readable
|
||||
constructor: (@options = {}) ->
|
||||
super
|
||||
|
||||
# PDF version
|
||||
@version = 1.3
|
||||
|
||||
# Whether streams should be compressed
|
||||
@compress = @options.compress ? yes
|
||||
|
||||
@_pageBuffer = []
|
||||
@_pageBufferStart = 0
|
||||
|
||||
# The PDF object store
|
||||
@_offsets = []
|
||||
@_waiting = 0
|
||||
@_ended = false
|
||||
@_offset = 0
|
||||
|
||||
@_root = @ref
|
||||
Type: 'Catalog'
|
||||
Pages: @ref
|
||||
Type: 'Pages'
|
||||
Count: 0
|
||||
Kids: []
|
||||
|
||||
# The current page
|
||||
@page = null
|
||||
|
||||
# Initialize mixins
|
||||
@initColor()
|
||||
@initVector()
|
||||
@initFonts()
|
||||
@initText()
|
||||
@initImages()
|
||||
|
||||
# Initialize the metadata
|
||||
@info =
|
||||
Producer: 'PDFKit'
|
||||
Creator: 'PDFKit'
|
||||
CreationDate: new Date()
|
||||
|
||||
if @options.info
|
||||
for key, val of @options.info
|
||||
@info[key] = val
|
||||
|
||||
# Write the header
|
||||
# PDF version
|
||||
@_write "%PDF-#{@version}"
|
||||
|
||||
# 4 binary chars, as recommended by the spec
|
||||
@_write "%\xFF\xFF\xFF\xFF"
|
||||
|
||||
# Add the first page
|
||||
if @options.autoFirstPage isnt false
|
||||
@addPage()
|
||||
|
||||
mixin = (methods) =>
|
||||
for name, method of methods
|
||||
this::[name] = method
|
||||
|
||||
# Load mixins
|
||||
mixin require './mixins/color'
|
||||
mixin require './mixins/vector'
|
||||
mixin require './mixins/fonts'
|
||||
mixin require './mixins/text'
|
||||
mixin require './mixins/images'
|
||||
mixin require './mixins/annotations'
|
||||
|
||||
addPage: (options = @options) ->
|
||||
# end the current page if needed
|
||||
@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
|
||||
pages.Count++
|
||||
|
||||
# reset x and y coordinates
|
||||
@x = @page.margins.left
|
||||
@y = @page.margins.top
|
||||
|
||||
# flip PDF coordinate system so that the origin is in
|
||||
# the top left rather than the bottom left
|
||||
@_ctm = [1, 0, 0, 1, 0, 0]
|
||||
@transform 1, 0, 0, -1, 0, @page.height
|
||||
|
||||
@emit('pageAdded')
|
||||
|
||||
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
|
||||
@_waiting++
|
||||
return ref
|
||||
|
||||
_read: ->
|
||||
# do nothing, but this method is required by node
|
||||
|
||||
_write: (data) ->
|
||||
unless Buffer.isBuffer(data)
|
||||
data = new Buffer(data + '\n', 'binary')
|
||||
|
||||
@push data
|
||||
@_offset += data.length
|
||||
|
||||
addContent: (data) ->
|
||||
@page.write data
|
||||
return this
|
||||
|
||||
_refEnd: (ref) ->
|
||||
@_offsets[ref.id - 1] = ref.offset
|
||||
if --@_waiting is 0 and @_ended
|
||||
@_finalize()
|
||||
@_ended = false
|
||||
|
||||
write: (filename, fn) ->
|
||||
# print a deprecation warning with a stacktrace
|
||||
err = new Error '
|
||||
PDFDocument#write is deprecated, and will be removed in a future version of PDFKit.
|
||||
Please pipe the document into a Node stream.
|
||||
'
|
||||
|
||||
console.warn err.stack
|
||||
|
||||
@pipe fs.createWriteStream(filename)
|
||||
@end()
|
||||
@once 'end', fn
|
||||
|
||||
output: (fn) ->
|
||||
# more difficult to support this. It would involve concatenating all the buffers together
|
||||
throw new Error '
|
||||
PDFDocument#output is deprecated, and has been removed from PDFKit.
|
||||
Please pipe the document into a Node stream.
|
||||
'
|
||||
|
||||
end: ->
|
||||
@flushPages()
|
||||
@_info = @ref()
|
||||
for key, val of @info
|
||||
if typeof val is 'string'
|
||||
val = new String val
|
||||
|
||||
@_info.data[key] = val
|
||||
|
||||
@_info.end()
|
||||
|
||||
for name, font of @_fontFamilies
|
||||
font.finalize()
|
||||
|
||||
@_root.end()
|
||||
@_root.data.Pages.end()
|
||||
|
||||
if @_waiting is 0
|
||||
@_finalize()
|
||||
else
|
||||
@_ended = true
|
||||
|
||||
_finalize: (fn) ->
|
||||
# generate xref
|
||||
xRefOffset = @_offset
|
||||
@_write "xref"
|
||||
@_write "0 #{@_offsets.length + 1}"
|
||||
@_write "0000000000 65535 f "
|
||||
|
||||
for offset in @_offsets
|
||||
offset = ('0000000000' + offset).slice(-10)
|
||||
@_write offset + ' 00000 n '
|
||||
|
||||
# trailer
|
||||
@_write 'trailer'
|
||||
@_write PDFObject.convert
|
||||
Size: @_offsets.length + 1
|
||||
Root: @_root
|
||||
Info: @_info
|
||||
|
||||
@_write 'startxref'
|
||||
@_write "#{xRefOffset}"
|
||||
@_write '%%EOF'
|
||||
|
||||
# end the stream
|
||||
@push null
|
||||
|
||||
toString: ->
|
||||
"[object PDFDocument]"
|
||||
|
||||
module.exports = PDFDocument
|
@ -0,0 +1,247 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
|
||||
/*
|
||||
PDFDocument - represents an entire PDF document
|
||||
By Devon Govett
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var PDFDocument, PDFObject, PDFPage, PDFReference, fs, stream,
|
||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
stream = require('stream');
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
PDFObject = require('./object');
|
||||
|
||||
PDFReference = require('./reference');
|
||||
|
||||
PDFPage = require('./page');
|
||||
|
||||
PDFDocument = (function(superClass) {
|
||||
var mixin;
|
||||
|
||||
extend(PDFDocument, superClass);
|
||||
|
||||
function PDFDocument(options1) {
|
||||
var key, ref1, ref2, val;
|
||||
this.options = options1 != null ? options1 : {};
|
||||
PDFDocument.__super__.constructor.apply(this, arguments);
|
||||
this.version = 1.3;
|
||||
this.compress = (ref1 = this.options.compress) != null ? ref1 : true;
|
||||
this._pageBuffer = [];
|
||||
this._pageBufferStart = 0;
|
||||
this._offsets = [];
|
||||
this._waiting = 0;
|
||||
this._ended = false;
|
||||
this._offset = 0;
|
||||
this._root = this.ref({
|
||||
Type: 'Catalog',
|
||||
Pages: this.ref({
|
||||
Type: 'Pages',
|
||||
Count: 0,
|
||||
Kids: []
|
||||
})
|
||||
});
|
||||
this.page = null;
|
||||
this.initColor();
|
||||
this.initVector();
|
||||
this.initFonts();
|
||||
this.initText();
|
||||
this.initImages();
|
||||
this.info = {
|
||||
Producer: 'PDFKit',
|
||||
Creator: 'PDFKit',
|
||||
CreationDate: new Date()
|
||||
};
|
||||
if (this.options.info) {
|
||||
ref2 = this.options.info;
|
||||
for (key in ref2) {
|
||||
val = ref2[key];
|
||||
this.info[key] = val;
|
||||
}
|
||||
}
|
||||
this._write("%PDF-" + this.version);
|
||||
this._write("%\xFF\xFF\xFF\xFF");
|
||||
if (this.options.autoFirstPage !== false) {
|
||||
this.addPage();
|
||||
}
|
||||
}
|
||||
|
||||
mixin = function(methods) {
|
||||
var method, name, results;
|
||||
results = [];
|
||||
for (name in methods) {
|
||||
method = methods[name];
|
||||
results.push(PDFDocument.prototype[name] = method);
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
mixin(require('./mixins/color'));
|
||||
|
||||
mixin(require('./mixins/vector'));
|
||||
|
||||
mixin(require('./mixins/fonts'));
|
||||
|
||||
mixin(require('./mixins/text'));
|
||||
|
||||
mixin(require('./mixins/images'));
|
||||
|
||||
mixin(require('./mixins/annotations'));
|
||||
|
||||
PDFDocument.prototype.addPage = function(options) {
|
||||
var pages;
|
||||
if (options == null) {
|
||||
options = this.options;
|
||||
}
|
||||
if (!this.options.bufferPages) {
|
||||
this.flushPages();
|
||||
}
|
||||
this.page = new PDFPage(this, options);
|
||||
this._pageBuffer.push(this.page);
|
||||
pages = this._root.data.Pages.data;
|
||||
pages.Kids.push(this.page.dictionary);
|
||||
pages.Count++;
|
||||
this.x = this.page.margins.left;
|
||||
this.y = this.page.margins.top;
|
||||
this._ctm = [1, 0, 0, 1, 0, 0];
|
||||
this.transform(1, 0, 0, -1, 0, this.page.height);
|
||||
this.emit('pageAdded');
|
||||
return this;
|
||||
};
|
||||
|
||||
PDFDocument.prototype.bufferedPageRange = function() {
|
||||
return {
|
||||
start: this._pageBufferStart,
|
||||
count: this._pageBuffer.length
|
||||
};
|
||||
};
|
||||
|
||||
PDFDocument.prototype.switchToPage = function(n) {
|
||||
var page;
|
||||
if (!(page = this._pageBuffer[n - this._pageBufferStart])) {
|
||||
throw new Error("switchToPage(" + n + ") out of bounds, current buffer covers pages " + this._pageBufferStart + " to " + (this._pageBufferStart + this._pageBuffer.length - 1));
|
||||
}
|
||||
return this.page = page;
|
||||
};
|
||||
|
||||
PDFDocument.prototype.flushPages = function() {
|
||||
var i, len, page, pages;
|
||||
pages = this._pageBuffer;
|
||||
this._pageBuffer = [];
|
||||
this._pageBufferStart += pages.length;
|
||||
for (i = 0, len = pages.length; i < len; i++) {
|
||||
page = pages[i];
|
||||
page.end();
|
||||
}
|
||||
};
|
||||
|
||||
PDFDocument.prototype.ref = function(data) {
|
||||
var ref;
|
||||
ref = new PDFReference(this, this._offsets.length + 1, data);
|
||||
this._offsets.push(null);
|
||||
this._waiting++;
|
||||
return ref;
|
||||
};
|
||||
|
||||
PDFDocument.prototype._read = function() {};
|
||||
|
||||
PDFDocument.prototype._write = function(data) {
|
||||
if (!Buffer.isBuffer(data)) {
|
||||
data = new Buffer(data + '\n', 'binary');
|
||||
}
|
||||
this.push(data);
|
||||
return this._offset += data.length;
|
||||
};
|
||||
|
||||
PDFDocument.prototype.addContent = function(data) {
|
||||
this.page.write(data);
|
||||
return this;
|
||||
};
|
||||
|
||||
PDFDocument.prototype._refEnd = function(ref) {
|
||||
this._offsets[ref.id - 1] = ref.offset;
|
||||
if (--this._waiting === 0 && this._ended) {
|
||||
this._finalize();
|
||||
return this._ended = false;
|
||||
}
|
||||
};
|
||||
|
||||
PDFDocument.prototype.write = function(filename, fn) {
|
||||
var err;
|
||||
err = new Error('PDFDocument#write is deprecated, and will be removed in a future version of PDFKit. Please pipe the document into a Node stream.');
|
||||
console.warn(err.stack);
|
||||
this.pipe(fs.createWriteStream(filename));
|
||||
this.end();
|
||||
return this.once('end', fn);
|
||||
};
|
||||
|
||||
PDFDocument.prototype.output = function(fn) {
|
||||
throw new Error('PDFDocument#output is deprecated, and has been removed from PDFKit. Please pipe the document into a Node stream.');
|
||||
};
|
||||
|
||||
PDFDocument.prototype.end = function() {
|
||||
var font, key, name, ref1, ref2, val;
|
||||
this.flushPages();
|
||||
this._info = this.ref();
|
||||
ref1 = this.info;
|
||||
for (key in ref1) {
|
||||
val = ref1[key];
|
||||
if (typeof val === 'string') {
|
||||
val = new String(val);
|
||||
}
|
||||
this._info.data[key] = val;
|
||||
}
|
||||
this._info.end();
|
||||
ref2 = this._fontFamilies;
|
||||
for (name in ref2) {
|
||||
font = ref2[name];
|
||||
font.finalize();
|
||||
}
|
||||
this._root.end();
|
||||
this._root.data.Pages.end();
|
||||
if (this._waiting === 0) {
|
||||
return this._finalize();
|
||||
} else {
|
||||
return this._ended = true;
|
||||
}
|
||||
};
|
||||
|
||||
PDFDocument.prototype._finalize = function(fn) {
|
||||
var i, len, offset, ref1, xRefOffset;
|
||||
xRefOffset = this._offset;
|
||||
this._write("xref");
|
||||
this._write("0 " + (this._offsets.length + 1));
|
||||
this._write("0000000000 65535 f ");
|
||||
ref1 = this._offsets;
|
||||
for (i = 0, len = ref1.length; i < len; i++) {
|
||||
offset = ref1[i];
|
||||
offset = ('0000000000' + offset).slice(-10);
|
||||
this._write(offset + ' 00000 n ');
|
||||
}
|
||||
this._write('trailer');
|
||||
this._write(PDFObject.convert({
|
||||
Size: this._offsets.length + 1,
|
||||
Root: this._root,
|
||||
Info: this._info
|
||||
}));
|
||||
this._write('startxref');
|
||||
this._write("" + xRefOffset);
|
||||
this._write('%%EOF');
|
||||
return this.push(null);
|
||||
};
|
||||
|
||||
PDFDocument.prototype.toString = function() {
|
||||
return "[object PDFDocument]";
|
||||
};
|
||||
|
||||
return PDFDocument;
|
||||
|
||||
})(stream.Readable);
|
||||
|
||||
module.exports = PDFDocument;
|
||||
|
||||
}).call(this);
|
@ -0,0 +1,53 @@
|
||||
fontkit = require 'fontkit'
|
||||
|
||||
class PDFFont
|
||||
@open: (document, src, family, id) ->
|
||||
if typeof src is 'string'
|
||||
if StandardFont.isStandardFont src
|
||||
return new StandardFont document, src, id
|
||||
|
||||
font = fontkit.openSync src, family
|
||||
|
||||
else if Buffer.isBuffer(src)
|
||||
font = fontkit.create src, family
|
||||
|
||||
else if src instanceof Uint8Array
|
||||
font = fontkit.create new Buffer(src), family
|
||||
|
||||
else if src instanceof ArrayBuffer
|
||||
font = fontkit.create new Buffer(new Uint8Array(src)), family
|
||||
|
||||
if not font?
|
||||
throw new Error 'Not a supported font format or standard PDF font.'
|
||||
|
||||
return new EmbeddedFont document, font, id
|
||||
|
||||
constructor: ->
|
||||
throw new Error 'Cannot construct a PDFFont directly.'
|
||||
|
||||
encode: (text) ->
|
||||
throw new Error 'Must be implemented by subclasses'
|
||||
|
||||
widthOfString: (text) ->
|
||||
throw new Error 'Must be implemented by subclasses'
|
||||
|
||||
ref: ->
|
||||
@dictionary ?= @document.ref()
|
||||
|
||||
finalize: ->
|
||||
return if @embedded or not @dictionary?
|
||||
|
||||
@embed()
|
||||
@embedded = true
|
||||
|
||||
embed: ->
|
||||
throw new Error 'Must be implemented by subclasses'
|
||||
|
||||
lineHeight: (size, includeGap = false) ->
|
||||
gap = if includeGap then @lineGap else 0
|
||||
(@ascender + gap - @descender) / 1000 * size
|
||||
|
||||
module.exports = PDFFont
|
||||
|
||||
StandardFont = require './font/standard'
|
||||
EmbeddedFont = require './font/embedded'
|
@ -0,0 +1,75 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
(function() {
|
||||
var EmbeddedFont, PDFFont, StandardFont, fontkit;
|
||||
|
||||
fontkit = require('fontkit');
|
||||
|
||||
PDFFont = (function() {
|
||||
PDFFont.open = function(document, src, family, id) {
|
||||
var font;
|
||||
if (typeof src === 'string') {
|
||||
if (StandardFont.isStandardFont(src)) {
|
||||
return new StandardFont(document, src, id);
|
||||
}
|
||||
font = fontkit.openSync(src, family);
|
||||
} else if (Buffer.isBuffer(src)) {
|
||||
font = fontkit.create(src, family);
|
||||
} else if (src instanceof Uint8Array) {
|
||||
font = fontkit.create(new Buffer(src), family);
|
||||
} else if (src instanceof ArrayBuffer) {
|
||||
font = fontkit.create(new Buffer(new Uint8Array(src)), family);
|
||||
}
|
||||
if (font == null) {
|
||||
throw new Error('Not a supported font format or standard PDF font.');
|
||||
}
|
||||
return new EmbeddedFont(document, font, id);
|
||||
};
|
||||
|
||||
function PDFFont() {
|
||||
throw new Error('Cannot construct a PDFFont directly.');
|
||||
}
|
||||
|
||||
PDFFont.prototype.encode = function(text) {
|
||||
throw new Error('Must be implemented by subclasses');
|
||||
};
|
||||
|
||||
PDFFont.prototype.widthOfString = function(text) {
|
||||
throw new Error('Must be implemented by subclasses');
|
||||
};
|
||||
|
||||
PDFFont.prototype.ref = function() {
|
||||
return this.dictionary != null ? this.dictionary : this.dictionary = this.document.ref();
|
||||
};
|
||||
|
||||
PDFFont.prototype.finalize = function() {
|
||||
if (this.embedded || (this.dictionary == null)) {
|
||||
return;
|
||||
}
|
||||
this.embed();
|
||||
return this.embedded = true;
|
||||
};
|
||||
|
||||
PDFFont.prototype.embed = function() {
|
||||
throw new Error('Must be implemented by subclasses');
|
||||
};
|
||||
|
||||
PDFFont.prototype.lineHeight = function(size, includeGap) {
|
||||
var gap;
|
||||
if (includeGap == null) {
|
||||
includeGap = false;
|
||||
}
|
||||
gap = includeGap ? this.lineGap : 0;
|
||||
return (this.ascender + gap - this.descender) / 1000 * size;
|
||||
};
|
||||
|
||||
return PDFFont;
|
||||
|
||||
})();
|
||||
|
||||
module.exports = PDFFont;
|
||||
|
||||
StandardFont = require('./font/standard');
|
||||
|
||||
EmbeddedFont = require('./font/embedded');
|
||||
|
||||
}).call(this);
|
@ -0,0 +1,195 @@
|
||||
fs = require 'fs'
|
||||
|
||||
class AFMFont
|
||||
@open: (filename) ->
|
||||
new AFMFont fs.readFileSync filename, 'utf8'
|
||||
|
||||
constructor: (@contents) ->
|
||||
@attributes = {}
|
||||
@glyphWidths = {}
|
||||
@boundingBoxes = {}
|
||||
@kernPairs = {}
|
||||
|
||||
@parse()
|
||||
@charWidths = (@glyphWidths[characters[i]] for i in [0..255])
|
||||
|
||||
@bbox = (+e for e in @attributes['FontBBox'].split /\s+/)
|
||||
@ascender = +(@attributes['Ascender'] or 0)
|
||||
@descender = +(@attributes['Descender'] or 0)
|
||||
@lineGap = (@bbox[3] - @bbox[1]) - (@ascender - @descender)
|
||||
|
||||
parse: ->
|
||||
section = ''
|
||||
for line in @contents.split '\n'
|
||||
if match = line.match /^Start(\w+)/
|
||||
section = match[1]
|
||||
continue
|
||||
|
||||
else if match = line.match /^End(\w+)/
|
||||
section = ''
|
||||
continue
|
||||
|
||||
switch section
|
||||
when 'FontMetrics'
|
||||
match = line.match /(^\w+)\s+(.*)/
|
||||
key = match[1]
|
||||
value = match[2]
|
||||
|
||||
if a = @attributes[key]
|
||||
a = @attributes[key] = [a] if !Array.isArray(a)
|
||||
a.push(value)
|
||||
else
|
||||
@attributes[key] = value
|
||||
|
||||
when 'CharMetrics'
|
||||
continue unless /^CH?\s/.test(line)
|
||||
name = line.match(/\bN\s+(\.?\w+)\s*;/)[1]
|
||||
@glyphWidths[name] = +line.match(/\bWX\s+(\d+)\s*;/)[1]
|
||||
|
||||
when 'KernPairs'
|
||||
match = line.match /^KPX\s+(\.?\w+)\s+(\.?\w+)\s+(-?\d+)/
|
||||
if match
|
||||
@kernPairs[match[1] + '\0' + match[2]] = parseInt match[3]
|
||||
|
||||
return
|
||||
|
||||
WIN_ANSI_MAP =
|
||||
402: 131
|
||||
8211: 150
|
||||
8212: 151
|
||||
8216: 145
|
||||
8217: 146
|
||||
8218: 130
|
||||
8220: 147
|
||||
8221: 148
|
||||
8222: 132
|
||||
8224: 134
|
||||
8225: 135
|
||||
8226: 149
|
||||
8230: 133
|
||||
8364: 128
|
||||
8240: 137
|
||||
8249: 139
|
||||
8250: 155
|
||||
710: 136
|
||||
8482: 153
|
||||
338: 140
|
||||
339: 156
|
||||
732: 152
|
||||
352: 138
|
||||
353: 154
|
||||
376: 159
|
||||
381: 142
|
||||
382: 158
|
||||
|
||||
encodeText: (text) ->
|
||||
res = []
|
||||
for i in [0...text.length]
|
||||
char = text.charCodeAt(i)
|
||||
char = WIN_ANSI_MAP[char] or char
|
||||
res.push char.toString(16)
|
||||
|
||||
return res
|
||||
|
||||
glyphsForString: (string) ->
|
||||
glyphs = []
|
||||
|
||||
for i in [0...string.length]
|
||||
charCode = string.charCodeAt(i)
|
||||
glyphs.push @characterToGlyph charCode
|
||||
|
||||
return glyphs
|
||||
|
||||
characterToGlyph: (character) ->
|
||||
return characters[WIN_ANSI_MAP[character] or character] or '.notdef'
|
||||
|
||||
widthOfGlyph: (glyph) ->
|
||||
return @glyphWidths[glyph] or 0
|
||||
|
||||
getKernPair: (left, right) ->
|
||||
return @kernPairs[left + '\0' + right] or 0
|
||||
|
||||
advancesForGlyphs: (glyphs) ->
|
||||
advances = []
|
||||
|
||||
for left, index in glyphs
|
||||
right = glyphs[index + 1]
|
||||
advances.push @widthOfGlyph(left) + @getKernPair(left, right)
|
||||
|
||||
return advances
|
||||
|
||||
characters = '''
|
||||
.notdef .notdef .notdef .notdef
|
||||
.notdef .notdef .notdef .notdef
|
||||
.notdef .notdef .notdef .notdef
|
||||
.notdef .notdef .notdef .notdef
|
||||
.notdef .notdef .notdef .notdef
|
||||
.notdef .notdef .notdef .notdef
|
||||
.notdef .notdef .notdef .notdef
|
||||
.notdef .notdef .notdef .notdef
|
||||
|
||||
space exclam quotedbl numbersign
|
||||
dollar percent ampersand quotesingle
|
||||
parenleft parenright asterisk plus
|
||||
comma hyphen period slash
|
||||
zero one two three
|
||||
four five six seven
|
||||
eight nine colon semicolon
|
||||
less equal greater question
|
||||
|
||||
at A B C
|
||||
D E F G
|
||||
H I J K
|
||||
L M N O
|
||||
P Q R S
|
||||
T U V W
|
||||
X Y Z bracketleft
|
||||
backslash bracketright asciicircum underscore
|
||||
|
||||
grave a b c
|
||||
d e f g
|
||||
h i j k
|
||||
l m n o
|
||||
p q r s
|
||||
t u v w
|
||||
x y z braceleft
|
||||
bar braceright asciitilde .notdef
|
||||
|
||||
Euro .notdef quotesinglbase florin
|
||||
quotedblbase ellipsis dagger daggerdbl
|
||||
circumflex perthousand Scaron guilsinglleft
|
||||
OE .notdef Zcaron .notdef
|
||||
.notdef quoteleft quoteright quotedblleft
|
||||
quotedblright bullet endash emdash
|
||||
tilde trademark scaron guilsinglright
|
||||
oe .notdef zcaron ydieresis
|
||||
|
||||
space exclamdown cent sterling
|
||||
currency yen brokenbar section
|
||||
dieresis copyright ordfeminine guillemotleft
|
||||
logicalnot hyphen registered macron
|
||||
degree plusminus twosuperior threesuperior
|
||||
acute mu paragraph periodcentered
|
||||
cedilla onesuperior ordmasculine guillemotright
|
||||
onequarter onehalf threequarters questiondown
|
||||
|
||||
Agrave Aacute Acircumflex Atilde
|
||||
Adieresis Aring AE Ccedilla
|
||||
Egrave Eacute Ecircumflex Edieresis
|
||||
Igrave Iacute Icircumflex Idieresis
|
||||
Eth Ntilde Ograve Oacute
|
||||
Ocircumflex Otilde Odieresis multiply
|
||||
Oslash Ugrave Uacute Ucircumflex
|
||||
Udieresis Yacute Thorn germandbls
|
||||
|
||||
agrave aacute acircumflex atilde
|
||||
adieresis aring ae ccedilla
|
||||
egrave eacute ecircumflex edieresis
|
||||
igrave iacute icircumflex idieresis
|
||||
eth ntilde ograve oacute
|
||||
ocircumflex otilde odieresis divide
|
||||
oslash ugrave uacute ucircumflex
|
||||
udieresis yacute thorn ydieresis
|
||||
'''.split(/\s+/)
|
||||
|
||||
module.exports = AFMFont
|
@ -0,0 +1,342 @@
|
||||
StartFontMetrics 4.1
|
||||
Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
|
||||
Comment Creation Date: Mon Jun 23 16:28:00 1997
|
||||
Comment UniqueID 43048
|
||||
Comment VMusage 41139 52164
|
||||
FontName Courier-Bold
|
||||
FullName Courier Bold
|
||||
FamilyName Courier
|
||||
Weight Bold
|
||||
ItalicAngle 0
|
||||
IsFixedPitch true
|
||||
CharacterSet ExtendedRoman
|
||||
FontBBox -113 -250 749 801
|
||||
UnderlinePosition -100
|
||||
UnderlineThickness 50
|
||||
Version 003.000
|
||||
Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
|
||||
EncodingScheme AdobeStandardEncoding
|
||||
CapHeight 562
|
||||
XHeight 439
|
||||
Ascender 629
|
||||
Descender -157
|
||||
StdHW 84
|
||||
StdVW 106
|
||||
StartCharMetrics 315
|
||||
C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
|
||||
C 33 ; WX 600 ; N exclam ; B 202 -15 398 572 ;
|
||||
C 34 ; WX 600 ; N quotedbl ; B 135 277 465 562 ;
|
||||
C 35 ; WX 600 ; N numbersign ; B 56 -45 544 651 ;
|
||||
C 36 ; WX 600 ; N dollar ; B 82 -126 519 666 ;
|
||||
C 37 ; WX 600 ; N percent ; B 5 -15 595 616 ;
|
||||
C 38 ; WX 600 ; N ampersand ; B 36 -15 546 543 ;
|
||||
C 39 ; WX 600 ; N quoteright ; B 171 277 423 562 ;
|
||||
C 40 ; WX 600 ; N parenleft ; B 219 -102 461 616 ;
|
||||
C 41 ; WX 600 ; N parenright ; B 139 -102 381 616 ;
|
||||
C 42 ; WX 600 ; N asterisk ; B 91 219 509 601 ;
|
||||
C 43 ; WX 600 ; N plus ; B 71 39 529 478 ;
|
||||
C 44 ; WX 600 ; N comma ; B 123 -111 393 174 ;
|
||||
C 45 ; WX 600 ; N hyphen ; B 100 203 500 313 ;
|
||||
C 46 ; WX 600 ; N period ; B 192 -15 408 171 ;
|
||||
C 47 ; WX 600 ; N slash ; B 98 -77 502 626 ;
|
||||
C 48 ; WX 600 ; N zero ; B 87 -15 513 616 ;
|
||||
C 49 ; WX 600 ; N one ; B 81 0 539 616 ;
|
||||
C 50 ; WX 600 ; N two ; B 61 0 499 616 ;
|
||||
C 51 ; WX 600 ; N three ; B 63 -15 501 616 ;
|
||||
C 52 ; WX 600 ; N four ; B 53 0 507 616 ;
|
||||
C 53 ; WX 600 ; N five ; B 70 -15 521 601 ;
|
||||
C 54 ; WX 600 ; N six ; B 90 -15 521 616 ;
|
||||
C 55 ; WX 600 ; N seven ; B 55 0 494 601 ;
|
||||
C 56 ; WX 600 ; N eight ; B 83 -15 517 616 ;
|
||||
C 57 ; WX 600 ; N nine ; B 79 -15 510 616 ;
|
||||
C 58 ; WX 600 ; N colon ; B 191 -15 407 425 ;
|
||||
C 59 ; WX 600 ; N semicolon ; B 123 -111 408 425 ;
|
||||
C 60 ; WX 600 ; N less ; B 66 15 523 501 ;
|
||||
C 61 ; WX 600 ; N equal ; B 71 118 529 398 ;
|
||||
C 62 ; WX 600 ; N greater ; B 77 15 534 501 ;
|
||||
C 63 ; WX 600 ; N question ; B 98 -14 501 580 ;
|
||||
C 64 ; WX 600 ; N at ; B 16 -15 584 616 ;
|
||||
C 65 ; WX 600 ; N A ; B -9 0 609 562 ;
|
||||
C 66 ; WX 600 ; N B ; B 30 0 573 562 ;
|
||||
C 67 ; WX 600 ; N C ; B 22 -18 560 580 ;
|
||||
C 68 ; WX 600 ; N D ; B 30 0 594 562 ;
|
||||
C 69 ; WX 600 ; N E ; B 25 0 560 562 ;
|
||||
C 70 ; WX 600 ; N F ; B 39 0 570 562 ;
|
||||
C 71 ; WX 600 ; N G ; B 22 -18 594 580 ;
|
||||
C 72 ; WX 600 ; N H ; B 20 0 580 562 ;
|
||||
C 73 ; WX 600 ; N I ; B 77 0 523 562 ;
|
||||
C 74 ; WX 600 ; N J ; B 37 -18 601 562 ;
|
||||
C 75 ; WX 600 ; N K ; B 21 0 599 562 ;
|
||||
C 76 ; WX 600 ; N L ; B 39 0 578 562 ;
|
||||
C 77 ; WX 600 ; N M ; B -2 0 602 562 ;
|
||||
C 78 ; WX 600 ; N N ; B 8 -12 610 562 ;
|
||||
C 79 ; WX 600 ; N O ; B 22 -18 578 580 ;
|
||||
C 80 ; WX 600 ; N P ; B 48 0 559 562 ;
|
||||
C 81 ; WX 600 ; N Q ; B 32 -138 578 580 ;
|
||||
C 82 ; WX 600 ; N R ; B 24 0 599 562 ;
|
||||
C 83 ; WX 600 ; N S ; B 47 -22 553 582 ;
|
||||
C 84 ; WX 600 ; N T ; B 21 0 579 562 ;
|
||||
C 85 ; WX 600 ; N U ; B 4 -18 596 562 ;
|
||||
C 86 ; WX 600 ; N V ; B -13 0 613 562 ;
|
||||
C 87 ; WX 600 ; N W ; B -18 0 618 562 ;
|
||||
C 88 ; WX 600 ; N X ; B 12 0 588 562 ;
|
||||
C 89 ; WX 600 ; N Y ; B 12 0 589 562 ;
|
||||
C 90 ; WX 600 ; N Z ; B 62 0 539 562 ;
|
||||
C 91 ; WX 600 ; N bracketleft ; B 245 -102 475 616 ;
|
||||
C 92 ; WX 600 ; N backslash ; B 99 -77 503 626 ;
|
||||
C 93 ; WX 600 ; N bracketright ; B 125 -102 355 616 ;
|
||||
C 94 ; WX 600 ; N asciicircum ; B 108 250 492 616 ;
|
||||
C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ;
|
||||
C 96 ; WX 600 ; N quoteleft ; B 178 277 428 562 ;
|
||||
C 97 ; WX 600 ; N a ; B 35 -15 570 454 ;
|
||||
C 98 ; WX 600 ; N b ; B 0 -15 584 626 ;
|
||||
C 99 ; WX 600 ; N c ; B 40 -15 545 459 ;
|
||||
C 100 ; WX 600 ; N d ; B 20 -15 591 626 ;
|
||||
C 101 ; WX 600 ; N e ; B 40 -15 563 454 ;
|
||||
C 102 ; WX 600 ; N f ; B 83 0 547 626 ; L i fi ; L l fl ;
|
||||
C 103 ; WX 600 ; N g ; B 30 -146 580 454 ;
|
||||
C 104 ; WX 600 ; N h ; B 5 0 592 626 ;
|
||||
C 105 ; WX 600 ; N i ; B 77 0 523 658 ;
|
||||
C 106 ; WX 600 ; N j ; B 63 -146 440 658 ;
|
||||
C 107 ; WX 600 ; N k ; B 20 0 585 626 ;
|
||||
C 108 ; WX 600 ; N l ; B 77 0 523 626 ;
|
||||
C 109 ; WX 600 ; N m ; B -22 0 626 454 ;
|
||||
C 110 ; WX 600 ; N n ; B 18 0 592 454 ;
|
||||
C 111 ; WX 600 ; N o ; B 30 -15 570 454 ;
|
||||
C 112 ; WX 600 ; N p ; B -1 -142 570 454 ;
|
||||
C 113 ; WX 600 ; N q ; B 20 -142 591 454 ;
|
||||
C 114 ; WX 600 ; N r ; B 47 0 580 454 ;
|
||||
C 115 ; WX 600 ; N s ; B 68 -17 535 459 ;
|
||||
C 116 ; WX 600 ; N t ; B 47 -15 532 562 ;
|
||||
C 117 ; WX 600 ; N u ; B -1 -15 569 439 ;
|
||||
C 118 ; WX 600 ; N v ; B -1 0 601 439 ;
|
||||
C 119 ; WX 600 ; N w ; B -18 0 618 439 ;
|
||||
C 120 ; WX 600 ; N x ; B 6 0 594 439 ;
|
||||
C 121 ; WX 600 ; N y ; B -4 -142 601 439 ;
|
||||
C 122 ; WX 600 ; N z ; B 81 0 520 439 ;
|
||||
C 123 ; WX 600 ; N braceleft ; B 160 -102 464 616 ;
|
||||
C 124 ; WX 600 ; N bar ; B 255 -250 345 750 ;
|
||||
C 125 ; WX 600 ; N braceright ; B 136 -102 440 616 ;
|
||||
C 126 ; WX 600 ; N asciitilde ; B 71 153 530 356 ;
|
||||
C 161 ; WX 600 ; N exclamdown ; B 202 -146 398 449 ;
|
||||
C 162 ; WX 600 ; N cent ; B 66 -49 518 614 ;
|
||||
C 163 ; WX 600 ; N sterling ; B 72 -28 558 611 ;
|
||||
C 164 ; WX 600 ; N fraction ; B 25 -60 576 661 ;
|
||||
C 165 ; WX 600 ; N yen ; B 10 0 590 562 ;
|
||||
C 166 ; WX 600 ; N florin ; B -30 -131 572 616 ;
|
||||
C 167 ; WX 600 ; N section ; B 83 -70 517 580 ;
|
||||
C 168 ; WX 600 ; N currency ; B 54 49 546 517 ;
|
||||
C 169 ; WX 600 ; N quotesingle ; B 227 277 373 562 ;
|
||||
C 170 ; WX 600 ; N quotedblleft ; B 71 277 535 562 ;
|
||||
C 171 ; WX 600 ; N guillemotleft ; B 8 70 553 446 ;
|
||||
C 172 ; WX 600 ; N guilsinglleft ; B 141 70 459 446 ;
|
||||
C 173 ; WX 600 ; N guilsinglright ; B 141 70 459 446 ;
|
||||
C 174 ; WX 600 ; N fi ; B 12 0 593 626 ;
|
||||
C 175 ; WX 600 ; N fl ; B 12 0 593 626 ;
|
||||
C 177 ; WX 600 ; N endash ; B 65 203 535 313 ;
|
||||
C 178 ; WX 600 ; N dagger ; B 106 -70 494 580 ;
|
||||
C 179 ; WX 600 ; N daggerdbl ; B 106 -70 494 580 ;
|
||||
C 180 ; WX 600 ; N periodcentered ; B 196 165 404 351 ;
|
||||
C 182 ; WX 600 ; N paragraph ; B 6 -70 576 580 ;
|
||||
C 183 ; WX 600 ; N bullet ; B 140 132 460 430 ;
|
||||
C 184 ; WX 600 ; N quotesinglbase ; B 175 -142 427 143 ;
|
||||
C 185 ; WX 600 ; N quotedblbase ; B 65 -142 529 143 ;
|
||||
C 186 ; WX 600 ; N quotedblright ; B 61 277 525 562 ;
|
||||
C 187 ; WX 600 ; N guillemotright ; B 47 70 592 446 ;
|
||||
C 188 ; WX 600 ; N ellipsis ; B 26 -15 574 116 ;
|
||||
C 189 ; WX 600 ; N perthousand ; B -113 -15 713 616 ;
|
||||
C 191 ; WX 600 ; N questiondown ; B 99 -146 502 449 ;
|
||||
C 193 ; WX 600 ; N grave ; B 132 508 395 661 ;
|
||||
C 194 ; WX 600 ; N acute ; B 205 508 468 661 ;
|
||||
C 195 ; WX 600 ; N circumflex ; B 103 483 497 657 ;
|
||||
C 196 ; WX 600 ; N tilde ; B 89 493 512 636 ;
|
||||
C 197 ; WX 600 ; N macron ; B 88 505 512 585 ;
|
||||
C 198 ; WX 600 ; N breve ; B 83 468 517 631 ;
|
||||
C 199 ; WX 600 ; N dotaccent ; B 230 498 370 638 ;
|
||||
C 200 ; WX 600 ; N dieresis ; B 128 498 472 638 ;
|
||||
C 202 ; WX 600 ; N ring ; B 198 481 402 678 ;
|
||||
C 203 ; WX 600 ; N cedilla ; B 205 -206 387 0 ;
|
||||
C 205 ; WX 600 ; N hungarumlaut ; B 68 488 588 661 ;
|
||||
C 206 ; WX 600 ; N ogonek ; B 169 -199 400 0 ;
|
||||
C 207 ; WX 600 ; N caron ; B 103 493 497 667 ;
|
||||
C 208 ; WX 600 ; N emdash ; B -10 203 610 313 ;
|
||||
C 225 ; WX 600 ; N AE ; B -29 0 602 562 ;
|
||||
C 227 ; WX 600 ; N ordfeminine ; B 147 196 453 580 ;
|
||||
C 232 ; WX 600 ; N Lslash ; B 39 0 578 562 ;
|
||||
C 233 ; WX 600 ; N Oslash ; B 22 -22 578 584 ;
|
||||
C 234 ; WX 600 ; N OE ; B -25 0 595 562 ;
|
||||
C 235 ; WX 600 ; N ordmasculine ; B 147 196 453 580 ;
|
||||
C 241 ; WX 600 ; N ae ; B -4 -15 601 454 ;
|
||||
C 245 ; WX 600 ; N dotlessi ; B 77 0 523 439 ;
|
||||
C 248 ; WX 600 ; N lslash ; B 77 0 523 626 ;
|
||||
C 249 ; WX 600 ; N oslash ; B 30 -24 570 463 ;
|
||||
C 250 ; WX 600 ; N oe ; B -18 -15 611 454 ;
|
||||
C 251 ; WX 600 ; N germandbls ; B 22 -15 596 626 ;
|
||||
C -1 ; WX 600 ; N Idieresis ; B 77 0 523 761 ;
|
||||
C -1 ; WX 600 ; N eacute ; B 40 -15 563 661 ;
|
||||
C -1 ; WX 600 ; N abreve ; B 35 -15 570 661 ;
|
||||
C -1 ; WX 600 ; N uhungarumlaut ; B -1 -15 628 661 ;
|
||||
C -1 ; WX 600 ; N ecaron ; B 40 -15 563 667 ;
|
||||
C -1 ; WX 600 ; N Ydieresis ; B 12 0 589 761 ;
|
||||
C -1 ; WX 600 ; N divide ; B 71 16 529 500 ;
|
||||
C -1 ; WX 600 ; N Yacute ; B 12 0 589 784 ;
|
||||
C -1 ; WX 600 ; N Acircumflex ; B -9 0 609 780 ;
|
||||
C -1 ; WX 600 ; N aacute ; B 35 -15 570 661 ;
|
||||
C -1 ; WX 600 ; N Ucircumflex ; B 4 -18 596 780 ;
|
||||
C -1 ; WX 600 ; N yacute ; B -4 -142 601 661 ;
|
||||
C -1 ; WX 600 ; N scommaaccent ; B 68 -250 535 459 ;
|
||||
C -1 ; WX 600 ; N ecircumflex ; B 40 -15 563 657 ;
|
||||
C -1 ; WX 600 ; N Uring ; B 4 -18 596 801 ;
|
||||
C -1 ; WX 600 ; N Udieresis ; B 4 -18 596 761 ;
|
||||
C -1 ; WX 600 ; N aogonek ; B 35 -199 586 454 ;
|
||||
C -1 ; WX 600 ; N Uacute ; B 4 -18 596 784 ;
|
||||
C -1 ; WX 600 ; N uogonek ; B -1 -199 585 439 ;
|
||||
C -1 ; WX 600 ; N Edieresis ; B 25 0 560 761 ;
|
||||
C -1 ; WX 600 ; N Dcroat ; B 30 0 594 562 ;
|
||||
C -1 ; WX 600 ; N commaaccent ; B 205 -250 397 -57 ;
|
||||
C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
|
||||
C -1 ; WX 600 ; N Emacron ; B 25 0 560 708 ;
|
||||
C -1 ; WX 600 ; N ccaron ; B 40 -15 545 667 ;
|
||||
C -1 ; WX 600 ; N aring ; B 35 -15 570 678 ;
|
||||
C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 610 562 ;
|
||||
C -1 ; WX 600 ; N lacute ; B 77 0 523 801 ;
|
||||
C -1 ; WX 600 ; N agrave ; B 35 -15 570 661 ;
|
||||
C -1 ; WX 600 ; N Tcommaaccent ; B 21 -250 579 562 ;
|
||||
C -1 ; WX 600 ; N Cacute ; B 22 -18 560 784 ;
|
||||
C -1 ; WX 600 ; N atilde ; B 35 -15 570 636 ;
|
||||
C -1 ; WX 600 ; N Edotaccent ; B 25 0 560 761 ;
|
||||
C -1 ; WX 600 ; N scaron ; B 68 -17 535 667 ;
|
||||
C -1 ; WX 600 ; N scedilla ; B 68 -206 535 459 ;
|
||||
C -1 ; WX 600 ; N iacute ; B 77 0 523 661 ;
|
||||
C -1 ; WX 600 ; N lozenge ; B 66 0 534 740 ;
|
||||
C -1 ; WX 600 ; N Rcaron ; B 24 0 599 790 ;
|
||||
C -1 ; WX 600 ; N Gcommaaccent ; B 22 -250 594 580 ;
|
||||
C -1 ; WX 600 ; N ucircumflex ; B -1 -15 569 657 ;
|
||||
C -1 ; WX 600 ; N acircumflex ; B 35 -15 570 657 ;
|
||||
C -1 ; WX 600 ; N Amacron ; B -9 0 609 708 ;
|
||||
C -1 ; WX 600 ; N rcaron ; B 47 0 580 667 ;
|
||||
C -1 ; WX 600 ; N ccedilla ; B 40 -206 545 459 ;
|
||||
C -1 ; WX 600 ; N Zdotaccent ; B 62 0 539 761 ;
|
||||
C -1 ; WX 600 ; N Thorn ; B 48 0 557 562 ;
|
||||
C -1 ; WX 600 ; N Omacron ; B 22 -18 578 708 ;
|
||||
C -1 ; WX 600 ; N Racute ; B 24 0 599 784 ;
|
||||
C -1 ; WX 600 ; N Sacute ; B 47 -22 553 784 ;
|
||||
C -1 ; WX 600 ; N dcaron ; B 20 -15 727 626 ;
|
||||
C -1 ; WX 600 ; N Umacron ; B 4 -18 596 708 ;
|
||||
C -1 ; WX 600 ; N uring ; B -1 -15 569 678 ;
|
||||
C -1 ; WX 600 ; N threesuperior ; B 138 222 433 616 ;
|
||||
C -1 ; WX 600 ; N Ograve ; B 22 -18 578 784 ;
|
||||
C -1 ; WX 600 ; N Agrave ; B -9 0 609 784 ;
|
||||
C -1 ; WX 600 ; N Abreve ; B -9 0 609 784 ;
|
||||
C -1 ; WX 600 ; N multiply ; B 81 39 520 478 ;
|
||||
C -1 ; WX 600 ; N uacute ; B -1 -15 569 661 ;
|
||||
C -1 ; WX 600 ; N Tcaron ; B 21 0 579 790 ;
|
||||
C -1 ; WX 600 ; N partialdiff ; B 63 -38 537 728 ;
|
||||
C -1 ; WX 600 ; N ydieresis ; B -4 -142 601 638 ;
|
||||
C -1 ; WX 600 ; N Nacute ; B 8 -12 610 784 ;
|
||||
C -1 ; WX 600 ; N icircumflex ; B 73 0 523 657 ;
|
||||
C -1 ; WX 600 ; N Ecircumflex ; B 25 0 560 780 ;
|
||||
C -1 ; WX 600 ; N adieresis ; B 35 -15 570 638 ;
|
||||
C -1 ; WX 600 ; N edieresis ; B 40 -15 563 638 ;
|
||||
C -1 ; WX 600 ; N cacute ; B 40 -15 545 661 ;
|
||||
C -1 ; WX 600 ; N nacute ; B 18 0 592 661 ;
|
||||
C -1 ; WX 600 ; N umacron ; B -1 -15 569 585 ;
|
||||
C -1 ; WX 600 ; N Ncaron ; B 8 -12 610 790 ;
|
||||
C -1 ; WX 600 ; N Iacute ; B 77 0 523 784 ;
|
||||
C -1 ; WX 600 ; N plusminus ; B 71 24 529 515 ;
|
||||
C -1 ; WX 600 ; N brokenbar ; B 255 -175 345 675 ;
|
||||
C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
|
||||
C -1 ; WX 600 ; N Gbreve ; B 22 -18 594 784 ;
|
||||
C -1 ; WX 600 ; N Idotaccent ; B 77 0 523 761 ;
|
||||
C -1 ; WX 600 ; N summation ; B 15 -10 586 706 ;
|
||||
C -1 ; WX 600 ; N Egrave ; B 25 0 560 784 ;
|
||||
C -1 ; WX 600 ; N racute ; B 47 0 580 661 ;
|
||||
C -1 ; WX 600 ; N omacron ; B 30 -15 570 585 ;
|
||||
C -1 ; WX 600 ; N Zacute ; B 62 0 539 784 ;
|
||||
C -1 ; WX 600 ; N Zcaron ; B 62 0 539 790 ;
|
||||
C -1 ; WX 600 ; N greaterequal ; B 26 0 523 696 ;
|
||||
C -1 ; WX 600 ; N Eth ; B 30 0 594 562 ;
|
||||
C -1 ; WX 600 ; N Ccedilla ; B 22 -206 560 580 ;
|
||||
C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 523 626 ;
|
||||
C -1 ; WX 600 ; N tcaron ; B 47 -15 532 703 ;
|
||||
C -1 ; WX 600 ; N eogonek ; B 40 -199 563 454 ;
|
||||
C -1 ; WX 600 ; N Uogonek ; B 4 -199 596 562 ;
|
||||
C -1 ; WX 600 ; N Aacute ; B -9 0 609 784 ;
|
||||
C -1 ; WX 600 ; N Adieresis ; B -9 0 609 761 ;
|
||||
C -1 ; WX 600 ; N egrave ; B 40 -15 563 661 ;
|
||||
C -1 ; WX 600 ; N zacute ; B 81 0 520 661 ;
|
||||
C -1 ; WX 600 ; N iogonek ; B 77 -199 523 658 ;
|
||||
C -1 ; WX 600 ; N Oacute ; B 22 -18 578 784 ;
|
||||
C -1 ; WX 600 ; N oacute ; B 30 -15 570 661 ;
|
||||
C -1 ; WX 600 ; N amacron ; B 35 -15 570 585 ;
|
||||
C -1 ; WX 600 ; N sacute ; B 68 -17 535 661 ;
|
||||
C -1 ; WX 600 ; N idieresis ; B 77 0 523 618 ;
|
||||
C -1 ; WX 600 ; N Ocircumflex ; B 22 -18 578 780 ;
|
||||
C -1 ; WX 600 ; N Ugrave ; B 4 -18 596 784 ;
|
||||
C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ;
|
||||
C -1 ; WX 600 ; N thorn ; B -14 -142 570 626 ;
|
||||
C -1 ; WX 600 ; N twosuperior ; B 143 230 436 616 ;
|
||||
C -1 ; WX 600 ; N Odieresis ; B 22 -18 578 761 ;
|
||||
C -1 ; WX 600 ; N mu ; B -1 -142 569 439 ;
|
||||
C -1 ; WX 600 ; N igrave ; B 77 0 523 661 ;
|
||||
C -1 ; WX 600 ; N ohungarumlaut ; B 30 -15 668 661 ;
|
||||
C -1 ; WX 600 ; N Eogonek ; B 25 -199 576 562 ;
|
||||
C -1 ; WX 600 ; N dcroat ; B 20 -15 591 626 ;
|
||||
C -1 ; WX 600 ; N threequarters ; B -47 -60 648 661 ;
|
||||
C -1 ; WX 600 ; N Scedilla ; B 47 -206 553 582 ;
|
||||
C -1 ; WX 600 ; N lcaron ; B 77 0 597 626 ;
|
||||
C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 599 562 ;
|
||||
C -1 ; WX 600 ; N Lacute ; B 39 0 578 784 ;
|
||||
C -1 ; WX 600 ; N trademark ; B -9 230 749 562 ;
|
||||
C -1 ; WX 600 ; N edotaccent ; B 40 -15 563 638 ;
|
||||
C -1 ; WX 600 ; N Igrave ; B 77 0 523 784 ;
|
||||
C -1 ; WX 600 ; N Imacron ; B 77 0 523 708 ;
|
||||
C -1 ; WX 600 ; N Lcaron ; B 39 0 637 562 ;
|
||||
C -1 ; WX 600 ; N onehalf ; B -47 -60 648 661 ;
|
||||
C -1 ; WX 600 ; N lessequal ; B 26 0 523 696 ;
|
||||
C -1 ; WX 600 ; N ocircumflex ; B 30 -15 570 657 ;
|
||||
C -1 ; WX 600 ; N ntilde ; B 18 0 592 636 ;
|
||||
C -1 ; WX 600 ; N Uhungarumlaut ; B 4 -18 638 784 ;
|
||||
C -1 ; WX 600 ; N Eacute ; B 25 0 560 784 ;
|
||||
C -1 ; WX 600 ; N emacron ; B 40 -15 563 585 ;
|
||||
C -1 ; WX 600 ; N gbreve ; B 30 -146 580 661 ;
|
||||
C -1 ; WX 600 ; N onequarter ; B -56 -60 656 661 ;
|
||||
C -1 ; WX 600 ; N Scaron ; B 47 -22 553 790 ;
|
||||
C -1 ; WX 600 ; N Scommaaccent ; B 47 -250 553 582 ;
|
||||
C -1 ; WX 600 ; N Ohungarumlaut ; B 22 -18 628 784 ;
|
||||
C -1 ; WX 600 ; N degree ; B 86 243 474 616 ;
|
||||
C -1 ; WX 600 ; N ograve ; B 30 -15 570 661 ;
|
||||
C -1 ; WX 600 ; N Ccaron ; B 22 -18 560 790 ;
|
||||
C -1 ; WX 600 ; N ugrave ; B -1 -15 569 661 ;
|
||||
C -1 ; WX 600 ; N radical ; B -19 -104 473 778 ;
|
||||
C -1 ; WX 600 ; N Dcaron ; B 30 0 594 790 ;
|
||||
C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 580 454 ;
|
||||
C -1 ; WX 600 ; N Ntilde ; B 8 -12 610 759 ;
|
||||
C -1 ; WX 600 ; N otilde ; B 30 -15 570 636 ;
|
||||
C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 599 562 ;
|
||||
C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 578 562 ;
|
||||
C -1 ; WX 600 ; N Atilde ; B -9 0 609 759 ;
|
||||
C -1 ; WX 600 ; N Aogonek ; B -9 -199 625 562 ;
|
||||
C -1 ; WX 600 ; N Aring ; B -9 0 609 801 ;
|
||||
C -1 ; WX 600 ; N Otilde ; B 22 -18 578 759 ;
|
||||
C -1 ; WX 600 ; N zdotaccent ; B 81 0 520 638 ;
|
||||
C -1 ; WX 600 ; N Ecaron ; B 25 0 560 790 ;
|
||||
C -1 ; WX 600 ; N Iogonek ; B 77 -199 523 562 ;
|
||||
C -1 ; WX 600 ; N kcommaaccent ; B 20 -250 585 626 ;
|
||||
C -1 ; WX 600 ; N minus ; B 71 203 529 313 ;
|
||||
C -1 ; WX 600 ; N Icircumflex ; B 77 0 523 780 ;
|
||||
C -1 ; WX 600 ; N ncaron ; B 18 0 592 667 ;
|
||||
C -1 ; WX 600 ; N tcommaaccent ; B 47 -250 532 562 ;
|
||||
C -1 ; WX 600 ; N logicalnot ; B 71 103 529 413 ;
|
||||
C -1 ; WX 600 ; N odieresis ; B 30 -15 570 638 ;
|
||||
C -1 ; WX 600 ; N udieresis ; B -1 -15 569 638 ;
|
||||
C -1 ; WX 600 ; N notequal ; B 12 -47 537 563 ;
|
||||
C -1 ; WX 600 ; N gcommaaccent ; B 30 -146 580 714 ;
|
||||
C -1 ; WX 600 ; N eth ; B 58 -27 543 626 ;
|
||||
C -1 ; WX 600 ; N zcaron ; B 81 0 520 667 ;
|
||||
C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 592 454 ;
|
||||
C -1 ; WX 600 ; N onesuperior ; B 153 230 447 616 ;
|
||||
C -1 ; WX 600 ; N imacron ; B 77 0 523 585 ;
|
||||
C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
|
||||
EndCharMetrics
|
||||
EndFontMetrics
|
@ -0,0 +1,342 @@
|
||||
StartFontMetrics 4.1
|
||||
Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
|
||||
Comment Creation Date: Mon Jun 23 16:28:46 1997
|
||||
Comment UniqueID 43049
|
||||
Comment VMusage 17529 79244
|
||||
FontName Courier-BoldOblique
|
||||
FullName Courier Bold Oblique
|
||||
FamilyName Courier
|
||||
Weight Bold
|
||||
ItalicAngle -12
|
||||
IsFixedPitch true
|
||||
CharacterSet ExtendedRoman
|
||||
FontBBox -57 -250 869 801
|
||||
UnderlinePosition -100
|
||||
UnderlineThickness 50
|
||||
Version 003.000
|
||||
Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
|
||||
EncodingScheme AdobeStandardEncoding
|
||||
CapHeight 562
|
||||
XHeight 439
|
||||
Ascender 629
|
||||
Descender -157
|
||||
StdHW 84
|
||||
StdVW 106
|
||||
StartCharMetrics 315
|
||||
C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
|
||||
C 33 ; WX 600 ; N exclam ; B 215 -15 495 572 ;
|
||||
C 34 ; WX 600 ; N quotedbl ; B 211 277 585 562 ;
|
||||
C 35 ; WX 600 ; N numbersign ; B 88 -45 641 651 ;
|
||||
C 36 ; WX 600 ; N dollar ; B 87 -126 630 666 ;
|
||||
C 37 ; WX 600 ; N percent ; B 101 -15 625 616 ;
|
||||
C 38 ; WX 600 ; N ampersand ; B 61 -15 595 543 ;
|
||||
C 39 ; WX 600 ; N quoteright ; B 229 277 543 562 ;
|
||||
C 40 ; WX 600 ; N parenleft ; B 265 -102 592 616 ;
|
||||
C 41 ; WX 600 ; N parenright ; B 117 -102 444 616 ;
|
||||
C 42 ; WX 600 ; N asterisk ; B 179 219 598 601 ;
|
||||
C 43 ; WX 600 ; N plus ; B 114 39 596 478 ;
|
||||
C 44 ; WX 600 ; N comma ; B 99 -111 430 174 ;
|
||||
C 45 ; WX 600 ; N hyphen ; B 143 203 567 313 ;
|
||||
C 46 ; WX 600 ; N period ; B 206 -15 427 171 ;
|
||||
C 47 ; WX 600 ; N slash ; B 90 -77 626 626 ;
|
||||
C 48 ; WX 600 ; N zero ; B 135 -15 593 616 ;
|
||||
C 49 ; WX 600 ; N one ; B 93 0 562 616 ;
|
||||
C 50 ; WX 600 ; N two ; B 61 0 594 616 ;
|
||||
C 51 ; WX 600 ; N three ; B 71 -15 571 616 ;
|
||||
C 52 ; WX 600 ; N four ; B 81 0 559 616 ;
|
||||
C 53 ; WX 600 ; N five ; B 77 -15 621 601 ;
|
||||
C 54 ; WX 600 ; N six ; B 135 -15 652 616 ;
|
||||
C 55 ; WX 600 ; N seven ; B 147 0 622 601 ;
|
||||
C 56 ; WX 600 ; N eight ; B 115 -15 604 616 ;
|
||||
C 57 ; WX 600 ; N nine ; B 75 -15 592 616 ;
|
||||
C 58 ; WX 600 ; N colon ; B 205 -15 480 425 ;
|
||||
C 59 ; WX 600 ; N semicolon ; B 99 -111 481 425 ;
|
||||
C 60 ; WX 600 ; N less ; B 120 15 613 501 ;
|
||||
C 61 ; WX 600 ; N equal ; B 96 118 614 398 ;
|
||||
C 62 ; WX 600 ; N greater ; B 97 15 589 501 ;
|
||||
C 63 ; WX 600 ; N question ; B 183 -14 592 580 ;
|
||||
C 64 ; WX 600 ; N at ; B 65 -15 642 616 ;
|
||||
C 65 ; WX 600 ; N A ; B -9 0 632 562 ;
|
||||
C 66 ; WX 600 ; N B ; B 30 0 630 562 ;
|
||||
C 67 ; WX 600 ; N C ; B 74 -18 675 580 ;
|
||||
C 68 ; WX 600 ; N D ; B 30 0 664 562 ;
|
||||
C 69 ; WX 600 ; N E ; B 25 0 670 562 ;
|
||||
C 70 ; WX 600 ; N F ; B 39 0 684 562 ;
|
||||
C 71 ; WX 600 ; N G ; B 74 -18 675 580 ;
|
||||
C 72 ; WX 600 ; N H ; B 20 0 700 562 ;
|
||||
C 73 ; WX 600 ; N I ; B 77 0 643 562 ;
|
||||
C 74 ; WX 600 ; N J ; B 58 -18 721 562 ;
|
||||
C 75 ; WX 600 ; N K ; B 21 0 692 562 ;
|
||||
C 76 ; WX 600 ; N L ; B 39 0 636 562 ;
|
||||
C 77 ; WX 600 ; N M ; B -2 0 722 562 ;
|
||||
C 78 ; WX 600 ; N N ; B 8 -12 730 562 ;
|
||||
C 79 ; WX 600 ; N O ; B 74 -18 645 580 ;
|
||||
C 80 ; WX 600 ; N P ; B 48 0 643 562 ;
|
||||
C 81 ; WX 600 ; N Q ; B 83 -138 636 580 ;
|
||||
C 82 ; WX 600 ; N R ; B 24 0 617 562 ;
|
||||
C 83 ; WX 600 ; N S ; B 54 -22 673 582 ;
|
||||
C 84 ; WX 600 ; N T ; B 86 0 679 562 ;
|
||||
C 85 ; WX 600 ; N U ; B 101 -18 716 562 ;
|
||||
C 86 ; WX 600 ; N V ; B 84 0 733 562 ;
|
||||
C 87 ; WX 600 ; N W ; B 79 0 738 562 ;
|
||||
C 88 ; WX 600 ; N X ; B 12 0 690 562 ;
|
||||
C 89 ; WX 600 ; N Y ; B 109 0 709 562 ;
|
||||
C 90 ; WX 600 ; N Z ; B 62 0 637 562 ;
|
||||
C 91 ; WX 600 ; N bracketleft ; B 223 -102 606 616 ;
|
||||
C 92 ; WX 600 ; N backslash ; B 222 -77 496 626 ;
|
||||
C 93 ; WX 600 ; N bracketright ; B 103 -102 486 616 ;
|
||||
C 94 ; WX 600 ; N asciicircum ; B 171 250 556 616 ;
|
||||
C 95 ; WX 600 ; N underscore ; B -27 -125 585 -75 ;
|
||||
C 96 ; WX 600 ; N quoteleft ; B 297 277 487 562 ;
|
||||
C 97 ; WX 600 ; N a ; B 61 -15 593 454 ;
|
||||
C 98 ; WX 600 ; N b ; B 13 -15 636 626 ;
|
||||
C 99 ; WX 600 ; N c ; B 81 -15 631 459 ;
|
||||
C 100 ; WX 600 ; N d ; B 60 -15 645 626 ;
|
||||
C 101 ; WX 600 ; N e ; B 81 -15 605 454 ;
|
||||
C 102 ; WX 600 ; N f ; B 83 0 677 626 ; L i fi ; L l fl ;
|
||||
C 103 ; WX 600 ; N g ; B 40 -146 674 454 ;
|
||||
C 104 ; WX 600 ; N h ; B 18 0 615 626 ;
|
||||
C 105 ; WX 600 ; N i ; B 77 0 546 658 ;
|
||||
C 106 ; WX 600 ; N j ; B 36 -146 580 658 ;
|
||||
C 107 ; WX 600 ; N k ; B 33 0 643 626 ;
|
||||
C 108 ; WX 600 ; N l ; B 77 0 546 626 ;
|
||||
C 109 ; WX 600 ; N m ; B -22 0 649 454 ;
|
||||
C 110 ; WX 600 ; N n ; B 18 0 615 454 ;
|
||||
C 111 ; WX 600 ; N o ; B 71 -15 622 454 ;
|
||||
C 112 ; WX 600 ; N p ; B -32 -142 622 454 ;
|
||||
C 113 ; WX 600 ; N q ; B 60 -142 685 454 ;
|
||||
C 114 ; WX 600 ; N r ; B 47 0 655 454 ;
|
||||
C 115 ; WX 600 ; N s ; B 66 -17 608 459 ;
|
||||
C 116 ; WX 600 ; N t ; B 118 -15 567 562 ;
|
||||
C 117 ; WX 600 ; N u ; B 70 -15 592 439 ;
|
||||
C 118 ; WX 600 ; N v ; B 70 0 695 439 ;
|
||||
C 119 ; WX 600 ; N w ; B 53 0 712 439 ;
|
||||
C 120 ; WX 600 ; N x ; B 6 0 671 439 ;
|
||||
C 121 ; WX 600 ; N y ; B -21 -142 695 439 ;
|
||||
C 122 ; WX 600 ; N z ; B 81 0 614 439 ;
|
||||
C 123 ; WX 600 ; N braceleft ; B 203 -102 595 616 ;
|
||||
C 124 ; WX 600 ; N bar ; B 201 -250 505 750 ;
|
||||
C 125 ; WX 600 ; N braceright ; B 114 -102 506 616 ;
|
||||
C 126 ; WX 600 ; N asciitilde ; B 120 153 590 356 ;
|
||||
C 161 ; WX 600 ; N exclamdown ; B 196 -146 477 449 ;
|
||||
C 162 ; WX 600 ; N cent ; B 121 -49 605 614 ;
|
||||
C 163 ; WX 600 ; N sterling ; B 106 -28 650 611 ;
|
||||
C 164 ; WX 600 ; N fraction ; B 22 -60 708 661 ;
|
||||
C 165 ; WX 600 ; N yen ; B 98 0 710 562 ;
|
||||
C 166 ; WX 600 ; N florin ; B -57 -131 702 616 ;
|
||||
C 167 ; WX 600 ; N section ; B 74 -70 620 580 ;
|
||||
C 168 ; WX 600 ; N currency ; B 77 49 644 517 ;
|
||||
C 169 ; WX 600 ; N quotesingle ; B 303 277 493 562 ;
|
||||
C 170 ; WX 600 ; N quotedblleft ; B 190 277 594 562 ;
|
||||
C 171 ; WX 600 ; N guillemotleft ; B 62 70 639 446 ;
|
||||
C 172 ; WX 600 ; N guilsinglleft ; B 195 70 545 446 ;
|
||||
C 173 ; WX 600 ; N guilsinglright ; B 165 70 514 446 ;
|
||||
C 174 ; WX 600 ; N fi ; B 12 0 644 626 ;
|
||||
C 175 ; WX 600 ; N fl ; B 12 0 644 626 ;
|
||||
C 177 ; WX 600 ; N endash ; B 108 203 602 313 ;
|
||||
C 178 ; WX 600 ; N dagger ; B 175 -70 586 580 ;
|
||||
C 179 ; WX 600 ; N daggerdbl ; B 121 -70 587 580 ;
|
||||
C 180 ; WX 600 ; N periodcentered ; B 248 165 461 351 ;
|
||||
C 182 ; WX 600 ; N paragraph ; B 61 -70 700 580 ;
|
||||
C 183 ; WX 600 ; N bullet ; B 196 132 523 430 ;
|
||||
C 184 ; WX 600 ; N quotesinglbase ; B 144 -142 458 143 ;
|
||||
C 185 ; WX 600 ; N quotedblbase ; B 34 -142 560 143 ;
|
||||
C 186 ; WX 600 ; N quotedblright ; B 119 277 645 562 ;
|
||||
C 187 ; WX 600 ; N guillemotright ; B 71 70 647 446 ;
|
||||
C 188 ; WX 600 ; N ellipsis ; B 35 -15 587 116 ;
|
||||
C 189 ; WX 600 ; N perthousand ; B -45 -15 743 616 ;
|
||||
C 191 ; WX 600 ; N questiondown ; B 100 -146 509 449 ;
|
||||
C 193 ; WX 600 ; N grave ; B 272 508 503 661 ;
|
||||
C 194 ; WX 600 ; N acute ; B 312 508 609 661 ;
|
||||
C 195 ; WX 600 ; N circumflex ; B 212 483 607 657 ;
|
||||
C 196 ; WX 600 ; N tilde ; B 199 493 643 636 ;
|
||||
C 197 ; WX 600 ; N macron ; B 195 505 637 585 ;
|
||||
C 198 ; WX 600 ; N breve ; B 217 468 652 631 ;
|
||||
C 199 ; WX 600 ; N dotaccent ; B 348 498 493 638 ;
|
||||
C 200 ; WX 600 ; N dieresis ; B 246 498 595 638 ;
|
||||
C 202 ; WX 600 ; N ring ; B 319 481 528 678 ;
|
||||
C 203 ; WX 600 ; N cedilla ; B 168 -206 368 0 ;
|
||||
C 205 ; WX 600 ; N hungarumlaut ; B 171 488 729 661 ;
|
||||
C 206 ; WX 600 ; N ogonek ; B 143 -199 367 0 ;
|
||||
C 207 ; WX 600 ; N caron ; B 238 493 633 667 ;
|
||||
C 208 ; WX 600 ; N emdash ; B 33 203 677 313 ;
|
||||
C 225 ; WX 600 ; N AE ; B -29 0 708 562 ;
|
||||
C 227 ; WX 600 ; N ordfeminine ; B 188 196 526 580 ;
|
||||
C 232 ; WX 600 ; N Lslash ; B 39 0 636 562 ;
|
||||
C 233 ; WX 600 ; N Oslash ; B 48 -22 673 584 ;
|
||||
C 234 ; WX 600 ; N OE ; B 26 0 701 562 ;
|
||||
C 235 ; WX 600 ; N ordmasculine ; B 188 196 543 580 ;
|
||||
C 241 ; WX 600 ; N ae ; B 21 -15 652 454 ;
|
||||
C 245 ; WX 600 ; N dotlessi ; B 77 0 546 439 ;
|
||||
C 248 ; WX 600 ; N lslash ; B 77 0 587 626 ;
|
||||
C 249 ; WX 600 ; N oslash ; B 54 -24 638 463 ;
|
||||
C 250 ; WX 600 ; N oe ; B 18 -15 662 454 ;
|
||||
C 251 ; WX 600 ; N germandbls ; B 22 -15 629 626 ;
|
||||
C -1 ; WX 600 ; N Idieresis ; B 77 0 643 761 ;
|
||||
C -1 ; WX 600 ; N eacute ; B 81 -15 609 661 ;
|
||||
C -1 ; WX 600 ; N abreve ; B 61 -15 658 661 ;
|
||||
C -1 ; WX 600 ; N uhungarumlaut ; B 70 -15 769 661 ;
|
||||
C -1 ; WX 600 ; N ecaron ; B 81 -15 633 667 ;
|
||||
C -1 ; WX 600 ; N Ydieresis ; B 109 0 709 761 ;
|
||||
C -1 ; WX 600 ; N divide ; B 114 16 596 500 ;
|
||||
C -1 ; WX 600 ; N Yacute ; B 109 0 709 784 ;
|
||||
C -1 ; WX 600 ; N Acircumflex ; B -9 0 632 780 ;
|
||||
C -1 ; WX 600 ; N aacute ; B 61 -15 609 661 ;
|
||||
C -1 ; WX 600 ; N Ucircumflex ; B 101 -18 716 780 ;
|
||||
C -1 ; WX 600 ; N yacute ; B -21 -142 695 661 ;
|
||||
C -1 ; WX 600 ; N scommaaccent ; B 66 -250 608 459 ;
|
||||
C -1 ; WX 600 ; N ecircumflex ; B 81 -15 607 657 ;
|
||||
C -1 ; WX 600 ; N Uring ; B 101 -18 716 801 ;
|
||||
C -1 ; WX 600 ; N Udieresis ; B 101 -18 716 761 ;
|
||||
C -1 ; WX 600 ; N aogonek ; B 61 -199 593 454 ;
|
||||
C -1 ; WX 600 ; N Uacute ; B 101 -18 716 784 ;
|
||||
C -1 ; WX 600 ; N uogonek ; B 70 -199 592 439 ;
|
||||
C -1 ; WX 600 ; N Edieresis ; B 25 0 670 761 ;
|
||||
C -1 ; WX 600 ; N Dcroat ; B 30 0 664 562 ;
|
||||
C -1 ; WX 600 ; N commaaccent ; B 151 -250 385 -57 ;
|
||||
C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
|
||||
C -1 ; WX 600 ; N Emacron ; B 25 0 670 708 ;
|
||||
C -1 ; WX 600 ; N ccaron ; B 81 -15 633 667 ;
|
||||
C -1 ; WX 600 ; N aring ; B 61 -15 593 678 ;
|
||||
C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 730 562 ;
|
||||
C -1 ; WX 600 ; N lacute ; B 77 0 639 801 ;
|
||||
C -1 ; WX 600 ; N agrave ; B 61 -15 593 661 ;
|
||||
C -1 ; WX 600 ; N Tcommaaccent ; B 86 -250 679 562 ;
|
||||
C -1 ; WX 600 ; N Cacute ; B 74 -18 675 784 ;
|
||||
C -1 ; WX 600 ; N atilde ; B 61 -15 643 636 ;
|
||||
C -1 ; WX 600 ; N Edotaccent ; B 25 0 670 761 ;
|
||||
C -1 ; WX 600 ; N scaron ; B 66 -17 633 667 ;
|
||||
C -1 ; WX 600 ; N scedilla ; B 66 -206 608 459 ;
|
||||
C -1 ; WX 600 ; N iacute ; B 77 0 609 661 ;
|
||||
C -1 ; WX 600 ; N lozenge ; B 145 0 614 740 ;
|
||||
C -1 ; WX 600 ; N Rcaron ; B 24 0 659 790 ;
|
||||
C -1 ; WX 600 ; N Gcommaaccent ; B 74 -250 675 580 ;
|
||||
C -1 ; WX 600 ; N ucircumflex ; B 70 -15 597 657 ;
|
||||
C -1 ; WX 600 ; N acircumflex ; B 61 -15 607 657 ;
|
||||
C -1 ; WX 600 ; N Amacron ; B -9 0 633 708 ;
|
||||
C -1 ; WX 600 ; N rcaron ; B 47 0 655 667 ;
|
||||
C -1 ; WX 600 ; N ccedilla ; B 81 -206 631 459 ;
|
||||
C -1 ; WX 600 ; N Zdotaccent ; B 62 0 637 761 ;
|
||||
C -1 ; WX 600 ; N Thorn ; B 48 0 620 562 ;
|
||||
C -1 ; WX 600 ; N Omacron ; B 74 -18 663 708 ;
|
||||
C -1 ; WX 600 ; N Racute ; B 24 0 665 784 ;
|
||||
C -1 ; WX 600 ; N Sacute ; B 54 -22 673 784 ;
|
||||
C -1 ; WX 600 ; N dcaron ; B 60 -15 861 626 ;
|
||||
C -1 ; WX 600 ; N Umacron ; B 101 -18 716 708 ;
|
||||
C -1 ; WX 600 ; N uring ; B 70 -15 592 678 ;
|
||||
C -1 ; WX 600 ; N threesuperior ; B 193 222 526 616 ;
|
||||
C -1 ; WX 600 ; N Ograve ; B 74 -18 645 784 ;
|
||||
C -1 ; WX 600 ; N Agrave ; B -9 0 632 784 ;
|
||||
C -1 ; WX 600 ; N Abreve ; B -9 0 684 784 ;
|
||||
C -1 ; WX 600 ; N multiply ; B 104 39 606 478 ;
|
||||
C -1 ; WX 600 ; N uacute ; B 70 -15 599 661 ;
|
||||
C -1 ; WX 600 ; N Tcaron ; B 86 0 679 790 ;
|
||||
C -1 ; WX 600 ; N partialdiff ; B 91 -38 627 728 ;
|
||||
C -1 ; WX 600 ; N ydieresis ; B -21 -142 695 638 ;
|
||||
C -1 ; WX 600 ; N Nacute ; B 8 -12 730 784 ;
|
||||
C -1 ; WX 600 ; N icircumflex ; B 77 0 577 657 ;
|
||||
C -1 ; WX 600 ; N Ecircumflex ; B 25 0 670 780 ;
|
||||
C -1 ; WX 600 ; N adieresis ; B 61 -15 595 638 ;
|
||||
C -1 ; WX 600 ; N edieresis ; B 81 -15 605 638 ;
|
||||
C -1 ; WX 600 ; N cacute ; B 81 -15 649 661 ;
|
||||
C -1 ; WX 600 ; N nacute ; B 18 0 639 661 ;
|
||||
C -1 ; WX 600 ; N umacron ; B 70 -15 637 585 ;
|
||||
C -1 ; WX 600 ; N Ncaron ; B 8 -12 730 790 ;
|
||||
C -1 ; WX 600 ; N Iacute ; B 77 0 643 784 ;
|
||||
C -1 ; WX 600 ; N plusminus ; B 76 24 614 515 ;
|
||||
C -1 ; WX 600 ; N brokenbar ; B 217 -175 489 675 ;
|
||||
C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
|
||||
C -1 ; WX 600 ; N Gbreve ; B 74 -18 684 784 ;
|
||||
C -1 ; WX 600 ; N Idotaccent ; B 77 0 643 761 ;
|
||||
C -1 ; WX 600 ; N summation ; B 15 -10 672 706 ;
|
||||
C -1 ; WX 600 ; N Egrave ; B 25 0 670 784 ;
|
||||
C -1 ; WX 600 ; N racute ; B 47 0 655 661 ;
|
||||
C -1 ; WX 600 ; N omacron ; B 71 -15 637 585 ;
|
||||
C -1 ; WX 600 ; N Zacute ; B 62 0 665 784 ;
|
||||
C -1 ; WX 600 ; N Zcaron ; B 62 0 659 790 ;
|
||||
C -1 ; WX 600 ; N greaterequal ; B 26 0 627 696 ;
|
||||
C -1 ; WX 600 ; N Eth ; B 30 0 664 562 ;
|
||||
C -1 ; WX 600 ; N Ccedilla ; B 74 -206 675 580 ;
|
||||
C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 546 626 ;
|
||||
C -1 ; WX 600 ; N tcaron ; B 118 -15 627 703 ;
|
||||
C -1 ; WX 600 ; N eogonek ; B 81 -199 605 454 ;
|
||||
C -1 ; WX 600 ; N Uogonek ; B 101 -199 716 562 ;
|
||||
C -1 ; WX 600 ; N Aacute ; B -9 0 655 784 ;
|
||||
C -1 ; WX 600 ; N Adieresis ; B -9 0 632 761 ;
|
||||
C -1 ; WX 600 ; N egrave ; B 81 -15 605 661 ;
|
||||
C -1 ; WX 600 ; N zacute ; B 81 0 614 661 ;
|
||||
C -1 ; WX 600 ; N iogonek ; B 77 -199 546 658 ;
|
||||
C -1 ; WX 600 ; N Oacute ; B 74 -18 645 784 ;
|
||||
C -1 ; WX 600 ; N oacute ; B 71 -15 649 661 ;
|
||||
C -1 ; WX 600 ; N amacron ; B 61 -15 637 585 ;
|
||||
C -1 ; WX 600 ; N sacute ; B 66 -17 609 661 ;
|
||||
C -1 ; WX 600 ; N idieresis ; B 77 0 561 618 ;
|
||||
C -1 ; WX 600 ; N Ocircumflex ; B 74 -18 645 780 ;
|
||||
C -1 ; WX 600 ; N Ugrave ; B 101 -18 716 784 ;
|
||||
C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ;
|
||||
C -1 ; WX 600 ; N thorn ; B -32 -142 622 626 ;
|
||||
C -1 ; WX 600 ; N twosuperior ; B 191 230 542 616 ;
|
||||
C -1 ; WX 600 ; N Odieresis ; B 74 -18 645 761 ;
|
||||
C -1 ; WX 600 ; N mu ; B 49 -142 592 439 ;
|
||||
C -1 ; WX 600 ; N igrave ; B 77 0 546 661 ;
|
||||
C -1 ; WX 600 ; N ohungarumlaut ; B 71 -15 809 661 ;
|
||||
C -1 ; WX 600 ; N Eogonek ; B 25 -199 670 562 ;
|
||||
C -1 ; WX 600 ; N dcroat ; B 60 -15 712 626 ;
|
||||
C -1 ; WX 600 ; N threequarters ; B 8 -60 699 661 ;
|
||||
C -1 ; WX 600 ; N Scedilla ; B 54 -206 673 582 ;
|
||||
C -1 ; WX 600 ; N lcaron ; B 77 0 731 626 ;
|
||||
C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 692 562 ;
|
||||
C -1 ; WX 600 ; N Lacute ; B 39 0 636 784 ;
|
||||
C -1 ; WX 600 ; N trademark ; B 86 230 869 562 ;
|
||||
C -1 ; WX 600 ; N edotaccent ; B 81 -15 605 638 ;
|
||||
C -1 ; WX 600 ; N Igrave ; B 77 0 643 784 ;
|
||||
C -1 ; WX 600 ; N Imacron ; B 77 0 663 708 ;
|
||||
C -1 ; WX 600 ; N Lcaron ; B 39 0 757 562 ;
|
||||
C -1 ; WX 600 ; N onehalf ; B 22 -60 716 661 ;
|
||||
C -1 ; WX 600 ; N lessequal ; B 26 0 671 696 ;
|
||||
C -1 ; WX 600 ; N ocircumflex ; B 71 -15 622 657 ;
|
||||
C -1 ; WX 600 ; N ntilde ; B 18 0 643 636 ;
|
||||
C -1 ; WX 600 ; N Uhungarumlaut ; B 101 -18 805 784 ;
|
||||
C -1 ; WX 600 ; N Eacute ; B 25 0 670 784 ;
|
||||
C -1 ; WX 600 ; N emacron ; B 81 -15 637 585 ;
|
||||
C -1 ; WX 600 ; N gbreve ; B 40 -146 674 661 ;
|
||||
C -1 ; WX 600 ; N onequarter ; B 13 -60 707 661 ;
|
||||
C -1 ; WX 600 ; N Scaron ; B 54 -22 689 790 ;
|
||||
C -1 ; WX 600 ; N Scommaaccent ; B 54 -250 673 582 ;
|
||||
C -1 ; WX 600 ; N Ohungarumlaut ; B 74 -18 795 784 ;
|
||||
C -1 ; WX 600 ; N degree ; B 173 243 570 616 ;
|
||||
C -1 ; WX 600 ; N ograve ; B 71 -15 622 661 ;
|
||||
C -1 ; WX 600 ; N Ccaron ; B 74 -18 689 790 ;
|
||||
C -1 ; WX 600 ; N ugrave ; B 70 -15 592 661 ;
|
||||
C -1 ; WX 600 ; N radical ; B 67 -104 635 778 ;
|
||||
C -1 ; WX 600 ; N Dcaron ; B 30 0 664 790 ;
|
||||
C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 655 454 ;
|
||||
C -1 ; WX 600 ; N Ntilde ; B 8 -12 730 759 ;
|
||||
C -1 ; WX 600 ; N otilde ; B 71 -15 643 636 ;
|
||||
C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 617 562 ;
|
||||
C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 636 562 ;
|
||||
C -1 ; WX 600 ; N Atilde ; B -9 0 669 759 ;
|
||||
C -1 ; WX 600 ; N Aogonek ; B -9 -199 632 562 ;
|
||||
C -1 ; WX 600 ; N Aring ; B -9 0 632 801 ;
|
||||
C -1 ; WX 600 ; N Otilde ; B 74 -18 669 759 ;
|
||||
C -1 ; WX 600 ; N zdotaccent ; B 81 0 614 638 ;
|
||||
C -1 ; WX 600 ; N Ecaron ; B 25 0 670 790 ;
|
||||
C -1 ; WX 600 ; N Iogonek ; B 77 -199 643 562 ;
|
||||
C -1 ; WX 600 ; N kcommaaccent ; B 33 -250 643 626 ;
|
||||
C -1 ; WX 600 ; N minus ; B 114 203 596 313 ;
|
||||
C -1 ; WX 600 ; N Icircumflex ; B 77 0 643 780 ;
|
||||
C -1 ; WX 600 ; N ncaron ; B 18 0 633 667 ;
|
||||
C -1 ; WX 600 ; N tcommaaccent ; B 118 -250 567 562 ;
|
||||
C -1 ; WX 600 ; N logicalnot ; B 135 103 617 413 ;
|
||||
C -1 ; WX 600 ; N odieresis ; B 71 -15 622 638 ;
|
||||
C -1 ; WX 600 ; N udieresis ; B 70 -15 595 638 ;
|
||||
C -1 ; WX 600 ; N notequal ; B 30 -47 626 563 ;
|
||||
C -1 ; WX 600 ; N gcommaaccent ; B 40 -146 674 714 ;
|
||||
C -1 ; WX 600 ; N eth ; B 93 -27 661 626 ;
|
||||
C -1 ; WX 600 ; N zcaron ; B 81 0 643 667 ;
|
||||
C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 615 454 ;
|
||||
C -1 ; WX 600 ; N onesuperior ; B 212 230 514 616 ;
|
||||
C -1 ; WX 600 ; N imacron ; B 77 0 575 585 ;
|
||||
C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
|
||||
EndCharMetrics
|
||||
EndFontMetrics
|
@ -0,0 +1,342 @@
|
||||
StartFontMetrics 4.1
|
||||
Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
|
||||
Comment Creation Date: Thu May 1 17:37:52 1997
|
||||
Comment UniqueID 43051
|
||||
Comment VMusage 16248 75829
|
||||
FontName Courier-Oblique
|
||||
FullName Courier Oblique
|
||||
FamilyName Courier
|
||||
Weight Medium
|
||||
ItalicAngle -12
|
||||
IsFixedPitch true
|
||||
CharacterSet ExtendedRoman
|
||||
FontBBox -27 -250 849 805
|
||||
UnderlinePosition -100
|
||||
UnderlineThickness 50
|
||||
Version 003.000
|
||||
Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
|
||||
EncodingScheme AdobeStandardEncoding
|
||||
CapHeight 562
|
||||
XHeight 426
|
||||
Ascender 629
|
||||
Descender -157
|
||||
StdHW 51
|
||||
StdVW 51
|
||||
StartCharMetrics 315
|
||||
C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
|
||||
C 33 ; WX 600 ; N exclam ; B 243 -15 464 572 ;
|
||||
C 34 ; WX 600 ; N quotedbl ; B 273 328 532 562 ;
|
||||
C 35 ; WX 600 ; N numbersign ; B 133 -32 596 639 ;
|
||||
C 36 ; WX 600 ; N dollar ; B 108 -126 596 662 ;
|
||||
C 37 ; WX 600 ; N percent ; B 134 -15 599 622 ;
|
||||
C 38 ; WX 600 ; N ampersand ; B 87 -15 580 543 ;
|
||||
C 39 ; WX 600 ; N quoteright ; B 283 328 495 562 ;
|
||||
C 40 ; WX 600 ; N parenleft ; B 313 -108 572 622 ;
|
||||
C 41 ; WX 600 ; N parenright ; B 137 -108 396 622 ;
|
||||
C 42 ; WX 600 ; N asterisk ; B 212 257 580 607 ;
|
||||
C 43 ; WX 600 ; N plus ; B 129 44 580 470 ;
|
||||
C 44 ; WX 600 ; N comma ; B 157 -112 370 122 ;
|
||||
C 45 ; WX 600 ; N hyphen ; B 152 231 558 285 ;
|
||||
C 46 ; WX 600 ; N period ; B 238 -15 382 109 ;
|
||||
C 47 ; WX 600 ; N slash ; B 112 -80 604 629 ;
|
||||
C 48 ; WX 600 ; N zero ; B 154 -15 575 622 ;
|
||||
C 49 ; WX 600 ; N one ; B 98 0 515 622 ;
|
||||
C 50 ; WX 600 ; N two ; B 70 0 568 622 ;
|
||||
C 51 ; WX 600 ; N three ; B 82 -15 538 622 ;
|
||||
C 52 ; WX 600 ; N four ; B 108 0 541 622 ;
|
||||
C 53 ; WX 600 ; N five ; B 99 -15 589 607 ;
|
||||
C 54 ; WX 600 ; N six ; B 155 -15 629 622 ;
|
||||
C 55 ; WX 600 ; N seven ; B 182 0 612 607 ;
|
||||
C 56 ; WX 600 ; N eight ; B 132 -15 588 622 ;
|
||||
C 57 ; WX 600 ; N nine ; B 93 -15 574 622 ;
|
||||
C 58 ; WX 600 ; N colon ; B 238 -15 441 385 ;
|
||||
C 59 ; WX 600 ; N semicolon ; B 157 -112 441 385 ;
|
||||
C 60 ; WX 600 ; N less ; B 96 42 610 472 ;
|
||||
C 61 ; WX 600 ; N equal ; B 109 138 600 376 ;
|
||||
C 62 ; WX 600 ; N greater ; B 85 42 599 472 ;
|
||||
C 63 ; WX 600 ; N question ; B 222 -15 583 572 ;
|
||||
C 64 ; WX 600 ; N at ; B 127 -15 582 622 ;
|
||||
C 65 ; WX 600 ; N A ; B 3 0 607 562 ;
|
||||
C 66 ; WX 600 ; N B ; B 43 0 616 562 ;
|
||||
C 67 ; WX 600 ; N C ; B 93 -18 655 580 ;
|
||||
C 68 ; WX 600 ; N D ; B 43 0 645 562 ;
|
||||
C 69 ; WX 600 ; N E ; B 53 0 660 562 ;
|
||||
C 70 ; WX 600 ; N F ; B 53 0 660 562 ;
|
||||
C 71 ; WX 600 ; N G ; B 83 -18 645 580 ;
|
||||
C 72 ; WX 600 ; N H ; B 32 0 687 562 ;
|
||||
C 73 ; WX 600 ; N I ; B 96 0 623 562 ;
|
||||
C 74 ; WX 600 ; N J ; B 52 -18 685 562 ;
|
||||
C 75 ; WX 600 ; N K ; B 38 0 671 562 ;
|
||||
C 76 ; WX 600 ; N L ; B 47 0 607 562 ;
|
||||
C 77 ; WX 600 ; N M ; B 4 0 715 562 ;
|
||||
C 78 ; WX 600 ; N N ; B 7 -13 712 562 ;
|
||||
C 79 ; WX 600 ; N O ; B 94 -18 625 580 ;
|
||||
C 80 ; WX 600 ; N P ; B 79 0 644 562 ;
|
||||
C 81 ; WX 600 ; N Q ; B 95 -138 625 580 ;
|
||||
C 82 ; WX 600 ; N R ; B 38 0 598 562 ;
|
||||
C 83 ; WX 600 ; N S ; B 76 -20 650 580 ;
|
||||
C 84 ; WX 600 ; N T ; B 108 0 665 562 ;
|
||||
C 85 ; WX 600 ; N U ; B 125 -18 702 562 ;
|
||||
C 86 ; WX 600 ; N V ; B 105 -13 723 562 ;
|
||||
C 87 ; WX 600 ; N W ; B 106 -13 722 562 ;
|
||||
C 88 ; WX 600 ; N X ; B 23 0 675 562 ;
|
||||
C 89 ; WX 600 ; N Y ; B 133 0 695 562 ;
|
||||
C 90 ; WX 600 ; N Z ; B 86 0 610 562 ;
|
||||
C 91 ; WX 600 ; N bracketleft ; B 246 -108 574 622 ;
|
||||
C 92 ; WX 600 ; N backslash ; B 249 -80 468 629 ;
|
||||
C 93 ; WX 600 ; N bracketright ; B 135 -108 463 622 ;
|
||||
C 94 ; WX 600 ; N asciicircum ; B 175 354 587 622 ;
|
||||
C 95 ; WX 600 ; N underscore ; B -27 -125 584 -75 ;
|
||||
C 96 ; WX 600 ; N quoteleft ; B 343 328 457 562 ;
|
||||
C 97 ; WX 600 ; N a ; B 76 -15 569 441 ;
|
||||
C 98 ; WX 600 ; N b ; B 29 -15 625 629 ;
|
||||
C 99 ; WX 600 ; N c ; B 106 -15 608 441 ;
|
||||
C 100 ; WX 600 ; N d ; B 85 -15 640 629 ;
|
||||
C 101 ; WX 600 ; N e ; B 106 -15 598 441 ;
|
||||
C 102 ; WX 600 ; N f ; B 114 0 662 629 ; L i fi ; L l fl ;
|
||||
C 103 ; WX 600 ; N g ; B 61 -157 657 441 ;
|
||||
C 104 ; WX 600 ; N h ; B 33 0 592 629 ;
|
||||
C 105 ; WX 600 ; N i ; B 95 0 515 657 ;
|
||||
C 106 ; WX 600 ; N j ; B 52 -157 550 657 ;
|
||||
C 107 ; WX 600 ; N k ; B 58 0 633 629 ;
|
||||
C 108 ; WX 600 ; N l ; B 95 0 515 629 ;
|
||||
C 109 ; WX 600 ; N m ; B -5 0 615 441 ;
|
||||
C 110 ; WX 600 ; N n ; B 26 0 585 441 ;
|
||||
C 111 ; WX 600 ; N o ; B 102 -15 588 441 ;
|
||||
C 112 ; WX 600 ; N p ; B -24 -157 605 441 ;
|
||||
C 113 ; WX 600 ; N q ; B 85 -157 682 441 ;
|
||||
C 114 ; WX 600 ; N r ; B 60 0 636 441 ;
|
||||
C 115 ; WX 600 ; N s ; B 78 -15 584 441 ;
|
||||
C 116 ; WX 600 ; N t ; B 167 -15 561 561 ;
|
||||
C 117 ; WX 600 ; N u ; B 101 -15 572 426 ;
|
||||
C 118 ; WX 600 ; N v ; B 90 -10 681 426 ;
|
||||
C 119 ; WX 600 ; N w ; B 76 -10 695 426 ;
|
||||
C 120 ; WX 600 ; N x ; B 20 0 655 426 ;
|
||||
C 121 ; WX 600 ; N y ; B -4 -157 683 426 ;
|
||||
C 122 ; WX 600 ; N z ; B 99 0 593 426 ;
|
||||
C 123 ; WX 600 ; N braceleft ; B 233 -108 569 622 ;
|
||||
C 124 ; WX 600 ; N bar ; B 222 -250 485 750 ;
|
||||
C 125 ; WX 600 ; N braceright ; B 140 -108 477 622 ;
|
||||
C 126 ; WX 600 ; N asciitilde ; B 116 197 600 320 ;
|
||||
C 161 ; WX 600 ; N exclamdown ; B 225 -157 445 430 ;
|
||||
C 162 ; WX 600 ; N cent ; B 151 -49 588 614 ;
|
||||
C 163 ; WX 600 ; N sterling ; B 124 -21 621 611 ;
|
||||
C 164 ; WX 600 ; N fraction ; B 84 -57 646 665 ;
|
||||
C 165 ; WX 600 ; N yen ; B 120 0 693 562 ;
|
||||
C 166 ; WX 600 ; N florin ; B -26 -143 671 622 ;
|
||||
C 167 ; WX 600 ; N section ; B 104 -78 590 580 ;
|
||||
C 168 ; WX 600 ; N currency ; B 94 58 628 506 ;
|
||||
C 169 ; WX 600 ; N quotesingle ; B 345 328 460 562 ;
|
||||
C 170 ; WX 600 ; N quotedblleft ; B 262 328 541 562 ;
|
||||
C 171 ; WX 600 ; N guillemotleft ; B 92 70 652 446 ;
|
||||
C 172 ; WX 600 ; N guilsinglleft ; B 204 70 540 446 ;
|
||||
C 173 ; WX 600 ; N guilsinglright ; B 170 70 506 446 ;
|
||||
C 174 ; WX 600 ; N fi ; B 3 0 619 629 ;
|
||||
C 175 ; WX 600 ; N fl ; B 3 0 619 629 ;
|
||||
C 177 ; WX 600 ; N endash ; B 124 231 586 285 ;
|
||||
C 178 ; WX 600 ; N dagger ; B 217 -78 546 580 ;
|
||||
C 179 ; WX 600 ; N daggerdbl ; B 163 -78 546 580 ;
|
||||
C 180 ; WX 600 ; N periodcentered ; B 275 189 434 327 ;
|
||||
C 182 ; WX 600 ; N paragraph ; B 100 -78 630 562 ;
|
||||
C 183 ; WX 600 ; N bullet ; B 224 130 485 383 ;
|
||||
C 184 ; WX 600 ; N quotesinglbase ; B 185 -134 397 100 ;
|
||||
C 185 ; WX 600 ; N quotedblbase ; B 115 -134 478 100 ;
|
||||
C 186 ; WX 600 ; N quotedblright ; B 213 328 576 562 ;
|
||||
C 187 ; WX 600 ; N guillemotright ; B 58 70 618 446 ;
|
||||
C 188 ; WX 600 ; N ellipsis ; B 46 -15 575 111 ;
|
||||
C 189 ; WX 600 ; N perthousand ; B 59 -15 627 622 ;
|
||||
C 191 ; WX 600 ; N questiondown ; B 105 -157 466 430 ;
|
||||
C 193 ; WX 600 ; N grave ; B 294 497 484 672 ;
|
||||
C 194 ; WX 600 ; N acute ; B 348 497 612 672 ;
|
||||
C 195 ; WX 600 ; N circumflex ; B 229 477 581 654 ;
|
||||
C 196 ; WX 600 ; N tilde ; B 212 489 629 606 ;
|
||||
C 197 ; WX 600 ; N macron ; B 232 525 600 565 ;
|
||||
C 198 ; WX 600 ; N breve ; B 279 501 576 609 ;
|
||||
C 199 ; WX 600 ; N dotaccent ; B 373 537 478 640 ;
|
||||
C 200 ; WX 600 ; N dieresis ; B 272 537 579 640 ;
|
||||
C 202 ; WX 600 ; N ring ; B 332 463 500 627 ;
|
||||
C 203 ; WX 600 ; N cedilla ; B 197 -151 344 10 ;
|
||||
C 205 ; WX 600 ; N hungarumlaut ; B 239 497 683 672 ;
|
||||
C 206 ; WX 600 ; N ogonek ; B 189 -172 377 4 ;
|
||||
C 207 ; WX 600 ; N caron ; B 262 492 614 669 ;
|
||||
C 208 ; WX 600 ; N emdash ; B 49 231 661 285 ;
|
||||
C 225 ; WX 600 ; N AE ; B 3 0 655 562 ;
|
||||
C 227 ; WX 600 ; N ordfeminine ; B 209 249 512 580 ;
|
||||
C 232 ; WX 600 ; N Lslash ; B 47 0 607 562 ;
|
||||
C 233 ; WX 600 ; N Oslash ; B 94 -80 625 629 ;
|
||||
C 234 ; WX 600 ; N OE ; B 59 0 672 562 ;
|
||||
C 235 ; WX 600 ; N ordmasculine ; B 210 249 535 580 ;
|
||||
C 241 ; WX 600 ; N ae ; B 41 -15 626 441 ;
|
||||
C 245 ; WX 600 ; N dotlessi ; B 95 0 515 426 ;
|
||||
C 248 ; WX 600 ; N lslash ; B 95 0 587 629 ;
|
||||
C 249 ; WX 600 ; N oslash ; B 102 -80 588 506 ;
|
||||
C 250 ; WX 600 ; N oe ; B 54 -15 615 441 ;
|
||||
C 251 ; WX 600 ; N germandbls ; B 48 -15 617 629 ;
|
||||
C -1 ; WX 600 ; N Idieresis ; B 96 0 623 753 ;
|
||||
C -1 ; WX 600 ; N eacute ; B 106 -15 612 672 ;
|
||||
C -1 ; WX 600 ; N abreve ; B 76 -15 576 609 ;
|
||||
C -1 ; WX 600 ; N uhungarumlaut ; B 101 -15 723 672 ;
|
||||
C -1 ; WX 600 ; N ecaron ; B 106 -15 614 669 ;
|
||||
C -1 ; WX 600 ; N Ydieresis ; B 133 0 695 753 ;
|
||||
C -1 ; WX 600 ; N divide ; B 136 48 573 467 ;
|
||||
C -1 ; WX 600 ; N Yacute ; B 133 0 695 805 ;
|
||||
C -1 ; WX 600 ; N Acircumflex ; B 3 0 607 787 ;
|
||||
C -1 ; WX 600 ; N aacute ; B 76 -15 612 672 ;
|
||||
C -1 ; WX 600 ; N Ucircumflex ; B 125 -18 702 787 ;
|
||||
C -1 ; WX 600 ; N yacute ; B -4 -157 683 672 ;
|
||||
C -1 ; WX 600 ; N scommaaccent ; B 78 -250 584 441 ;
|
||||
C -1 ; WX 600 ; N ecircumflex ; B 106 -15 598 654 ;
|
||||
C -1 ; WX 600 ; N Uring ; B 125 -18 702 760 ;
|
||||
C -1 ; WX 600 ; N Udieresis ; B 125 -18 702 753 ;
|
||||
C -1 ; WX 600 ; N aogonek ; B 76 -172 569 441 ;
|
||||
C -1 ; WX 600 ; N Uacute ; B 125 -18 702 805 ;
|
||||
C -1 ; WX 600 ; N uogonek ; B 101 -172 572 426 ;
|
||||
C -1 ; WX 600 ; N Edieresis ; B 53 0 660 753 ;
|
||||
C -1 ; WX 600 ; N Dcroat ; B 43 0 645 562 ;
|
||||
C -1 ; WX 600 ; N commaaccent ; B 145 -250 323 -58 ;
|
||||
C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
|
||||
C -1 ; WX 600 ; N Emacron ; B 53 0 660 698 ;
|
||||
C -1 ; WX 600 ; N ccaron ; B 106 -15 614 669 ;
|
||||
C -1 ; WX 600 ; N aring ; B 76 -15 569 627 ;
|
||||
C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 712 562 ;
|
||||
C -1 ; WX 600 ; N lacute ; B 95 0 640 805 ;
|
||||
C -1 ; WX 600 ; N agrave ; B 76 -15 569 672 ;
|
||||
C -1 ; WX 600 ; N Tcommaaccent ; B 108 -250 665 562 ;
|
||||
C -1 ; WX 600 ; N Cacute ; B 93 -18 655 805 ;
|
||||
C -1 ; WX 600 ; N atilde ; B 76 -15 629 606 ;
|
||||
C -1 ; WX 600 ; N Edotaccent ; B 53 0 660 753 ;
|
||||
C -1 ; WX 600 ; N scaron ; B 78 -15 614 669 ;
|
||||
C -1 ; WX 600 ; N scedilla ; B 78 -151 584 441 ;
|
||||
C -1 ; WX 600 ; N iacute ; B 95 0 612 672 ;
|
||||
C -1 ; WX 600 ; N lozenge ; B 94 0 519 706 ;
|
||||
C -1 ; WX 600 ; N Rcaron ; B 38 0 642 802 ;
|
||||
C -1 ; WX 600 ; N Gcommaaccent ; B 83 -250 645 580 ;
|
||||
C -1 ; WX 600 ; N ucircumflex ; B 101 -15 572 654 ;
|
||||
C -1 ; WX 600 ; N acircumflex ; B 76 -15 581 654 ;
|
||||
C -1 ; WX 600 ; N Amacron ; B 3 0 607 698 ;
|
||||
C -1 ; WX 600 ; N rcaron ; B 60 0 636 669 ;
|
||||
C -1 ; WX 600 ; N ccedilla ; B 106 -151 614 441 ;
|
||||
C -1 ; WX 600 ; N Zdotaccent ; B 86 0 610 753 ;
|
||||
C -1 ; WX 600 ; N Thorn ; B 79 0 606 562 ;
|
||||
C -1 ; WX 600 ; N Omacron ; B 94 -18 628 698 ;
|
||||
C -1 ; WX 600 ; N Racute ; B 38 0 670 805 ;
|
||||
C -1 ; WX 600 ; N Sacute ; B 76 -20 650 805 ;
|
||||
C -1 ; WX 600 ; N dcaron ; B 85 -15 849 629 ;
|
||||
C -1 ; WX 600 ; N Umacron ; B 125 -18 702 698 ;
|
||||
C -1 ; WX 600 ; N uring ; B 101 -15 572 627 ;
|
||||
C -1 ; WX 600 ; N threesuperior ; B 213 240 501 622 ;
|
||||
C -1 ; WX 600 ; N Ograve ; B 94 -18 625 805 ;
|
||||
C -1 ; WX 600 ; N Agrave ; B 3 0 607 805 ;
|
||||
C -1 ; WX 600 ; N Abreve ; B 3 0 607 732 ;
|
||||
C -1 ; WX 600 ; N multiply ; B 103 43 607 470 ;
|
||||
C -1 ; WX 600 ; N uacute ; B 101 -15 602 672 ;
|
||||
C -1 ; WX 600 ; N Tcaron ; B 108 0 665 802 ;
|
||||
C -1 ; WX 600 ; N partialdiff ; B 45 -38 546 710 ;
|
||||
C -1 ; WX 600 ; N ydieresis ; B -4 -157 683 620 ;
|
||||
C -1 ; WX 600 ; N Nacute ; B 7 -13 712 805 ;
|
||||
C -1 ; WX 600 ; N icircumflex ; B 95 0 551 654 ;
|
||||
C -1 ; WX 600 ; N Ecircumflex ; B 53 0 660 787 ;
|
||||
C -1 ; WX 600 ; N adieresis ; B 76 -15 575 620 ;
|
||||
C -1 ; WX 600 ; N edieresis ; B 106 -15 598 620 ;
|
||||
C -1 ; WX 600 ; N cacute ; B 106 -15 612 672 ;
|
||||
C -1 ; WX 600 ; N nacute ; B 26 0 602 672 ;
|
||||
C -1 ; WX 600 ; N umacron ; B 101 -15 600 565 ;
|
||||
C -1 ; WX 600 ; N Ncaron ; B 7 -13 712 802 ;
|
||||
C -1 ; WX 600 ; N Iacute ; B 96 0 640 805 ;
|
||||
C -1 ; WX 600 ; N plusminus ; B 96 44 594 558 ;
|
||||
C -1 ; WX 600 ; N brokenbar ; B 238 -175 469 675 ;
|
||||
C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
|
||||
C -1 ; WX 600 ; N Gbreve ; B 83 -18 645 732 ;
|
||||
C -1 ; WX 600 ; N Idotaccent ; B 96 0 623 753 ;
|
||||
C -1 ; WX 600 ; N summation ; B 15 -10 670 706 ;
|
||||
C -1 ; WX 600 ; N Egrave ; B 53 0 660 805 ;
|
||||
C -1 ; WX 600 ; N racute ; B 60 0 636 672 ;
|
||||
C -1 ; WX 600 ; N omacron ; B 102 -15 600 565 ;
|
||||
C -1 ; WX 600 ; N Zacute ; B 86 0 670 805 ;
|
||||
C -1 ; WX 600 ; N Zcaron ; B 86 0 642 802 ;
|
||||
C -1 ; WX 600 ; N greaterequal ; B 98 0 594 710 ;
|
||||
C -1 ; WX 600 ; N Eth ; B 43 0 645 562 ;
|
||||
C -1 ; WX 600 ; N Ccedilla ; B 93 -151 658 580 ;
|
||||
C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 515 629 ;
|
||||
C -1 ; WX 600 ; N tcaron ; B 167 -15 587 717 ;
|
||||
C -1 ; WX 600 ; N eogonek ; B 106 -172 598 441 ;
|
||||
C -1 ; WX 600 ; N Uogonek ; B 124 -172 702 562 ;
|
||||
C -1 ; WX 600 ; N Aacute ; B 3 0 660 805 ;
|
||||
C -1 ; WX 600 ; N Adieresis ; B 3 0 607 753 ;
|
||||
C -1 ; WX 600 ; N egrave ; B 106 -15 598 672 ;
|
||||
C -1 ; WX 600 ; N zacute ; B 99 0 612 672 ;
|
||||
C -1 ; WX 600 ; N iogonek ; B 95 -172 515 657 ;
|
||||
C -1 ; WX 600 ; N Oacute ; B 94 -18 640 805 ;
|
||||
C -1 ; WX 600 ; N oacute ; B 102 -15 612 672 ;
|
||||
C -1 ; WX 600 ; N amacron ; B 76 -15 600 565 ;
|
||||
C -1 ; WX 600 ; N sacute ; B 78 -15 612 672 ;
|
||||
C -1 ; WX 600 ; N idieresis ; B 95 0 545 620 ;
|
||||
C -1 ; WX 600 ; N Ocircumflex ; B 94 -18 625 787 ;
|
||||
C -1 ; WX 600 ; N Ugrave ; B 125 -18 702 805 ;
|
||||
C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ;
|
||||
C -1 ; WX 600 ; N thorn ; B -24 -157 605 629 ;
|
||||
C -1 ; WX 600 ; N twosuperior ; B 230 249 535 622 ;
|
||||
C -1 ; WX 600 ; N Odieresis ; B 94 -18 625 753 ;
|
||||
C -1 ; WX 600 ; N mu ; B 72 -157 572 426 ;
|
||||
C -1 ; WX 600 ; N igrave ; B 95 0 515 672 ;
|
||||
C -1 ; WX 600 ; N ohungarumlaut ; B 102 -15 723 672 ;
|
||||
C -1 ; WX 600 ; N Eogonek ; B 53 -172 660 562 ;
|
||||
C -1 ; WX 600 ; N dcroat ; B 85 -15 704 629 ;
|
||||
C -1 ; WX 600 ; N threequarters ; B 73 -56 659 666 ;
|
||||
C -1 ; WX 600 ; N Scedilla ; B 76 -151 650 580 ;
|
||||
C -1 ; WX 600 ; N lcaron ; B 95 0 667 629 ;
|
||||
C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 671 562 ;
|
||||
C -1 ; WX 600 ; N Lacute ; B 47 0 607 805 ;
|
||||
C -1 ; WX 600 ; N trademark ; B 75 263 742 562 ;
|
||||
C -1 ; WX 600 ; N edotaccent ; B 106 -15 598 620 ;
|
||||
C -1 ; WX 600 ; N Igrave ; B 96 0 623 805 ;
|
||||
C -1 ; WX 600 ; N Imacron ; B 96 0 628 698 ;
|
||||
C -1 ; WX 600 ; N Lcaron ; B 47 0 632 562 ;
|
||||
C -1 ; WX 600 ; N onehalf ; B 65 -57 669 665 ;
|
||||
C -1 ; WX 600 ; N lessequal ; B 98 0 645 710 ;
|
||||
C -1 ; WX 600 ; N ocircumflex ; B 102 -15 588 654 ;
|
||||
C -1 ; WX 600 ; N ntilde ; B 26 0 629 606 ;
|
||||
C -1 ; WX 600 ; N Uhungarumlaut ; B 125 -18 761 805 ;
|
||||
C -1 ; WX 600 ; N Eacute ; B 53 0 670 805 ;
|
||||
C -1 ; WX 600 ; N emacron ; B 106 -15 600 565 ;
|
||||
C -1 ; WX 600 ; N gbreve ; B 61 -157 657 609 ;
|
||||
C -1 ; WX 600 ; N onequarter ; B 65 -57 674 665 ;
|
||||
C -1 ; WX 600 ; N Scaron ; B 76 -20 672 802 ;
|
||||
C -1 ; WX 600 ; N Scommaaccent ; B 76 -250 650 580 ;
|
||||
C -1 ; WX 600 ; N Ohungarumlaut ; B 94 -18 751 805 ;
|
||||
C -1 ; WX 600 ; N degree ; B 214 269 576 622 ;
|
||||
C -1 ; WX 600 ; N ograve ; B 102 -15 588 672 ;
|
||||
C -1 ; WX 600 ; N Ccaron ; B 93 -18 672 802 ;
|
||||
C -1 ; WX 600 ; N ugrave ; B 101 -15 572 672 ;
|
||||
C -1 ; WX 600 ; N radical ; B 85 -15 765 792 ;
|
||||
C -1 ; WX 600 ; N Dcaron ; B 43 0 645 802 ;
|
||||
C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 636 441 ;
|
||||
C -1 ; WX 600 ; N Ntilde ; B 7 -13 712 729 ;
|
||||
C -1 ; WX 600 ; N otilde ; B 102 -15 629 606 ;
|
||||
C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 598 562 ;
|
||||
C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 607 562 ;
|
||||
C -1 ; WX 600 ; N Atilde ; B 3 0 655 729 ;
|
||||
C -1 ; WX 600 ; N Aogonek ; B 3 -172 607 562 ;
|
||||
C -1 ; WX 600 ; N Aring ; B 3 0 607 750 ;
|
||||
C -1 ; WX 600 ; N Otilde ; B 94 -18 655 729 ;
|
||||
C -1 ; WX 600 ; N zdotaccent ; B 99 0 593 620 ;
|
||||
C -1 ; WX 600 ; N Ecaron ; B 53 0 660 802 ;
|
||||
C -1 ; WX 600 ; N Iogonek ; B 96 -172 623 562 ;
|
||||
C -1 ; WX 600 ; N kcommaaccent ; B 58 -250 633 629 ;
|
||||
C -1 ; WX 600 ; N minus ; B 129 232 580 283 ;
|
||||
C -1 ; WX 600 ; N Icircumflex ; B 96 0 623 787 ;
|
||||
C -1 ; WX 600 ; N ncaron ; B 26 0 614 669 ;
|
||||
C -1 ; WX 600 ; N tcommaaccent ; B 165 -250 561 561 ;
|
||||
C -1 ; WX 600 ; N logicalnot ; B 155 108 591 369 ;
|
||||
C -1 ; WX 600 ; N odieresis ; B 102 -15 588 620 ;
|
||||
C -1 ; WX 600 ; N udieresis ; B 101 -15 575 620 ;
|
||||
C -1 ; WX 600 ; N notequal ; B 43 -16 621 529 ;
|
||||
C -1 ; WX 600 ; N gcommaaccent ; B 61 -157 657 708 ;
|
||||
C -1 ; WX 600 ; N eth ; B 102 -15 639 629 ;
|
||||
C -1 ; WX 600 ; N zcaron ; B 99 0 624 669 ;
|
||||
C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 585 441 ;
|
||||
C -1 ; WX 600 ; N onesuperior ; B 231 249 491 622 ;
|
||||
C -1 ; WX 600 ; N imacron ; B 95 0 543 565 ;
|
||||
C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
|
||||
EndCharMetrics
|
||||
EndFontMetrics
|
@ -0,0 +1,342 @@
|
||||
StartFontMetrics 4.1
|
||||
Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
|
||||
Comment Creation Date: Thu May 1 17:27:09 1997
|
||||
Comment UniqueID 43050
|
||||
Comment VMusage 39754 50779
|
||||
FontName Courier
|
||||
FullName Courier
|
||||
FamilyName Courier
|
||||
Weight Medium
|
||||
ItalicAngle 0
|
||||
IsFixedPitch true
|
||||
CharacterSet ExtendedRoman
|
||||
FontBBox -23 -250 715 805
|
||||
UnderlinePosition -100
|
||||
UnderlineThickness 50
|
||||
Version 003.000
|
||||
Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
|
||||
EncodingScheme AdobeStandardEncoding
|
||||
CapHeight 562
|
||||
XHeight 426
|
||||
Ascender 629
|
||||
Descender -157
|
||||
StdHW 51
|
||||
StdVW 51
|
||||
StartCharMetrics 315
|
||||
C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
|
||||
C 33 ; WX 600 ; N exclam ; B 236 -15 364 572 ;
|
||||
C 34 ; WX 600 ; N quotedbl ; B 187 328 413 562 ;
|
||||
C 35 ; WX 600 ; N numbersign ; B 93 -32 507 639 ;
|
||||
C 36 ; WX 600 ; N dollar ; B 105 -126 496 662 ;
|
||||
C 37 ; WX 600 ; N percent ; B 81 -15 518 622 ;
|
||||
C 38 ; WX 600 ; N ampersand ; B 63 -15 538 543 ;
|
||||
C 39 ; WX 600 ; N quoteright ; B 213 328 376 562 ;
|
||||
C 40 ; WX 600 ; N parenleft ; B 269 -108 440 622 ;
|
||||
C 41 ; WX 600 ; N parenright ; B 160 -108 331 622 ;
|
||||
C 42 ; WX 600 ; N asterisk ; B 116 257 484 607 ;
|
||||
C 43 ; WX 600 ; N plus ; B 80 44 520 470 ;
|
||||
C 44 ; WX 600 ; N comma ; B 181 -112 344 122 ;
|
||||
C 45 ; WX 600 ; N hyphen ; B 103 231 497 285 ;
|
||||
C 46 ; WX 600 ; N period ; B 229 -15 371 109 ;
|
||||
C 47 ; WX 600 ; N slash ; B 125 -80 475 629 ;
|
||||
C 48 ; WX 600 ; N zero ; B 106 -15 494 622 ;
|
||||
C 49 ; WX 600 ; N one ; B 96 0 505 622 ;
|
||||
C 50 ; WX 600 ; N two ; B 70 0 471 622 ;
|
||||
C 51 ; WX 600 ; N three ; B 75 -15 466 622 ;
|
||||
C 52 ; WX 600 ; N four ; B 78 0 500 622 ;
|
||||
C 53 ; WX 600 ; N five ; B 92 -15 497 607 ;
|
||||
C 54 ; WX 600 ; N six ; B 111 -15 497 622 ;
|
||||
C 55 ; WX 600 ; N seven ; B 82 0 483 607 ;
|
||||
C 56 ; WX 600 ; N eight ; B 102 -15 498 622 ;
|
||||
C 57 ; WX 600 ; N nine ; B 96 -15 489 622 ;
|
||||
C 58 ; WX 600 ; N colon ; B 229 -15 371 385 ;
|
||||
C 59 ; WX 600 ; N semicolon ; B 181 -112 371 385 ;
|
||||
C 60 ; WX 600 ; N less ; B 41 42 519 472 ;
|
||||
C 61 ; WX 600 ; N equal ; B 80 138 520 376 ;
|
||||
C 62 ; WX 600 ; N greater ; B 66 42 544 472 ;
|
||||
C 63 ; WX 600 ; N question ; B 129 -15 492 572 ;
|
||||
C 64 ; WX 600 ; N at ; B 77 -15 533 622 ;
|
||||
C 65 ; WX 600 ; N A ; B 3 0 597 562 ;
|
||||
C 66 ; WX 600 ; N B ; B 43 0 559 562 ;
|
||||
C 67 ; WX 600 ; N C ; B 41 -18 540 580 ;
|
||||
C 68 ; WX 600 ; N D ; B 43 0 574 562 ;
|
||||
C 69 ; WX 600 ; N E ; B 53 0 550 562 ;
|
||||
C 70 ; WX 600 ; N F ; B 53 0 545 562 ;
|
||||
C 71 ; WX 600 ; N G ; B 31 -18 575 580 ;
|
||||
C 72 ; WX 600 ; N H ; B 32 0 568 562 ;
|
||||
C 73 ; WX 600 ; N I ; B 96 0 504 562 ;
|
||||
C 74 ; WX 600 ; N J ; B 34 -18 566 562 ;
|
||||
C 75 ; WX 600 ; N K ; B 38 0 582 562 ;
|
||||
C 76 ; WX 600 ; N L ; B 47 0 554 562 ;
|
||||
C 77 ; WX 600 ; N M ; B 4 0 596 562 ;
|
||||
C 78 ; WX 600 ; N N ; B 7 -13 593 562 ;
|
||||
C 79 ; WX 600 ; N O ; B 43 -18 557 580 ;
|
||||
C 80 ; WX 600 ; N P ; B 79 0 558 562 ;
|
||||
C 81 ; WX 600 ; N Q ; B 43 -138 557 580 ;
|
||||
C 82 ; WX 600 ; N R ; B 38 0 588 562 ;
|
||||
C 83 ; WX 600 ; N S ; B 72 -20 529 580 ;
|
||||
C 84 ; WX 600 ; N T ; B 38 0 563 562 ;
|
||||
C 85 ; WX 600 ; N U ; B 17 -18 583 562 ;
|
||||
C 86 ; WX 600 ; N V ; B -4 -13 604 562 ;
|
||||
C 87 ; WX 600 ; N W ; B -3 -13 603 562 ;
|
||||
C 88 ; WX 600 ; N X ; B 23 0 577 562 ;
|
||||
C 89 ; WX 600 ; N Y ; B 24 0 576 562 ;
|
||||
C 90 ; WX 600 ; N Z ; B 86 0 514 562 ;
|
||||
C 91 ; WX 600 ; N bracketleft ; B 269 -108 442 622 ;
|
||||
C 92 ; WX 600 ; N backslash ; B 118 -80 482 629 ;
|
||||
C 93 ; WX 600 ; N bracketright ; B 158 -108 331 622 ;
|
||||
C 94 ; WX 600 ; N asciicircum ; B 94 354 506 622 ;
|
||||
C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ;
|
||||
C 96 ; WX 600 ; N quoteleft ; B 224 328 387 562 ;
|
||||
C 97 ; WX 600 ; N a ; B 53 -15 559 441 ;
|
||||
C 98 ; WX 600 ; N b ; B 14 -15 575 629 ;
|
||||
C 99 ; WX 600 ; N c ; B 66 -15 529 441 ;
|
||||
C 100 ; WX 600 ; N d ; B 45 -15 591 629 ;
|
||||
C 101 ; WX 600 ; N e ; B 66 -15 548 441 ;
|
||||
C 102 ; WX 600 ; N f ; B 114 0 531 629 ; L i fi ; L l fl ;
|
||||
C 103 ; WX 600 ; N g ; B 45 -157 566 441 ;
|
||||
C 104 ; WX 600 ; N h ; B 18 0 582 629 ;
|
||||
C 105 ; WX 600 ; N i ; B 95 0 505 657 ;
|
||||
C 106 ; WX 600 ; N j ; B 82 -157 410 657 ;
|
||||
C 107 ; WX 600 ; N k ; B 43 0 580 629 ;
|
||||
C 108 ; WX 600 ; N l ; B 95 0 505 629 ;
|
||||
C 109 ; WX 600 ; N m ; B -5 0 605 441 ;
|
||||
C 110 ; WX 600 ; N n ; B 26 0 575 441 ;
|
||||
C 111 ; WX 600 ; N o ; B 62 -15 538 441 ;
|
||||
C 112 ; WX 600 ; N p ; B 9 -157 555 441 ;
|
||||
C 113 ; WX 600 ; N q ; B 45 -157 591 441 ;
|
||||
C 114 ; WX 600 ; N r ; B 60 0 559 441 ;
|
||||
C 115 ; WX 600 ; N s ; B 80 -15 513 441 ;
|
||||
C 116 ; WX 600 ; N t ; B 87 -15 530 561 ;
|
||||
C 117 ; WX 600 ; N u ; B 21 -15 562 426 ;
|
||||
C 118 ; WX 600 ; N v ; B 10 -10 590 426 ;
|
||||
C 119 ; WX 600 ; N w ; B -4 -10 604 426 ;
|
||||
C 120 ; WX 600 ; N x ; B 20 0 580 426 ;
|
||||
C 121 ; WX 600 ; N y ; B 7 -157 592 426 ;
|
||||
C 122 ; WX 600 ; N z ; B 99 0 502 426 ;
|
||||
C 123 ; WX 600 ; N braceleft ; B 182 -108 437 622 ;
|
||||
C 124 ; WX 600 ; N bar ; B 275 -250 326 750 ;
|
||||
C 125 ; WX 600 ; N braceright ; B 163 -108 418 622 ;
|
||||
C 126 ; WX 600 ; N asciitilde ; B 63 197 540 320 ;
|
||||
C 161 ; WX 600 ; N exclamdown ; B 236 -157 364 430 ;
|
||||
C 162 ; WX 600 ; N cent ; B 96 -49 500 614 ;
|
||||
C 163 ; WX 600 ; N sterling ; B 84 -21 521 611 ;
|
||||
C 164 ; WX 600 ; N fraction ; B 92 -57 509 665 ;
|
||||
C 165 ; WX 600 ; N yen ; B 26 0 574 562 ;
|
||||
C 166 ; WX 600 ; N florin ; B 4 -143 539 622 ;
|
||||
C 167 ; WX 600 ; N section ; B 113 -78 488 580 ;
|
||||
C 168 ; WX 600 ; N currency ; B 73 58 527 506 ;
|
||||
C 169 ; WX 600 ; N quotesingle ; B 259 328 341 562 ;
|
||||
C 170 ; WX 600 ; N quotedblleft ; B 143 328 471 562 ;
|
||||
C 171 ; WX 600 ; N guillemotleft ; B 37 70 563 446 ;
|
||||
C 172 ; WX 600 ; N guilsinglleft ; B 149 70 451 446 ;
|
||||
C 173 ; WX 600 ; N guilsinglright ; B 149 70 451 446 ;
|
||||
C 174 ; WX 600 ; N fi ; B 3 0 597 629 ;
|
||||
C 175 ; WX 600 ; N fl ; B 3 0 597 629 ;
|
||||
C 177 ; WX 600 ; N endash ; B 75 231 525 285 ;
|
||||
C 178 ; WX 600 ; N dagger ; B 141 -78 459 580 ;
|
||||
C 179 ; WX 600 ; N daggerdbl ; B 141 -78 459 580 ;
|
||||
C 180 ; WX 600 ; N periodcentered ; B 222 189 378 327 ;
|
||||
C 182 ; WX 600 ; N paragraph ; B 50 -78 511 562 ;
|
||||
C 183 ; WX 600 ; N bullet ; B 172 130 428 383 ;
|
||||
C 184 ; WX 600 ; N quotesinglbase ; B 213 -134 376 100 ;
|
||||
C 185 ; WX 600 ; N quotedblbase ; B 143 -134 457 100 ;
|
||||
C 186 ; WX 600 ; N quotedblright ; B 143 328 457 562 ;
|
||||
C 187 ; WX 600 ; N guillemotright ; B 37 70 563 446 ;
|
||||
C 188 ; WX 600 ; N ellipsis ; B 37 -15 563 111 ;
|
||||
C 189 ; WX 600 ; N perthousand ; B 3 -15 600 622 ;
|
||||
C 191 ; WX 600 ; N questiondown ; B 108 -157 471 430 ;
|
||||
C 193 ; WX 600 ; N grave ; B 151 497 378 672 ;
|
||||
C 194 ; WX 600 ; N acute ; B 242 497 469 672 ;
|
||||
C 195 ; WX 600 ; N circumflex ; B 124 477 476 654 ;
|
||||
C 196 ; WX 600 ; N tilde ; B 105 489 503 606 ;
|
||||
C 197 ; WX 600 ; N macron ; B 120 525 480 565 ;
|
||||
C 198 ; WX 600 ; N breve ; B 153 501 447 609 ;
|
||||
C 199 ; WX 600 ; N dotaccent ; B 249 537 352 640 ;
|
||||
C 200 ; WX 600 ; N dieresis ; B 148 537 453 640 ;
|
||||
C 202 ; WX 600 ; N ring ; B 218 463 382 627 ;
|
||||
C 203 ; WX 600 ; N cedilla ; B 224 -151 362 10 ;
|
||||
C 205 ; WX 600 ; N hungarumlaut ; B 133 497 540 672 ;
|
||||
C 206 ; WX 600 ; N ogonek ; B 211 -172 407 4 ;
|
||||
C 207 ; WX 600 ; N caron ; B 124 492 476 669 ;
|
||||
C 208 ; WX 600 ; N emdash ; B 0 231 600 285 ;
|
||||
C 225 ; WX 600 ; N AE ; B 3 0 550 562 ;
|
||||
C 227 ; WX 600 ; N ordfeminine ; B 156 249 442 580 ;
|
||||
C 232 ; WX 600 ; N Lslash ; B 47 0 554 562 ;
|
||||
C 233 ; WX 600 ; N Oslash ; B 43 -80 557 629 ;
|
||||
C 234 ; WX 600 ; N OE ; B 7 0 567 562 ;
|
||||
C 235 ; WX 600 ; N ordmasculine ; B 157 249 443 580 ;
|
||||
C 241 ; WX 600 ; N ae ; B 19 -15 570 441 ;
|
||||
C 245 ; WX 600 ; N dotlessi ; B 95 0 505 426 ;
|
||||
C 248 ; WX 600 ; N lslash ; B 95 0 505 629 ;
|
||||
C 249 ; WX 600 ; N oslash ; B 62 -80 538 506 ;
|
||||
C 250 ; WX 600 ; N oe ; B 19 -15 559 441 ;
|
||||
C 251 ; WX 600 ; N germandbls ; B 48 -15 588 629 ;
|
||||
C -1 ; WX 600 ; N Idieresis ; B 96 0 504 753 ;
|
||||
C -1 ; WX 600 ; N eacute ; B 66 -15 548 672 ;
|
||||
C -1 ; WX 600 ; N abreve ; B 53 -15 559 609 ;
|
||||
C -1 ; WX 600 ; N uhungarumlaut ; B 21 -15 580 672 ;
|
||||
C -1 ; WX 600 ; N ecaron ; B 66 -15 548 669 ;
|
||||
C -1 ; WX 600 ; N Ydieresis ; B 24 0 576 753 ;
|
||||
C -1 ; WX 600 ; N divide ; B 87 48 513 467 ;
|
||||
C -1 ; WX 600 ; N Yacute ; B 24 0 576 805 ;
|
||||
C -1 ; WX 600 ; N Acircumflex ; B 3 0 597 787 ;
|
||||
C -1 ; WX 600 ; N aacute ; B 53 -15 559 672 ;
|
||||
C -1 ; WX 600 ; N Ucircumflex ; B 17 -18 583 787 ;
|
||||
C -1 ; WX 600 ; N yacute ; B 7 -157 592 672 ;
|
||||
C -1 ; WX 600 ; N scommaaccent ; B 80 -250 513 441 ;
|
||||
C -1 ; WX 600 ; N ecircumflex ; B 66 -15 548 654 ;
|
||||
C -1 ; WX 600 ; N Uring ; B 17 -18 583 760 ;
|
||||
C -1 ; WX 600 ; N Udieresis ; B 17 -18 583 753 ;
|
||||
C -1 ; WX 600 ; N aogonek ; B 53 -172 587 441 ;
|
||||
C -1 ; WX 600 ; N Uacute ; B 17 -18 583 805 ;
|
||||
C -1 ; WX 600 ; N uogonek ; B 21 -172 590 426 ;
|
||||
C -1 ; WX 600 ; N Edieresis ; B 53 0 550 753 ;
|
||||
C -1 ; WX 600 ; N Dcroat ; B 30 0 574 562 ;
|
||||
C -1 ; WX 600 ; N commaaccent ; B 198 -250 335 -58 ;
|
||||
C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
|
||||
C -1 ; WX 600 ; N Emacron ; B 53 0 550 698 ;
|
||||
C -1 ; WX 600 ; N ccaron ; B 66 -15 529 669 ;
|
||||
C -1 ; WX 600 ; N aring ; B 53 -15 559 627 ;
|
||||
C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 593 562 ;
|
||||
C -1 ; WX 600 ; N lacute ; B 95 0 505 805 ;
|
||||
C -1 ; WX 600 ; N agrave ; B 53 -15 559 672 ;
|
||||
C -1 ; WX 600 ; N Tcommaaccent ; B 38 -250 563 562 ;
|
||||
C -1 ; WX 600 ; N Cacute ; B 41 -18 540 805 ;
|
||||
C -1 ; WX 600 ; N atilde ; B 53 -15 559 606 ;
|
||||
C -1 ; WX 600 ; N Edotaccent ; B 53 0 550 753 ;
|
||||
C -1 ; WX 600 ; N scaron ; B 80 -15 513 669 ;
|
||||
C -1 ; WX 600 ; N scedilla ; B 80 -151 513 441 ;
|
||||
C -1 ; WX 600 ; N iacute ; B 95 0 505 672 ;
|
||||
C -1 ; WX 600 ; N lozenge ; B 18 0 443 706 ;
|
||||
C -1 ; WX 600 ; N Rcaron ; B 38 0 588 802 ;
|
||||
C -1 ; WX 600 ; N Gcommaaccent ; B 31 -250 575 580 ;
|
||||
C -1 ; WX 600 ; N ucircumflex ; B 21 -15 562 654 ;
|
||||
C -1 ; WX 600 ; N acircumflex ; B 53 -15 559 654 ;
|
||||
C -1 ; WX 600 ; N Amacron ; B 3 0 597 698 ;
|
||||
C -1 ; WX 600 ; N rcaron ; B 60 0 559 669 ;
|
||||
C -1 ; WX 600 ; N ccedilla ; B 66 -151 529 441 ;
|
||||
C -1 ; WX 600 ; N Zdotaccent ; B 86 0 514 753 ;
|
||||
C -1 ; WX 600 ; N Thorn ; B 79 0 538 562 ;
|
||||
C -1 ; WX 600 ; N Omacron ; B 43 -18 557 698 ;
|
||||
C -1 ; WX 600 ; N Racute ; B 38 0 588 805 ;
|
||||
C -1 ; WX 600 ; N Sacute ; B 72 -20 529 805 ;
|
||||
C -1 ; WX 600 ; N dcaron ; B 45 -15 715 629 ;
|
||||
C -1 ; WX 600 ; N Umacron ; B 17 -18 583 698 ;
|
||||
C -1 ; WX 600 ; N uring ; B 21 -15 562 627 ;
|
||||
C -1 ; WX 600 ; N threesuperior ; B 155 240 406 622 ;
|
||||
C -1 ; WX 600 ; N Ograve ; B 43 -18 557 805 ;
|
||||
C -1 ; WX 600 ; N Agrave ; B 3 0 597 805 ;
|
||||
C -1 ; WX 600 ; N Abreve ; B 3 0 597 732 ;
|
||||
C -1 ; WX 600 ; N multiply ; B 87 43 515 470 ;
|
||||
C -1 ; WX 600 ; N uacute ; B 21 -15 562 672 ;
|
||||
C -1 ; WX 600 ; N Tcaron ; B 38 0 563 802 ;
|
||||
C -1 ; WX 600 ; N partialdiff ; B 17 -38 459 710 ;
|
||||
C -1 ; WX 600 ; N ydieresis ; B 7 -157 592 620 ;
|
||||
C -1 ; WX 600 ; N Nacute ; B 7 -13 593 805 ;
|
||||
C -1 ; WX 600 ; N icircumflex ; B 94 0 505 654 ;
|
||||
C -1 ; WX 600 ; N Ecircumflex ; B 53 0 550 787 ;
|
||||
C -1 ; WX 600 ; N adieresis ; B 53 -15 559 620 ;
|
||||
C -1 ; WX 600 ; N edieresis ; B 66 -15 548 620 ;
|
||||
C -1 ; WX 600 ; N cacute ; B 66 -15 529 672 ;
|
||||
C -1 ; WX 600 ; N nacute ; B 26 0 575 672 ;
|
||||
C -1 ; WX 600 ; N umacron ; B 21 -15 562 565 ;
|
||||
C -1 ; WX 600 ; N Ncaron ; B 7 -13 593 802 ;
|
||||
C -1 ; WX 600 ; N Iacute ; B 96 0 504 805 ;
|
||||
C -1 ; WX 600 ; N plusminus ; B 87 44 513 558 ;
|
||||
C -1 ; WX 600 ; N brokenbar ; B 275 -175 326 675 ;
|
||||
C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
|
||||
C -1 ; WX 600 ; N Gbreve ; B 31 -18 575 732 ;
|
||||
C -1 ; WX 600 ; N Idotaccent ; B 96 0 504 753 ;
|
||||
C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
|
||||
C -1 ; WX 600 ; N Egrave ; B 53 0 550 805 ;
|
||||
C -1 ; WX 600 ; N racute ; B 60 0 559 672 ;
|
||||
C -1 ; WX 600 ; N omacron ; B 62 -15 538 565 ;
|
||||
C -1 ; WX 600 ; N Zacute ; B 86 0 514 805 ;
|
||||
C -1 ; WX 600 ; N Zcaron ; B 86 0 514 802 ;
|
||||
C -1 ; WX 600 ; N greaterequal ; B 98 0 502 710 ;
|
||||
C -1 ; WX 600 ; N Eth ; B 30 0 574 562 ;
|
||||
C -1 ; WX 600 ; N Ccedilla ; B 41 -151 540 580 ;
|
||||
C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 505 629 ;
|
||||
C -1 ; WX 600 ; N tcaron ; B 87 -15 530 717 ;
|
||||
C -1 ; WX 600 ; N eogonek ; B 66 -172 548 441 ;
|
||||
C -1 ; WX 600 ; N Uogonek ; B 17 -172 583 562 ;
|
||||
C -1 ; WX 600 ; N Aacute ; B 3 0 597 805 ;
|
||||
C -1 ; WX 600 ; N Adieresis ; B 3 0 597 753 ;
|
||||
C -1 ; WX 600 ; N egrave ; B 66 -15 548 672 ;
|
||||
C -1 ; WX 600 ; N zacute ; B 99 0 502 672 ;
|
||||
C -1 ; WX 600 ; N iogonek ; B 95 -172 505 657 ;
|
||||
C -1 ; WX 600 ; N Oacute ; B 43 -18 557 805 ;
|
||||
C -1 ; WX 600 ; N oacute ; B 62 -15 538 672 ;
|
||||
C -1 ; WX 600 ; N amacron ; B 53 -15 559 565 ;
|
||||
C -1 ; WX 600 ; N sacute ; B 80 -15 513 672 ;
|
||||
C -1 ; WX 600 ; N idieresis ; B 95 0 505 620 ;
|
||||
C -1 ; WX 600 ; N Ocircumflex ; B 43 -18 557 787 ;
|
||||
C -1 ; WX 600 ; N Ugrave ; B 17 -18 583 805 ;
|
||||
C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ;
|
||||
C -1 ; WX 600 ; N thorn ; B -6 -157 555 629 ;
|
||||
C -1 ; WX 600 ; N twosuperior ; B 177 249 424 622 ;
|
||||
C -1 ; WX 600 ; N Odieresis ; B 43 -18 557 753 ;
|
||||
C -1 ; WX 600 ; N mu ; B 21 -157 562 426 ;
|
||||
C -1 ; WX 600 ; N igrave ; B 95 0 505 672 ;
|
||||
C -1 ; WX 600 ; N ohungarumlaut ; B 62 -15 580 672 ;
|
||||
C -1 ; WX 600 ; N Eogonek ; B 53 -172 561 562 ;
|
||||
C -1 ; WX 600 ; N dcroat ; B 45 -15 591 629 ;
|
||||
C -1 ; WX 600 ; N threequarters ; B 8 -56 593 666 ;
|
||||
C -1 ; WX 600 ; N Scedilla ; B 72 -151 529 580 ;
|
||||
C -1 ; WX 600 ; N lcaron ; B 95 0 533 629 ;
|
||||
C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 582 562 ;
|
||||
C -1 ; WX 600 ; N Lacute ; B 47 0 554 805 ;
|
||||
C -1 ; WX 600 ; N trademark ; B -23 263 623 562 ;
|
||||
C -1 ; WX 600 ; N edotaccent ; B 66 -15 548 620 ;
|
||||
C -1 ; WX 600 ; N Igrave ; B 96 0 504 805 ;
|
||||
C -1 ; WX 600 ; N Imacron ; B 96 0 504 698 ;
|
||||
C -1 ; WX 600 ; N Lcaron ; B 47 0 554 562 ;
|
||||
C -1 ; WX 600 ; N onehalf ; B 0 -57 611 665 ;
|
||||
C -1 ; WX 600 ; N lessequal ; B 98 0 502 710 ;
|
||||
C -1 ; WX 600 ; N ocircumflex ; B 62 -15 538 654 ;
|
||||
C -1 ; WX 600 ; N ntilde ; B 26 0 575 606 ;
|
||||
C -1 ; WX 600 ; N Uhungarumlaut ; B 17 -18 590 805 ;
|
||||
C -1 ; WX 600 ; N Eacute ; B 53 0 550 805 ;
|
||||
C -1 ; WX 600 ; N emacron ; B 66 -15 548 565 ;
|
||||
C -1 ; WX 600 ; N gbreve ; B 45 -157 566 609 ;
|
||||
C -1 ; WX 600 ; N onequarter ; B 0 -57 600 665 ;
|
||||
C -1 ; WX 600 ; N Scaron ; B 72 -20 529 802 ;
|
||||
C -1 ; WX 600 ; N Scommaaccent ; B 72 -250 529 580 ;
|
||||
C -1 ; WX 600 ; N Ohungarumlaut ; B 43 -18 580 805 ;
|
||||
C -1 ; WX 600 ; N degree ; B 123 269 477 622 ;
|
||||
C -1 ; WX 600 ; N ograve ; B 62 -15 538 672 ;
|
||||
C -1 ; WX 600 ; N Ccaron ; B 41 -18 540 802 ;
|
||||
C -1 ; WX 600 ; N ugrave ; B 21 -15 562 672 ;
|
||||
C -1 ; WX 600 ; N radical ; B 3 -15 597 792 ;
|
||||
C -1 ; WX 600 ; N Dcaron ; B 43 0 574 802 ;
|
||||
C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 559 441 ;
|
||||
C -1 ; WX 600 ; N Ntilde ; B 7 -13 593 729 ;
|
||||
C -1 ; WX 600 ; N otilde ; B 62 -15 538 606 ;
|
||||
C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 588 562 ;
|
||||
C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 554 562 ;
|
||||
C -1 ; WX 600 ; N Atilde ; B 3 0 597 729 ;
|
||||
C -1 ; WX 600 ; N Aogonek ; B 3 -172 608 562 ;
|
||||
C -1 ; WX 600 ; N Aring ; B 3 0 597 750 ;
|
||||
C -1 ; WX 600 ; N Otilde ; B 43 -18 557 729 ;
|
||||
C -1 ; WX 600 ; N zdotaccent ; B 99 0 502 620 ;
|
||||
C -1 ; WX 600 ; N Ecaron ; B 53 0 550 802 ;
|
||||
C -1 ; WX 600 ; N Iogonek ; B 96 -172 504 562 ;
|
||||
C -1 ; WX 600 ; N kcommaaccent ; B 43 -250 580 629 ;
|
||||
C -1 ; WX 600 ; N minus ; B 80 232 520 283 ;
|
||||
C -1 ; WX 600 ; N Icircumflex ; B 96 0 504 787 ;
|
||||
C -1 ; WX 600 ; N ncaron ; B 26 0 575 669 ;
|
||||
C -1 ; WX 600 ; N tcommaaccent ; B 87 -250 530 561 ;
|
||||
C -1 ; WX 600 ; N logicalnot ; B 87 108 513 369 ;
|
||||
C -1 ; WX 600 ; N odieresis ; B 62 -15 538 620 ;
|
||||
C -1 ; WX 600 ; N udieresis ; B 21 -15 562 620 ;
|
||||
C -1 ; WX 600 ; N notequal ; B 15 -16 540 529 ;
|
||||
C -1 ; WX 600 ; N gcommaaccent ; B 45 -157 566 708 ;
|
||||
C -1 ; WX 600 ; N eth ; B 62 -15 538 629 ;
|
||||
C -1 ; WX 600 ; N zcaron ; B 99 0 502 669 ;
|
||||
C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 575 441 ;
|
||||
C -1 ; WX 600 ; N onesuperior ; B 172 249 428 622 ;
|
||||
C -1 ; WX 600 ; N imacron ; B 95 0 505 565 ;
|
||||
C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
|
||||
EndCharMetrics
|
||||
EndFontMetrics
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
|
||||
<meta name="generator" content="Adobe GoLive 4">
|
||||
<title>Core 14 AFM Files - ReadMe</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="white">
|
||||
<font color="white">or</font>
|
||||
<table border="0" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td width="40"></td>
|
||||
<td width="300">This file and the 14 PostScript(R) AFM files it accompanies may be used, copied, and distributed for any purpose and without charge, with or without modification, provided that all copyright notices are retained; that the AFM files are not distributed without this file; that all modifications to this file or any of the AFM files are prominently noted in the modified file(s); and that this paragraph is not modified. Adobe Systems has no responsibility or obligation to support the use of the AFM files. <font color="white">Col</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -0,0 +1,213 @@
|
||||
StartFontMetrics 4.1
|
||||
Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved.
|
||||
Comment Creation Date: Thu May 1 15:12:25 1997
|
||||
Comment UniqueID 43064
|
||||
Comment VMusage 30820 39997
|
||||
FontName Symbol
|
||||
FullName Symbol
|
||||
FamilyName Symbol
|
||||
Weight Medium
|
||||
ItalicAngle 0
|
||||
IsFixedPitch false
|
||||
CharacterSet Special
|
||||
FontBBox -180 -293 1090 1010
|
||||
UnderlinePosition -100
|
||||
UnderlineThickness 50
|
||||
Version 001.008
|
||||
Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved.
|
||||
EncodingScheme FontSpecific
|
||||
StdHW 92
|
||||
StdVW 85
|
||||
StartCharMetrics 190
|
||||
C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
|
||||
C 33 ; WX 333 ; N exclam ; B 128 -17 240 672 ;
|
||||
C 34 ; WX 713 ; N universal ; B 31 0 681 705 ;
|
||||
C 35 ; WX 500 ; N numbersign ; B 20 -16 481 673 ;
|
||||
C 36 ; WX 549 ; N existential ; B 25 0 478 707 ;
|
||||
C 37 ; WX 833 ; N percent ; B 63 -36 771 655 ;
|
||||
C 38 ; WX 778 ; N ampersand ; B 41 -18 750 661 ;
|
||||
C 39 ; WX 439 ; N suchthat ; B 48 -17 414 500 ;
|
||||
C 40 ; WX 333 ; N parenleft ; B 53 -191 300 673 ;
|
||||
C 41 ; WX 333 ; N parenright ; B 30 -191 277 673 ;
|
||||
C 42 ; WX 500 ; N asteriskmath ; B 65 134 427 551 ;
|
||||
C 43 ; WX 549 ; N plus ; B 10 0 539 533 ;
|
||||
C 44 ; WX 250 ; N comma ; B 56 -152 194 104 ;
|
||||
C 45 ; WX 549 ; N minus ; B 11 233 535 288 ;
|
||||
C 46 ; WX 250 ; N period ; B 69 -17 181 95 ;
|
||||
C 47 ; WX 278 ; N slash ; B 0 -18 254 646 ;
|
||||
C 48 ; WX 500 ; N zero ; B 24 -14 476 685 ;
|
||||
C 49 ; WX 500 ; N one ; B 117 0 390 673 ;
|
||||
C 50 ; WX 500 ; N two ; B 25 0 475 685 ;
|
||||
C 51 ; WX 500 ; N three ; B 43 -14 435 685 ;
|
||||
C 52 ; WX 500 ; N four ; B 15 0 469 685 ;
|
||||
C 53 ; WX 500 ; N five ; B 32 -14 445 690 ;
|
||||
C 54 ; WX 500 ; N six ; B 34 -14 468 685 ;
|
||||
C 55 ; WX 500 ; N seven ; B 24 -16 448 673 ;
|
||||
C 56 ; WX 500 ; N eight ; B 56 -14 445 685 ;
|
||||
C 57 ; WX 500 ; N nine ; B 30 -18 459 685 ;
|
||||
C 58 ; WX 278 ; N colon ; B 81 -17 193 460 ;
|
||||
C 59 ; WX 278 ; N semicolon ; B 83 -152 221 460 ;
|
||||
C 60 ; WX 549 ; N less ; B 26 0 523 522 ;
|
||||
C 61 ; WX 549 ; N equal ; B 11 141 537 390 ;
|
||||
C 62 ; WX 549 ; N greater ; B 26 0 523 522 ;
|
||||
C 63 ; WX 444 ; N question ; B 70 -17 412 686 ;
|
||||
C 64 ; WX 549 ; N congruent ; B 11 0 537 475 ;
|
||||
C 65 ; WX 722 ; N Alpha ; B 4 0 684 673 ;
|
||||
C 66 ; WX 667 ; N Beta ; B 29 0 592 673 ;
|
||||
C 67 ; WX 722 ; N Chi ; B -9 0 704 673 ;
|
||||
C 68 ; WX 612 ; N Delta ; B 6 0 608 688 ;
|
||||
C 69 ; WX 611 ; N Epsilon ; B 32 0 617 673 ;
|
||||
C 70 ; WX 763 ; N Phi ; B 26 0 741 673 ;
|
||||
C 71 ; WX 603 ; N Gamma ; B 24 0 609 673 ;
|
||||
C 72 ; WX 722 ; N Eta ; B 39 0 729 673 ;
|
||||
C 73 ; WX 333 ; N Iota ; B 32 0 316 673 ;
|
||||
C 74 ; WX 631 ; N theta1 ; B 18 -18 623 689 ;
|
||||
C 75 ; WX 722 ; N Kappa ; B 35 0 722 673 ;
|
||||
C 76 ; WX 686 ; N Lambda ; B 6 0 680 688 ;
|
||||
C 77 ; WX 889 ; N Mu ; B 28 0 887 673 ;
|
||||
C 78 ; WX 722 ; N Nu ; B 29 -8 720 673 ;
|
||||
C 79 ; WX 722 ; N Omicron ; B 41 -17 715 685 ;
|
||||
C 80 ; WX 768 ; N Pi ; B 25 0 745 673 ;
|
||||
C 81 ; WX 741 ; N Theta ; B 41 -17 715 685 ;
|
||||
C 82 ; WX 556 ; N Rho ; B 28 0 563 673 ;
|
||||
C 83 ; WX 592 ; N Sigma ; B 5 0 589 673 ;
|
||||
C 84 ; WX 611 ; N Tau ; B 33 0 607 673 ;
|
||||
C 85 ; WX 690 ; N Upsilon ; B -8 0 694 673 ;
|
||||
C 86 ; WX 439 ; N sigma1 ; B 40 -233 436 500 ;
|
||||
C 87 ; WX 768 ; N Omega ; B 34 0 736 688 ;
|
||||
C 88 ; WX 645 ; N Xi ; B 40 0 599 673 ;
|
||||
C 89 ; WX 795 ; N Psi ; B 15 0 781 684 ;
|
||||
C 90 ; WX 611 ; N Zeta ; B 44 0 636 673 ;
|
||||
C 91 ; WX 333 ; N bracketleft ; B 86 -155 299 674 ;
|
||||
C 92 ; WX 863 ; N therefore ; B 163 0 701 487 ;
|
||||
C 93 ; WX 333 ; N bracketright ; B 33 -155 246 674 ;
|
||||
C 94 ; WX 658 ; N perpendicular ; B 15 0 652 674 ;
|
||||
C 95 ; WX 500 ; N underscore ; B -2 -125 502 -75 ;
|
||||
C 96 ; WX 500 ; N radicalex ; B 480 881 1090 917 ;
|
||||
C 97 ; WX 631 ; N alpha ; B 41 -18 622 500 ;
|
||||
C 98 ; WX 549 ; N beta ; B 61 -223 515 741 ;
|
||||
C 99 ; WX 549 ; N chi ; B 12 -231 522 499 ;
|
||||
C 100 ; WX 494 ; N delta ; B 40 -19 481 740 ;
|
||||
C 101 ; WX 439 ; N epsilon ; B 22 -19 427 502 ;
|
||||
C 102 ; WX 521 ; N phi ; B 28 -224 492 673 ;
|
||||
C 103 ; WX 411 ; N gamma ; B 5 -225 484 499 ;
|
||||
C 104 ; WX 603 ; N eta ; B 0 -202 527 514 ;
|
||||
C 105 ; WX 329 ; N iota ; B 0 -17 301 503 ;
|
||||
C 106 ; WX 603 ; N phi1 ; B 36 -224 587 499 ;
|
||||
C 107 ; WX 549 ; N kappa ; B 33 0 558 501 ;
|
||||
C 108 ; WX 549 ; N lambda ; B 24 -17 548 739 ;
|
||||
C 109 ; WX 576 ; N mu ; B 33 -223 567 500 ;
|
||||
C 110 ; WX 521 ; N nu ; B -9 -16 475 507 ;
|
||||
C 111 ; WX 549 ; N omicron ; B 35 -19 501 499 ;
|
||||
C 112 ; WX 549 ; N pi ; B 10 -19 530 487 ;
|
||||
C 113 ; WX 521 ; N theta ; B 43 -17 485 690 ;
|
||||
C 114 ; WX 549 ; N rho ; B 50 -230 490 499 ;
|
||||
C 115 ; WX 603 ; N sigma ; B 30 -21 588 500 ;
|
||||
C 116 ; WX 439 ; N tau ; B 10 -19 418 500 ;
|
||||
C 117 ; WX 576 ; N upsilon ; B 7 -18 535 507 ;
|
||||
C 118 ; WX 713 ; N omega1 ; B 12 -18 671 583 ;
|
||||
C 119 ; WX 686 ; N omega ; B 42 -17 684 500 ;
|
||||
C 120 ; WX 493 ; N xi ; B 27 -224 469 766 ;
|
||||
C 121 ; WX 686 ; N psi ; B 12 -228 701 500 ;
|
||||
C 122 ; WX 494 ; N zeta ; B 60 -225 467 756 ;
|
||||
C 123 ; WX 480 ; N braceleft ; B 58 -183 397 673 ;
|
||||
C 124 ; WX 200 ; N bar ; B 65 -293 135 707 ;
|
||||
C 125 ; WX 480 ; N braceright ; B 79 -183 418 673 ;
|
||||
C 126 ; WX 549 ; N similar ; B 17 203 529 307 ;
|
||||
C 160 ; WX 750 ; N Euro ; B 20 -12 714 685 ;
|
||||
C 161 ; WX 620 ; N Upsilon1 ; B -2 0 610 685 ;
|
||||
C 162 ; WX 247 ; N minute ; B 27 459 228 735 ;
|
||||
C 163 ; WX 549 ; N lessequal ; B 29 0 526 639 ;
|
||||
C 164 ; WX 167 ; N fraction ; B -180 -12 340 677 ;
|
||||
C 165 ; WX 713 ; N infinity ; B 26 124 688 404 ;
|
||||
C 166 ; WX 500 ; N florin ; B 2 -193 494 686 ;
|
||||
C 167 ; WX 753 ; N club ; B 86 -26 660 533 ;
|
||||
C 168 ; WX 753 ; N diamond ; B 142 -36 600 550 ;
|
||||
C 169 ; WX 753 ; N heart ; B 117 -33 631 532 ;
|
||||
C 170 ; WX 753 ; N spade ; B 113 -36 629 548 ;
|
||||
C 171 ; WX 1042 ; N arrowboth ; B 24 -15 1024 511 ;
|
||||
C 172 ; WX 987 ; N arrowleft ; B 32 -15 942 511 ;
|
||||
C 173 ; WX 603 ; N arrowup ; B 45 0 571 910 ;
|
||||
C 174 ; WX 987 ; N arrowright ; B 49 -15 959 511 ;
|
||||
C 175 ; WX 603 ; N arrowdown ; B 45 -22 571 888 ;
|
||||
C 176 ; WX 400 ; N degree ; B 50 385 350 685 ;
|
||||
C 177 ; WX 549 ; N plusminus ; B 10 0 539 645 ;
|
||||
C 178 ; WX 411 ; N second ; B 20 459 413 737 ;
|
||||
C 179 ; WX 549 ; N greaterequal ; B 29 0 526 639 ;
|
||||
C 180 ; WX 549 ; N multiply ; B 17 8 533 524 ;
|
||||
C 181 ; WX 713 ; N proportional ; B 27 123 639 404 ;
|
||||
C 182 ; WX 494 ; N partialdiff ; B 26 -20 462 746 ;
|
||||
C 183 ; WX 460 ; N bullet ; B 50 113 410 473 ;
|
||||
C 184 ; WX 549 ; N divide ; B 10 71 536 456 ;
|
||||
C 185 ; WX 549 ; N notequal ; B 15 -25 540 549 ;
|
||||
C 186 ; WX 549 ; N equivalence ; B 14 82 538 443 ;
|
||||
C 187 ; WX 549 ; N approxequal ; B 14 135 527 394 ;
|
||||
C 188 ; WX 1000 ; N ellipsis ; B 111 -17 889 95 ;
|
||||
C 189 ; WX 603 ; N arrowvertex ; B 280 -120 336 1010 ;
|
||||
C 190 ; WX 1000 ; N arrowhorizex ; B -60 220 1050 276 ;
|
||||
C 191 ; WX 658 ; N carriagereturn ; B 15 -16 602 629 ;
|
||||
C 192 ; WX 823 ; N aleph ; B 175 -18 661 658 ;
|
||||
C 193 ; WX 686 ; N Ifraktur ; B 10 -53 578 740 ;
|
||||
C 194 ; WX 795 ; N Rfraktur ; B 26 -15 759 734 ;
|
||||
C 195 ; WX 987 ; N weierstrass ; B 159 -211 870 573 ;
|
||||
C 196 ; WX 768 ; N circlemultiply ; B 43 -17 733 673 ;
|
||||
C 197 ; WX 768 ; N circleplus ; B 43 -15 733 675 ;
|
||||
C 198 ; WX 823 ; N emptyset ; B 39 -24 781 719 ;
|
||||
C 199 ; WX 768 ; N intersection ; B 40 0 732 509 ;
|
||||
C 200 ; WX 768 ; N union ; B 40 -17 732 492 ;
|
||||
C 201 ; WX 713 ; N propersuperset ; B 20 0 673 470 ;
|
||||
C 202 ; WX 713 ; N reflexsuperset ; B 20 -125 673 470 ;
|
||||
C 203 ; WX 713 ; N notsubset ; B 36 -70 690 540 ;
|
||||
C 204 ; WX 713 ; N propersubset ; B 37 0 690 470 ;
|
||||
C 205 ; WX 713 ; N reflexsubset ; B 37 -125 690 470 ;
|
||||
C 206 ; WX 713 ; N element ; B 45 0 505 468 ;
|
||||
C 207 ; WX 713 ; N notelement ; B 45 -58 505 555 ;
|
||||
C 208 ; WX 768 ; N angle ; B 26 0 738 673 ;
|
||||
C 209 ; WX 713 ; N gradient ; B 36 -19 681 718 ;
|
||||
C 210 ; WX 790 ; N registerserif ; B 50 -17 740 673 ;
|
||||
C 211 ; WX 790 ; N copyrightserif ; B 51 -15 741 675 ;
|
||||
C 212 ; WX 890 ; N trademarkserif ; B 18 293 855 673 ;
|
||||
C 213 ; WX 823 ; N product ; B 25 -101 803 751 ;
|
||||
C 214 ; WX 549 ; N radical ; B 10 -38 515 917 ;
|
||||
C 215 ; WX 250 ; N dotmath ; B 69 210 169 310 ;
|
||||
C 216 ; WX 713 ; N logicalnot ; B 15 0 680 288 ;
|
||||
C 217 ; WX 603 ; N logicaland ; B 23 0 583 454 ;
|
||||
C 218 ; WX 603 ; N logicalor ; B 30 0 578 477 ;
|
||||
C 219 ; WX 1042 ; N arrowdblboth ; B 27 -20 1023 510 ;
|
||||
C 220 ; WX 987 ; N arrowdblleft ; B 30 -15 939 513 ;
|
||||
C 221 ; WX 603 ; N arrowdblup ; B 39 2 567 911 ;
|
||||
C 222 ; WX 987 ; N arrowdblright ; B 45 -20 954 508 ;
|
||||
C 223 ; WX 603 ; N arrowdbldown ; B 44 -19 572 890 ;
|
||||
C 224 ; WX 494 ; N lozenge ; B 18 0 466 745 ;
|
||||
C 225 ; WX 329 ; N angleleft ; B 25 -198 306 746 ;
|
||||
C 226 ; WX 790 ; N registersans ; B 50 -20 740 670 ;
|
||||
C 227 ; WX 790 ; N copyrightsans ; B 49 -15 739 675 ;
|
||||
C 228 ; WX 786 ; N trademarksans ; B 5 293 725 673 ;
|
||||
C 229 ; WX 713 ; N summation ; B 14 -108 695 752 ;
|
||||
C 230 ; WX 384 ; N parenlefttp ; B 24 -293 436 926 ;
|
||||
C 231 ; WX 384 ; N parenleftex ; B 24 -85 108 925 ;
|
||||
C 232 ; WX 384 ; N parenleftbt ; B 24 -293 436 926 ;
|
||||
C 233 ; WX 384 ; N bracketlefttp ; B 0 -80 349 926 ;
|
||||
C 234 ; WX 384 ; N bracketleftex ; B 0 -79 77 925 ;
|
||||
C 235 ; WX 384 ; N bracketleftbt ; B 0 -80 349 926 ;
|
||||
C 236 ; WX 494 ; N bracelefttp ; B 209 -85 445 925 ;
|
||||
C 237 ; WX 494 ; N braceleftmid ; B 20 -85 284 935 ;
|
||||
C 238 ; WX 494 ; N braceleftbt ; B 209 -75 445 935 ;
|
||||
C 239 ; WX 494 ; N braceex ; B 209 -85 284 935 ;
|
||||
C 241 ; WX 329 ; N angleright ; B 21 -198 302 746 ;
|
||||
C 242 ; WX 274 ; N integral ; B 2 -107 291 916 ;
|
||||
C 243 ; WX 686 ; N integraltp ; B 308 -88 675 920 ;
|
||||
C 244 ; WX 686 ; N integralex ; B 308 -88 378 975 ;
|
||||
C 245 ; WX 686 ; N integralbt ; B 11 -87 378 921 ;
|
||||
C 246 ; WX 384 ; N parenrighttp ; B 54 -293 466 926 ;
|
||||
C 247 ; WX 384 ; N parenrightex ; B 382 -85 466 925 ;
|
||||
C 248 ; WX 384 ; N parenrightbt ; B 54 -293 466 926 ;
|
||||
C 249 ; WX 384 ; N bracketrighttp ; B 22 -80 371 926 ;
|
||||
C 250 ; WX 384 ; N bracketrightex ; B 294 -79 371 925 ;
|
||||
C 251 ; WX 384 ; N bracketrightbt ; B 22 -80 371 926 ;
|
||||
C 252 ; WX 494 ; N bracerighttp ; B 48 -85 284 925 ;
|
||||
C 253 ; WX 494 ; N bracerightmid ; B 209 -85 473 935 ;
|
||||
C 254 ; WX 494 ; N bracerightbt ; B 48 -75 284 935 ;
|
||||
C -1 ; WX 790 ; N apple ; B 56 -3 733 808 ;
|
||||
EndCharMetrics
|
||||
EndFontMetrics
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,225 @@
|
||||
StartFontMetrics 4.1
|
||||
Comment Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved.
|
||||
Comment Creation Date: Thu May 1 15:14:13 1997
|
||||
Comment UniqueID 43082
|
||||
Comment VMusage 45775 55535
|
||||
FontName ZapfDingbats
|
||||
FullName ITC Zapf Dingbats
|
||||
FamilyName ZapfDingbats
|
||||
Weight Medium
|
||||
ItalicAngle 0
|
||||
IsFixedPitch false
|
||||
CharacterSet Special
|
||||
FontBBox -1 -143 981 820
|
||||
UnderlinePosition -100
|
||||
UnderlineThickness 50
|
||||
Version 002.000
|
||||
Notice Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved.ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.
|
||||
EncodingScheme FontSpecific
|
||||
StdHW 28
|
||||
StdVW 90
|
||||
StartCharMetrics 202
|
||||
C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
|
||||
C 33 ; WX 974 ; N a1 ; B 35 72 939 621 ;
|
||||
C 34 ; WX 961 ; N a2 ; B 35 81 927 611 ;
|
||||
C 35 ; WX 974 ; N a202 ; B 35 72 939 621 ;
|
||||
C 36 ; WX 980 ; N a3 ; B 35 0 945 692 ;
|
||||
C 37 ; WX 719 ; N a4 ; B 34 139 685 566 ;
|
||||
C 38 ; WX 789 ; N a5 ; B 35 -14 755 705 ;
|
||||
C 39 ; WX 790 ; N a119 ; B 35 -14 755 705 ;
|
||||
C 40 ; WX 791 ; N a118 ; B 35 -13 761 705 ;
|
||||
C 41 ; WX 690 ; N a117 ; B 34 138 655 553 ;
|
||||
C 42 ; WX 960 ; N a11 ; B 35 123 925 568 ;
|
||||
C 43 ; WX 939 ; N a12 ; B 35 134 904 559 ;
|
||||
C 44 ; WX 549 ; N a13 ; B 29 -11 516 705 ;
|
||||
C 45 ; WX 855 ; N a14 ; B 34 59 820 632 ;
|
||||
C 46 ; WX 911 ; N a15 ; B 35 50 876 642 ;
|
||||
C 47 ; WX 933 ; N a16 ; B 35 139 899 550 ;
|
||||
C 48 ; WX 911 ; N a105 ; B 35 50 876 642 ;
|
||||
C 49 ; WX 945 ; N a17 ; B 35 139 909 553 ;
|
||||
C 50 ; WX 974 ; N a18 ; B 35 104 938 587 ;
|
||||
C 51 ; WX 755 ; N a19 ; B 34 -13 721 705 ;
|
||||
C 52 ; WX 846 ; N a20 ; B 36 -14 811 705 ;
|
||||
C 53 ; WX 762 ; N a21 ; B 35 0 727 692 ;
|
||||
C 54 ; WX 761 ; N a22 ; B 35 0 727 692 ;
|
||||
C 55 ; WX 571 ; N a23 ; B -1 -68 571 661 ;
|
||||
C 56 ; WX 677 ; N a24 ; B 36 -13 642 705 ;
|
||||
C 57 ; WX 763 ; N a25 ; B 35 0 728 692 ;
|
||||
C 58 ; WX 760 ; N a26 ; B 35 0 726 692 ;
|
||||
C 59 ; WX 759 ; N a27 ; B 35 0 725 692 ;
|
||||
C 60 ; WX 754 ; N a28 ; B 35 0 720 692 ;
|
||||
C 61 ; WX 494 ; N a6 ; B 35 0 460 692 ;
|
||||
C 62 ; WX 552 ; N a7 ; B 35 0 517 692 ;
|
||||
C 63 ; WX 537 ; N a8 ; B 35 0 503 692 ;
|
||||
C 64 ; WX 577 ; N a9 ; B 35 96 542 596 ;
|
||||
C 65 ; WX 692 ; N a10 ; B 35 -14 657 705 ;
|
||||
C 66 ; WX 786 ; N a29 ; B 35 -14 751 705 ;
|
||||
C 67 ; WX 788 ; N a30 ; B 35 -14 752 705 ;
|
||||
C 68 ; WX 788 ; N a31 ; B 35 -14 753 705 ;
|
||||
C 69 ; WX 790 ; N a32 ; B 35 -14 756 705 ;
|
||||
C 70 ; WX 793 ; N a33 ; B 35 -13 759 705 ;
|
||||
C 71 ; WX 794 ; N a34 ; B 35 -13 759 705 ;
|
||||
C 72 ; WX 816 ; N a35 ; B 35 -14 782 705 ;
|
||||
C 73 ; WX 823 ; N a36 ; B 35 -14 787 705 ;
|
||||
C 74 ; WX 789 ; N a37 ; B 35 -14 754 705 ;
|
||||
C 75 ; WX 841 ; N a38 ; B 35 -14 807 705 ;
|
||||
C 76 ; WX 823 ; N a39 ; B 35 -14 789 705 ;
|
||||
C 77 ; WX 833 ; N a40 ; B 35 -14 798 705 ;
|
||||
C 78 ; WX 816 ; N a41 ; B 35 -13 782 705 ;
|
||||
C 79 ; WX 831 ; N a42 ; B 35 -14 796 705 ;
|
||||
C 80 ; WX 923 ; N a43 ; B 35 -14 888 705 ;
|
||||
C 81 ; WX 744 ; N a44 ; B 35 0 710 692 ;
|
||||
C 82 ; WX 723 ; N a45 ; B 35 0 688 692 ;
|
||||
C 83 ; WX 749 ; N a46 ; B 35 0 714 692 ;
|
||||
C 84 ; WX 790 ; N a47 ; B 34 -14 756 705 ;
|
||||
C 85 ; WX 792 ; N a48 ; B 35 -14 758 705 ;
|
||||
C 86 ; WX 695 ; N a49 ; B 35 -14 661 706 ;
|
||||
C 87 ; WX 776 ; N a50 ; B 35 -6 741 699 ;
|
||||
C 88 ; WX 768 ; N a51 ; B 35 -7 734 699 ;
|
||||
C 89 ; WX 792 ; N a52 ; B 35 -14 757 705 ;
|
||||
C 90 ; WX 759 ; N a53 ; B 35 0 725 692 ;
|
||||
C 91 ; WX 707 ; N a54 ; B 35 -13 672 704 ;
|
||||
C 92 ; WX 708 ; N a55 ; B 35 -14 672 705 ;
|
||||
C 93 ; WX 682 ; N a56 ; B 35 -14 647 705 ;
|
||||
C 94 ; WX 701 ; N a57 ; B 35 -14 666 705 ;
|
||||
C 95 ; WX 826 ; N a58 ; B 35 -14 791 705 ;
|
||||
C 96 ; WX 815 ; N a59 ; B 35 -14 780 705 ;
|
||||
C 97 ; WX 789 ; N a60 ; B 35 -14 754 705 ;
|
||||
C 98 ; WX 789 ; N a61 ; B 35 -14 754 705 ;
|
||||
C 99 ; WX 707 ; N a62 ; B 34 -14 673 705 ;
|
||||
C 100 ; WX 687 ; N a63 ; B 36 0 651 692 ;
|
||||
C 101 ; WX 696 ; N a64 ; B 35 0 661 691 ;
|
||||
C 102 ; WX 689 ; N a65 ; B 35 0 655 692 ;
|
||||
C 103 ; WX 786 ; N a66 ; B 34 -14 751 705 ;
|
||||
C 104 ; WX 787 ; N a67 ; B 35 -14 752 705 ;
|
||||
C 105 ; WX 713 ; N a68 ; B 35 -14 678 705 ;
|
||||
C 106 ; WX 791 ; N a69 ; B 35 -14 756 705 ;
|
||||
C 107 ; WX 785 ; N a70 ; B 36 -14 751 705 ;
|
||||
C 108 ; WX 791 ; N a71 ; B 35 -14 757 705 ;
|
||||
C 109 ; WX 873 ; N a72 ; B 35 -14 838 705 ;
|
||||
C 110 ; WX 761 ; N a73 ; B 35 0 726 692 ;
|
||||
C 111 ; WX 762 ; N a74 ; B 35 0 727 692 ;
|
||||
C 112 ; WX 762 ; N a203 ; B 35 0 727 692 ;
|
||||
C 113 ; WX 759 ; N a75 ; B 35 0 725 692 ;
|
||||
C 114 ; WX 759 ; N a204 ; B 35 0 725 692 ;
|
||||
C 115 ; WX 892 ; N a76 ; B 35 0 858 705 ;
|
||||
C 116 ; WX 892 ; N a77 ; B 35 -14 858 692 ;
|
||||
C 117 ; WX 788 ; N a78 ; B 35 -14 754 705 ;
|
||||
C 118 ; WX 784 ; N a79 ; B 35 -14 749 705 ;
|
||||
C 119 ; WX 438 ; N a81 ; B 35 -14 403 705 ;
|
||||
C 120 ; WX 138 ; N a82 ; B 35 0 104 692 ;
|
||||
C 121 ; WX 277 ; N a83 ; B 35 0 242 692 ;
|
||||
C 122 ; WX 415 ; N a84 ; B 35 0 380 692 ;
|
||||
C 123 ; WX 392 ; N a97 ; B 35 263 357 705 ;
|
||||
C 124 ; WX 392 ; N a98 ; B 34 263 357 705 ;
|
||||
C 125 ; WX 668 ; N a99 ; B 35 263 633 705 ;
|
||||
C 126 ; WX 668 ; N a100 ; B 36 263 634 705 ;
|
||||
C 128 ; WX 390 ; N a89 ; B 35 -14 356 705 ;
|
||||
C 129 ; WX 390 ; N a90 ; B 35 -14 355 705 ;
|
||||
C 130 ; WX 317 ; N a93 ; B 35 0 283 692 ;
|
||||
C 131 ; WX 317 ; N a94 ; B 35 0 283 692 ;
|
||||
C 132 ; WX 276 ; N a91 ; B 35 0 242 692 ;
|
||||
C 133 ; WX 276 ; N a92 ; B 35 0 242 692 ;
|
||||
C 134 ; WX 509 ; N a205 ; B 35 0 475 692 ;
|
||||
C 135 ; WX 509 ; N a85 ; B 35 0 475 692 ;
|
||||
C 136 ; WX 410 ; N a206 ; B 35 0 375 692 ;
|
||||
C 137 ; WX 410 ; N a86 ; B 35 0 375 692 ;
|
||||
C 138 ; WX 234 ; N a87 ; B 35 -14 199 705 ;
|
||||
C 139 ; WX 234 ; N a88 ; B 35 -14 199 705 ;
|
||||
C 140 ; WX 334 ; N a95 ; B 35 0 299 692 ;
|
||||
C 141 ; WX 334 ; N a96 ; B 35 0 299 692 ;
|
||||
C 161 ; WX 732 ; N a101 ; B 35 -143 697 806 ;
|
||||
C 162 ; WX 544 ; N a102 ; B 56 -14 488 706 ;
|
||||
C 163 ; WX 544 ; N a103 ; B 34 -14 508 705 ;
|
||||
C 164 ; WX 910 ; N a104 ; B 35 40 875 651 ;
|
||||
C 165 ; WX 667 ; N a106 ; B 35 -14 633 705 ;
|
||||
C 166 ; WX 760 ; N a107 ; B 35 -14 726 705 ;
|
||||
C 167 ; WX 760 ; N a108 ; B 0 121 758 569 ;
|
||||
C 168 ; WX 776 ; N a112 ; B 35 0 741 705 ;
|
||||
C 169 ; WX 595 ; N a111 ; B 34 -14 560 705 ;
|
||||
C 170 ; WX 694 ; N a110 ; B 35 -14 659 705 ;
|
||||
C 171 ; WX 626 ; N a109 ; B 34 0 591 705 ;
|
||||
C 172 ; WX 788 ; N a120 ; B 35 -14 754 705 ;
|
||||
C 173 ; WX 788 ; N a121 ; B 35 -14 754 705 ;
|
||||
C 174 ; WX 788 ; N a122 ; B 35 -14 754 705 ;
|
||||
C 175 ; WX 788 ; N a123 ; B 35 -14 754 705 ;
|
||||
C 176 ; WX 788 ; N a124 ; B 35 -14 754 705 ;
|
||||
C 177 ; WX 788 ; N a125 ; B 35 -14 754 705 ;
|
||||
C 178 ; WX 788 ; N a126 ; B 35 -14 754 705 ;
|
||||
C 179 ; WX 788 ; N a127 ; B 35 -14 754 705 ;
|
||||
C 180 ; WX 788 ; N a128 ; B 35 -14 754 705 ;
|
||||
C 181 ; WX 788 ; N a129 ; B 35 -14 754 705 ;
|
||||
C 182 ; WX 788 ; N a130 ; B 35 -14 754 705 ;
|
||||
C 183 ; WX 788 ; N a131 ; B 35 -14 754 705 ;
|
||||
C 184 ; WX 788 ; N a132 ; B 35 -14 754 705 ;
|
||||
C 185 ; WX 788 ; N a133 ; B 35 -14 754 705 ;
|
||||
C 186 ; WX 788 ; N a134 ; B 35 -14 754 705 ;
|
||||
C 187 ; WX 788 ; N a135 ; B 35 -14 754 705 ;
|
||||
C 188 ; WX 788 ; N a136 ; B 35 -14 754 705 ;
|
||||
C 189 ; WX 788 ; N a137 ; B 35 -14 754 705 ;
|
||||
C 190 ; WX 788 ; N a138 ; B 35 -14 754 705 ;
|
||||
C 191 ; WX 788 ; N a139 ; B 35 -14 754 705 ;
|
||||
C 192 ; WX 788 ; N a140 ; B 35 -14 754 705 ;
|
||||
C 193 ; WX 788 ; N a141 ; B 35 -14 754 705 ;
|
||||
C 194 ; WX 788 ; N a142 ; B 35 -14 754 705 ;
|
||||
C 195 ; WX 788 ; N a143 ; B 35 -14 754 705 ;
|
||||
C 196 ; WX 788 ; N a144 ; B 35 -14 754 705 ;
|
||||
C 197 ; WX 788 ; N a145 ; B 35 -14 754 705 ;
|
||||
C 198 ; WX 788 ; N a146 ; B 35 -14 754 705 ;
|
||||
C 199 ; WX 788 ; N a147 ; B 35 -14 754 705 ;
|
||||
C 200 ; WX 788 ; N a148 ; B 35 -14 754 705 ;
|
||||
C 201 ; WX 788 ; N a149 ; B 35 -14 754 705 ;
|
||||
C 202 ; WX 788 ; N a150 ; B 35 -14 754 705 ;
|
||||
C 203 ; WX 788 ; N a151 ; B 35 -14 754 705 ;
|
||||
C 204 ; WX 788 ; N a152 ; B 35 -14 754 705 ;
|
||||
C 205 ; WX 788 ; N a153 ; B 35 -14 754 705 ;
|
||||
C 206 ; WX 788 ; N a154 ; B 35 -14 754 705 ;
|
||||
C 207 ; WX 788 ; N a155 ; B 35 -14 754 705 ;
|
||||
C 208 ; WX 788 ; N a156 ; B 35 -14 754 705 ;
|
||||
C 209 ; WX 788 ; N a157 ; B 35 -14 754 705 ;
|
||||
C 210 ; WX 788 ; N a158 ; B 35 -14 754 705 ;
|
||||
C 211 ; WX 788 ; N a159 ; B 35 -14 754 705 ;
|
||||
C 212 ; WX 894 ; N a160 ; B 35 58 860 634 ;
|
||||
C 213 ; WX 838 ; N a161 ; B 35 152 803 540 ;
|
||||
C 214 ; WX 1016 ; N a163 ; B 34 152 981 540 ;
|
||||
C 215 ; WX 458 ; N a164 ; B 35 -127 422 820 ;
|
||||
C 216 ; WX 748 ; N a196 ; B 35 94 698 597 ;
|
||||
C 217 ; WX 924 ; N a165 ; B 35 140 890 552 ;
|
||||
C 218 ; WX 748 ; N a192 ; B 35 94 698 597 ;
|
||||
C 219 ; WX 918 ; N a166 ; B 35 166 884 526 ;
|
||||
C 220 ; WX 927 ; N a167 ; B 35 32 892 660 ;
|
||||
C 221 ; WX 928 ; N a168 ; B 35 129 891 562 ;
|
||||
C 222 ; WX 928 ; N a169 ; B 35 128 893 563 ;
|
||||
C 223 ; WX 834 ; N a170 ; B 35 155 799 537 ;
|
||||
C 224 ; WX 873 ; N a171 ; B 35 93 838 599 ;
|
||||
C 225 ; WX 828 ; N a172 ; B 35 104 791 588 ;
|
||||
C 226 ; WX 924 ; N a173 ; B 35 98 889 594 ;
|
||||
C 227 ; WX 924 ; N a162 ; B 35 98 889 594 ;
|
||||
C 228 ; WX 917 ; N a174 ; B 35 0 882 692 ;
|
||||
C 229 ; WX 930 ; N a175 ; B 35 84 896 608 ;
|
||||
C 230 ; WX 931 ; N a176 ; B 35 84 896 608 ;
|
||||
C 231 ; WX 463 ; N a177 ; B 35 -99 429 791 ;
|
||||
C 232 ; WX 883 ; N a178 ; B 35 71 848 623 ;
|
||||
C 233 ; WX 836 ; N a179 ; B 35 44 802 648 ;
|
||||
C 234 ; WX 836 ; N a193 ; B 35 44 802 648 ;
|
||||
C 235 ; WX 867 ; N a180 ; B 35 101 832 591 ;
|
||||
C 236 ; WX 867 ; N a199 ; B 35 101 832 591 ;
|
||||
C 237 ; WX 696 ; N a181 ; B 35 44 661 648 ;
|
||||
C 238 ; WX 696 ; N a200 ; B 35 44 661 648 ;
|
||||
C 239 ; WX 874 ; N a182 ; B 35 77 840 619 ;
|
||||
C 241 ; WX 874 ; N a201 ; B 35 73 840 615 ;
|
||||
C 242 ; WX 760 ; N a183 ; B 35 0 725 692 ;
|
||||
C 243 ; WX 946 ; N a184 ; B 35 160 911 533 ;
|
||||
C 244 ; WX 771 ; N a197 ; B 34 37 736 655 ;
|
||||
C 245 ; WX 865 ; N a185 ; B 35 207 830 481 ;
|
||||
C 246 ; WX 771 ; N a194 ; B 34 37 736 655 ;
|
||||
C 247 ; WX 888 ; N a198 ; B 34 -19 853 712 ;
|
||||
C 248 ; WX 967 ; N a186 ; B 35 124 932 568 ;
|
||||
C 249 ; WX 888 ; N a195 ; B 34 -19 853 712 ;
|
||||
C 250 ; WX 831 ; N a187 ; B 35 113 796 579 ;
|
||||
C 251 ; WX 873 ; N a188 ; B 36 118 838 578 ;
|
||||
C 252 ; WX 927 ; N a189 ; B 35 150 891 542 ;
|
||||
C 253 ; WX 970 ; N a190 ; B 35 76 931 616 ;
|
||||
C 254 ; WX 918 ; N a191 ; B 34 99 884 593 ;
|
||||
EndCharMetrics
|
||||
EndFontMetrics
|
@ -0,0 +1,156 @@
|
||||
PDFFont = require '../font'
|
||||
PDFObject = require '../object'
|
||||
|
||||
class EmbeddedFont extends PDFFont
|
||||
constructor: (@document, @font, @id) ->
|
||||
@subset = @font.createSubset()
|
||||
@unicode = [[0]]
|
||||
@widths = [@font.getGlyph(0).advanceWidth]
|
||||
|
||||
@name = @font.postscriptName
|
||||
@scale = 1000 / @font.unitsPerEm
|
||||
@ascender = @font.ascent * @scale
|
||||
@descender = @font.descent * @scale
|
||||
@lineGap = @font.lineGap * @scale
|
||||
@bbox = @font.bbox
|
||||
|
||||
encode: (text, features) ->
|
||||
{glyphs, positions} = @font.layout text, features
|
||||
|
||||
res = []
|
||||
for glyph, i in glyphs
|
||||
gid = @subset.includeGlyph glyph.id
|
||||
res.push ('0000' + gid.toString(16)).slice(-4)
|
||||
|
||||
@widths[gid] ?= glyph.advanceWidth * @scale
|
||||
@unicode[gid] ?= glyph.codePoints
|
||||
|
||||
for key of positions[i]
|
||||
positions[i][key] *= @scale
|
||||
|
||||
positions[i].advanceWidth = glyph.advanceWidth * @scale
|
||||
|
||||
return [res, positions]
|
||||
|
||||
widthOfString: (string, size, features) ->
|
||||
width = @font.layout(string, features).advanceWidth
|
||||
scale = size / @font.unitsPerEm
|
||||
return width * scale
|
||||
|
||||
embed: ->
|
||||
isCFF = @subset.cff?
|
||||
fontFile = @document.ref()
|
||||
|
||||
if isCFF
|
||||
fontFile.data.Subtype = 'CIDFontType0C'
|
||||
|
||||
@subset.encodeStream().pipe(fontFile)
|
||||
|
||||
familyClass = (@font['OS/2']?.sFamilyClass or 0) >> 8
|
||||
flags = 0
|
||||
flags |= 1 << 0 if @font.post.isFixedPitch
|
||||
flags |= 1 << 1 if 1 <= familyClass <= 7
|
||||
flags |= 1 << 2 # assume the font uses non-latin characters
|
||||
flags |= 1 << 3 if familyClass is 10
|
||||
flags |= 1 << 6 if @font.head.macStyle.italic
|
||||
|
||||
# generate a random tag (6 uppercase letters. 65 is the char code for 'A')
|
||||
tag = (String.fromCharCode Math.random() * 26 + 65 for i in [0...6]).join ''
|
||||
name = tag + '+' + @font.postscriptName
|
||||
|
||||
bbox = @font.bbox
|
||||
descriptor = @document.ref
|
||||
Type: 'FontDescriptor'
|
||||
FontName: name
|
||||
Flags: flags
|
||||
FontBBox: [bbox.minX * @scale, bbox.minY * @scale, bbox.maxX * @scale, bbox.maxY * @scale]
|
||||
ItalicAngle: @font.italicAngle
|
||||
Ascent: @ascender
|
||||
Descent: @descender
|
||||
CapHeight: (@font.capHeight or @font.ascent) * @scale
|
||||
XHeight: (@font.xHeight or 0) * @scale
|
||||
StemV: 0 # not sure how to calculate this
|
||||
|
||||
if isCFF
|
||||
descriptor.data.FontFile3 = fontFile
|
||||
else
|
||||
descriptor.data.FontFile2 = fontFile
|
||||
|
||||
descriptor.end()
|
||||
|
||||
descendantFont = @document.ref
|
||||
Type: 'Font'
|
||||
Subtype: if isCFF then 'CIDFontType0' else 'CIDFontType2'
|
||||
BaseFont: name
|
||||
CIDSystemInfo:
|
||||
Registry: new String 'Adobe'
|
||||
Ordering: new String 'Identity'
|
||||
Supplement: 0
|
||||
FontDescriptor: descriptor
|
||||
W: [0, @widths]
|
||||
|
||||
descendantFont.end()
|
||||
|
||||
@dictionary.data =
|
||||
Type: 'Font'
|
||||
Subtype: 'Type0'
|
||||
BaseFont: name
|
||||
Encoding: 'Identity-H'
|
||||
DescendantFonts: [descendantFont]
|
||||
ToUnicode: @toUnicodeCmap()
|
||||
|
||||
@dictionary.end()
|
||||
|
||||
toHex = (codePoints...) ->
|
||||
codes = for code in codePoints
|
||||
('0000' + code.toString(16)).slice(-4)
|
||||
|
||||
return codes.join ''
|
||||
|
||||
# Maps the glyph ids encoded in the PDF back to unicode strings
|
||||
# Because of ligature substitutions and the like, there may be one or more
|
||||
# unicode characters represented by each glyph.
|
||||
toUnicodeCmap: ->
|
||||
cmap = @document.ref()
|
||||
|
||||
entries = []
|
||||
for codePoints in @unicode
|
||||
encoded = []
|
||||
|
||||
# encode codePoints to utf16
|
||||
for value in codePoints
|
||||
if value > 0xffff
|
||||
value -= 0x10000
|
||||
encoded.push toHex value >>> 10 & 0x3ff | 0xd800
|
||||
value = 0xdc00 | value & 0x3ff
|
||||
|
||||
encoded.push toHex value
|
||||
|
||||
entries.push "<#{encoded.join ' '}>"
|
||||
|
||||
cmap.end """
|
||||
/CIDInit /ProcSet findresource begin
|
||||
12 dict begin
|
||||
begincmap
|
||||
/CIDSystemInfo <<
|
||||
/Registry (Adobe)
|
||||
/Ordering (UCS)
|
||||
/Supplement 0
|
||||
>> def
|
||||
/CMapName /Adobe-Identity-UCS def
|
||||
/CMapType 2 def
|
||||
1 begincodespacerange
|
||||
<0000><ffff>
|
||||
endcodespacerange
|
||||
1 beginbfrange
|
||||
<0000> <#{toHex entries.length - 1}> [#{entries.join ' '}]
|
||||
endbfrange
|
||||
endcmap
|
||||
CMapName currentdict /CMap defineresource pop
|
||||
end
|
||||
end
|
||||
"""
|
||||
|
||||
return cmap
|
||||
|
||||
module.exports = EmbeddedFont
|
@ -0,0 +1,65 @@
|
||||
AFMFont = require './afm'
|
||||
PDFFont = require '../font'
|
||||
fs = require 'fs'
|
||||
|
||||
class StandardFont extends PDFFont
|
||||
constructor: (@document, @name, @id) ->
|
||||
@font = new AFMFont STANDARD_FONTS[@name]()
|
||||
{@ascender,@descender,@bbox,@lineGap} = @font
|
||||
|
||||
embed: ->
|
||||
@dictionary.data =
|
||||
Type: 'Font'
|
||||
BaseFont: @name
|
||||
Subtype: 'Type1'
|
||||
Encoding: 'WinAnsiEncoding'
|
||||
|
||||
@dictionary.end()
|
||||
|
||||
encode: (text) ->
|
||||
encoded = @font.encodeText text
|
||||
glyphs = @font.glyphsForString '' + text
|
||||
advances = @font.advancesForGlyphs glyphs
|
||||
positions = []
|
||||
for glyph, i in glyphs
|
||||
positions.push
|
||||
xAdvance: advances[i]
|
||||
yAdvance: 0
|
||||
xOffset: 0
|
||||
yOffset: 0
|
||||
advanceWidth: @font.widthOfGlyph glyph
|
||||
|
||||
return [encoded, positions]
|
||||
|
||||
widthOfString: (string, size) ->
|
||||
glyphs = @font.glyphsForString '' + string
|
||||
advances = @font.advancesForGlyphs glyphs
|
||||
|
||||
width = 0
|
||||
for advance in advances
|
||||
width += advance
|
||||
|
||||
scale = size / 1000
|
||||
return width * scale
|
||||
|
||||
@isStandardFont: (name) ->
|
||||
return name of STANDARD_FONTS
|
||||
|
||||
# This insanity is so browserify can inline the font files
|
||||
STANDARD_FONTS =
|
||||
"Courier": -> fs.readFileSync __dirname + "/../font/data/Courier.afm", 'utf8'
|
||||
"Courier-Bold": -> fs.readFileSync __dirname + "/../font/data/Courier-Bold.afm", 'utf8'
|
||||
"Courier-Oblique": -> fs.readFileSync __dirname + "/../font/data/Courier-Oblique.afm", 'utf8'
|
||||
"Courier-BoldOblique": -> fs.readFileSync __dirname + "/../font/data/Courier-BoldOblique.afm", 'utf8'
|
||||
"Helvetica": -> fs.readFileSync __dirname + "/../font/data/Helvetica.afm", 'utf8'
|
||||
"Helvetica-Bold": -> fs.readFileSync __dirname + "/../font/data/Helvetica-Bold.afm", 'utf8'
|
||||
"Helvetica-Oblique": -> fs.readFileSync __dirname + "/../font/data/Helvetica-Oblique.afm", 'utf8'
|
||||
"Helvetica-BoldOblique": -> fs.readFileSync __dirname + "/../font/data/Helvetica-BoldOblique.afm", 'utf8'
|
||||
"Times-Roman": -> fs.readFileSync __dirname + "/../font/data/Times-Roman.afm", 'utf8'
|
||||
"Times-Bold": -> fs.readFileSync __dirname + "/../font/data/Times-Bold.afm", 'utf8'
|
||||
"Times-Italic": -> fs.readFileSync __dirname + "/../font/data/Times-Italic.afm", 'utf8'
|
||||
"Times-BoldItalic": -> fs.readFileSync __dirname + "/../font/data/Times-BoldItalic.afm", 'utf8'
|
||||
"Symbol": -> fs.readFileSync __dirname + "/../font/data/Symbol.afm", 'utf8'
|
||||
"ZapfDingbats": -> fs.readFileSync __dirname + "/../font/data/ZapfDingbats.afm", 'utf8'
|
||||
|
||||
module.exports = StandardFont
|
@ -0,0 +1,178 @@
|
||||
class PDFGradient
|
||||
constructor: (@doc) ->
|
||||
@stops = []
|
||||
@embedded = no
|
||||
@transform = [1, 0, 0, 1, 0, 0]
|
||||
@_colorSpace = 'DeviceRGB'
|
||||
|
||||
stop: (pos, color, opacity = 1) ->
|
||||
opacity = Math.max(0, Math.min(1, opacity))
|
||||
@stops.push [pos, @doc._normalizeColor(color), opacity]
|
||||
return this
|
||||
|
||||
setTransform: (m11, m12, m21, m22, dx, dy) ->
|
||||
@transform = [m11, m12, m21, m22, dx, dy]
|
||||
return this
|
||||
|
||||
embed: (m) ->
|
||||
return if @stops.length is 0
|
||||
@embedded = yes
|
||||
@matrix = m
|
||||
|
||||
# if the last stop comes before 100%, add a copy at 100%
|
||||
last = @stops[@stops.length - 1]
|
||||
if last[0] < 1
|
||||
@stops.push [1, last[1], last[2]]
|
||||
|
||||
bounds = []
|
||||
encode = []
|
||||
stops = []
|
||||
|
||||
for i in [0...@stops.length - 1]
|
||||
encode.push 0, 1
|
||||
unless i + 2 is @stops.length
|
||||
bounds.push @stops[i + 1][0]
|
||||
|
||||
fn = @doc.ref
|
||||
FunctionType: 2
|
||||
Domain: [0, 1]
|
||||
C0: @stops[i + 0][1]
|
||||
C1: @stops[i + 1][1]
|
||||
N: 1
|
||||
|
||||
stops.push fn
|
||||
fn.end()
|
||||
|
||||
# if there are only two stops, we don't need a stitching function
|
||||
if stops.length is 1
|
||||
fn = stops[0]
|
||||
else
|
||||
fn = @doc.ref
|
||||
FunctionType: 3 # stitching function
|
||||
Domain: [0, 1]
|
||||
Functions: stops
|
||||
Bounds: bounds
|
||||
Encode: encode
|
||||
|
||||
fn.end()
|
||||
|
||||
@id = 'Sh' + (++@doc._gradCount)
|
||||
|
||||
shader = @shader fn
|
||||
shader.end()
|
||||
|
||||
pattern = @doc.ref
|
||||
Type: 'Pattern'
|
||||
PatternType: 2
|
||||
Shading: shader
|
||||
Matrix: (+v.toFixed(5) for v in @matrix)
|
||||
|
||||
pattern.end()
|
||||
|
||||
if (@stops.some (stop) -> stop[2] < 1)
|
||||
grad = @opacityGradient()
|
||||
grad._colorSpace = 'DeviceGray'
|
||||
|
||||
for stop in @stops
|
||||
grad.stop stop[0], [stop[2]]
|
||||
|
||||
grad = grad.embed(@matrix)
|
||||
|
||||
pageBBox = [0, 0, @doc.page.width, @doc.page.height]
|
||||
|
||||
form = @doc.ref
|
||||
Type: 'XObject'
|
||||
Subtype: 'Form'
|
||||
FormType: 1
|
||||
BBox: pageBBox
|
||||
Group:
|
||||
Type: 'Group'
|
||||
S: 'Transparency'
|
||||
CS: 'DeviceGray'
|
||||
Resources:
|
||||
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI']
|
||||
Pattern:
|
||||
Sh1: grad
|
||||
|
||||
form.write "/Pattern cs /Sh1 scn"
|
||||
form.end "#{pageBBox.join(" ")} re f"
|
||||
|
||||
gstate = @doc.ref
|
||||
Type: 'ExtGState'
|
||||
SMask:
|
||||
Type: 'Mask'
|
||||
S: 'Luminosity'
|
||||
G: form
|
||||
|
||||
gstate.end()
|
||||
|
||||
opacityPattern = @doc.ref
|
||||
Type: 'Pattern'
|
||||
PatternType: 1
|
||||
PaintType: 1
|
||||
TilingType: 2
|
||||
BBox: pageBBox
|
||||
XStep: pageBBox[2]
|
||||
YStep: pageBBox[3]
|
||||
Resources:
|
||||
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI']
|
||||
Pattern:
|
||||
Sh1: pattern
|
||||
ExtGState:
|
||||
Gs1: gstate
|
||||
|
||||
opacityPattern.write "/Gs1 gs /Pattern cs /Sh1 scn"
|
||||
opacityPattern.end "#{pageBBox.join(" ")} re f"
|
||||
|
||||
@doc.page.patterns[@id] = opacityPattern
|
||||
|
||||
else
|
||||
@doc.page.patterns[@id] = pattern
|
||||
|
||||
return pattern
|
||||
|
||||
apply: (op) ->
|
||||
# apply gradient transform to existing document ctm
|
||||
[m0, m1, m2, m3, m4, m5] = @doc._ctm.slice()
|
||||
[m11, m12, m21, m22, dx, dy] = @transform
|
||||
m = [m0 * m11 + m2 * m12,
|
||||
m1 * m11 + m3 * m12,
|
||||
m0 * m21 + m2 * m22,
|
||||
m1 * m21 + m3 * m22,
|
||||
m0 * dx + m2 * dy + m4,
|
||||
m1 * dx + m3 * dy + m5]
|
||||
|
||||
@embed(m) unless @embedded and m.join(" ") is @matrix.join(" ")
|
||||
@doc.addContent "/#{@id} #{op}"
|
||||
|
||||
class PDFLinearGradient extends PDFGradient
|
||||
constructor: (@doc, @x1, @y1, @x2, @y2) ->
|
||||
super
|
||||
|
||||
shader: (fn) ->
|
||||
@doc.ref
|
||||
ShadingType: 2
|
||||
ColorSpace: @_colorSpace
|
||||
Coords: [@x1, @y1, @x2, @y2]
|
||||
Function: fn
|
||||
Extend: [true, true]
|
||||
|
||||
opacityGradient: ->
|
||||
return new PDFLinearGradient(@doc, @x1, @y1, @x2, @y2)
|
||||
|
||||
class PDFRadialGradient extends PDFGradient
|
||||
constructor: (@doc, @x1, @y1, @r1, @x2, @y2, @r2) ->
|
||||
super
|
||||
|
||||
shader: (fn) ->
|
||||
@doc.ref
|
||||
ShadingType: 3
|
||||
ColorSpace: @_colorSpace
|
||||
Coords: [@x1, @y1, @r1, @x2, @y2, @r2]
|
||||
Function: fn
|
||||
Extend: [true, true]
|
||||
|
||||
opacityGradient: ->
|
||||
return new PDFRadialGradient(@doc, @x1, @y1, @r1, @x2, @y2, @r2)
|
||||
|
||||
module.exports = {PDFGradient, PDFLinearGradient, PDFRadialGradient}
|
@ -0,0 +1,240 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
(function() {
|
||||
var PDFGradient, PDFLinearGradient, PDFRadialGradient,
|
||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
PDFGradient = (function() {
|
||||
function PDFGradient(doc) {
|
||||
this.doc = doc;
|
||||
this.stops = [];
|
||||
this.embedded = false;
|
||||
this.transform = [1, 0, 0, 1, 0, 0];
|
||||
this._colorSpace = 'DeviceRGB';
|
||||
}
|
||||
|
||||
PDFGradient.prototype.stop = function(pos, color, opacity) {
|
||||
if (opacity == null) {
|
||||
opacity = 1;
|
||||
}
|
||||
opacity = Math.max(0, Math.min(1, opacity));
|
||||
this.stops.push([pos, this.doc._normalizeColor(color), opacity]);
|
||||
return this;
|
||||
};
|
||||
|
||||
PDFGradient.prototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
|
||||
this.transform = [m11, m12, m21, m22, dx, dy];
|
||||
return this;
|
||||
};
|
||||
|
||||
PDFGradient.prototype.embed = function(m) {
|
||||
var bounds, encode, fn, form, grad, gstate, i, j, k, last, len, opacityPattern, pageBBox, pattern, ref, ref1, shader, stop, stops, v;
|
||||
if (this.stops.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.embedded = true;
|
||||
this.matrix = m;
|
||||
last = this.stops[this.stops.length - 1];
|
||||
if (last[0] < 1) {
|
||||
this.stops.push([1, last[1], last[2]]);
|
||||
}
|
||||
bounds = [];
|
||||
encode = [];
|
||||
stops = [];
|
||||
for (i = j = 0, ref = this.stops.length - 1; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
|
||||
encode.push(0, 1);
|
||||
if (i + 2 !== this.stops.length) {
|
||||
bounds.push(this.stops[i + 1][0]);
|
||||
}
|
||||
fn = this.doc.ref({
|
||||
FunctionType: 2,
|
||||
Domain: [0, 1],
|
||||
C0: this.stops[i + 0][1],
|
||||
C1: this.stops[i + 1][1],
|
||||
N: 1
|
||||
});
|
||||
stops.push(fn);
|
||||
fn.end();
|
||||
}
|
||||
if (stops.length === 1) {
|
||||
fn = stops[0];
|
||||
} else {
|
||||
fn = this.doc.ref({
|
||||
FunctionType: 3,
|
||||
Domain: [0, 1],
|
||||
Functions: stops,
|
||||
Bounds: bounds,
|
||||
Encode: encode
|
||||
});
|
||||
fn.end();
|
||||
}
|
||||
this.id = 'Sh' + (++this.doc._gradCount);
|
||||
shader = this.shader(fn);
|
||||
shader.end();
|
||||
pattern = this.doc.ref({
|
||||
Type: 'Pattern',
|
||||
PatternType: 2,
|
||||
Shading: shader,
|
||||
Matrix: (function() {
|
||||
var k, len, ref1, results;
|
||||
ref1 = this.matrix;
|
||||
results = [];
|
||||
for (k = 0, len = ref1.length; k < len; k++) {
|
||||
v = ref1[k];
|
||||
results.push(+v.toFixed(5));
|
||||
}
|
||||
return results;
|
||||
}).call(this)
|
||||
});
|
||||
pattern.end();
|
||||
if (this.stops.some(function(stop) {
|
||||
return stop[2] < 1;
|
||||
})) {
|
||||
grad = this.opacityGradient();
|
||||
grad._colorSpace = 'DeviceGray';
|
||||
ref1 = this.stops;
|
||||
for (k = 0, len = ref1.length; k < len; k++) {
|
||||
stop = ref1[k];
|
||||
grad.stop(stop[0], [stop[2]]);
|
||||
}
|
||||
grad = grad.embed(this.matrix);
|
||||
pageBBox = [0, 0, this.doc.page.width, this.doc.page.height];
|
||||
form = this.doc.ref({
|
||||
Type: 'XObject',
|
||||
Subtype: 'Form',
|
||||
FormType: 1,
|
||||
BBox: pageBBox,
|
||||
Group: {
|
||||
Type: 'Group',
|
||||
S: 'Transparency',
|
||||
CS: 'DeviceGray'
|
||||
},
|
||||
Resources: {
|
||||
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI'],
|
||||
Pattern: {
|
||||
Sh1: grad
|
||||
}
|
||||
}
|
||||
});
|
||||
form.write("/Pattern cs /Sh1 scn");
|
||||
form.end((pageBBox.join(" ")) + " re f");
|
||||
gstate = this.doc.ref({
|
||||
Type: 'ExtGState',
|
||||
SMask: {
|
||||
Type: 'Mask',
|
||||
S: 'Luminosity',
|
||||
G: form
|
||||
}
|
||||
});
|
||||
gstate.end();
|
||||
opacityPattern = this.doc.ref({
|
||||
Type: 'Pattern',
|
||||
PatternType: 1,
|
||||
PaintType: 1,
|
||||
TilingType: 2,
|
||||
BBox: pageBBox,
|
||||
XStep: pageBBox[2],
|
||||
YStep: pageBBox[3],
|
||||
Resources: {
|
||||
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI'],
|
||||
Pattern: {
|
||||
Sh1: pattern
|
||||
},
|
||||
ExtGState: {
|
||||
Gs1: gstate
|
||||
}
|
||||
}
|
||||
});
|
||||
opacityPattern.write("/Gs1 gs /Pattern cs /Sh1 scn");
|
||||
opacityPattern.end((pageBBox.join(" ")) + " re f");
|
||||
this.doc.page.patterns[this.id] = opacityPattern;
|
||||
} else {
|
||||
this.doc.page.patterns[this.id] = pattern;
|
||||
}
|
||||
return pattern;
|
||||
};
|
||||
|
||||
PDFGradient.prototype.apply = function(op) {
|
||||
var dx, dy, m, m0, m1, m11, m12, m2, m21, m22, m3, m4, m5, ref, ref1;
|
||||
ref = this.doc._ctm.slice(), m0 = ref[0], m1 = ref[1], m2 = ref[2], m3 = ref[3], m4 = ref[4], m5 = ref[5];
|
||||
ref1 = this.transform, m11 = ref1[0], m12 = ref1[1], m21 = ref1[2], m22 = ref1[3], dx = ref1[4], dy = ref1[5];
|
||||
m = [m0 * m11 + m2 * m12, m1 * m11 + m3 * m12, m0 * m21 + m2 * m22, m1 * m21 + m3 * m22, m0 * dx + m2 * dy + m4, m1 * dx + m3 * dy + m5];
|
||||
if (!(this.embedded && m.join(" ") === this.matrix.join(" "))) {
|
||||
this.embed(m);
|
||||
}
|
||||
return this.doc.addContent("/" + this.id + " " + op);
|
||||
};
|
||||
|
||||
return PDFGradient;
|
||||
|
||||
})();
|
||||
|
||||
PDFLinearGradient = (function(superClass) {
|
||||
extend(PDFLinearGradient, superClass);
|
||||
|
||||
function PDFLinearGradient(doc, x1, y1, x2, y2) {
|
||||
this.doc = doc;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
PDFLinearGradient.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
PDFLinearGradient.prototype.shader = function(fn) {
|
||||
return this.doc.ref({
|
||||
ShadingType: 2,
|
||||
ColorSpace: this._colorSpace,
|
||||
Coords: [this.x1, this.y1, this.x2, this.y2],
|
||||
Function: fn,
|
||||
Extend: [true, true]
|
||||
});
|
||||
};
|
||||
|
||||
PDFLinearGradient.prototype.opacityGradient = function() {
|
||||
return new PDFLinearGradient(this.doc, this.x1, this.y1, this.x2, this.y2);
|
||||
};
|
||||
|
||||
return PDFLinearGradient;
|
||||
|
||||
})(PDFGradient);
|
||||
|
||||
PDFRadialGradient = (function(superClass) {
|
||||
extend(PDFRadialGradient, superClass);
|
||||
|
||||
function PDFRadialGradient(doc, x1, y1, r1, x2, y2, r2) {
|
||||
this.doc = doc;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.r1 = r1;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
this.r2 = r2;
|
||||
PDFRadialGradient.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
PDFRadialGradient.prototype.shader = function(fn) {
|
||||
return this.doc.ref({
|
||||
ShadingType: 3,
|
||||
ColorSpace: this._colorSpace,
|
||||
Coords: [this.x1, this.y1, this.r1, this.x2, this.y2, this.r2],
|
||||
Function: fn,
|
||||
Extend: [true, true]
|
||||
});
|
||||
};
|
||||
|
||||
PDFRadialGradient.prototype.opacityGradient = function() {
|
||||
return new PDFRadialGradient(this.doc, this.x1, this.y1, this.r1, this.x2, this.y2, this.r2);
|
||||
};
|
||||
|
||||
return PDFRadialGradient;
|
||||
|
||||
})(PDFGradient);
|
||||
|
||||
module.exports = {
|
||||
PDFGradient: PDFGradient,
|
||||
PDFLinearGradient: PDFLinearGradient,
|
||||
PDFRadialGradient: PDFRadialGradient
|
||||
};
|
||||
|
||||
}).call(this);
|
@ -0,0 +1,34 @@
|
||||
###
|
||||
PDFImage - embeds images in PDF documents
|
||||
By Devon Govett
|
||||
###
|
||||
|
||||
fs = require 'fs'
|
||||
Data = require './data'
|
||||
JPEG = require './image/jpeg'
|
||||
PNG = require './image/png'
|
||||
|
||||
class PDFImage
|
||||
@open: (src, label) ->
|
||||
if Buffer.isBuffer(src)
|
||||
data = src
|
||||
else if src instanceof ArrayBuffer
|
||||
data = new Buffer(new Uint8Array(src))
|
||||
else
|
||||
if match = /^data:.+;base64,(.*)$/.exec(src)
|
||||
data = new Buffer(match[1], 'base64')
|
||||
|
||||
else
|
||||
data = fs.readFileSync src
|
||||
return unless data
|
||||
|
||||
if data[0] is 0xff and data[1] is 0xd8
|
||||
return new JPEG(data, label)
|
||||
|
||||
else if data[0] is 0x89 and data.toString('ascii', 1, 4) is 'PNG'
|
||||
return new PNG(data, label)
|
||||
|
||||
else
|
||||
throw new Error 'Unknown image format.'
|
||||
|
||||
module.exports = PDFImage
|
@ -0,0 +1,53 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
|
||||
/*
|
||||
PDFImage - embeds images in PDF documents
|
||||
By Devon Govett
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Data, JPEG, PDFImage, PNG, fs;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
Data = require('./data');
|
||||
|
||||
JPEG = require('./image/jpeg');
|
||||
|
||||
PNG = require('./image/png');
|
||||
|
||||
PDFImage = (function() {
|
||||
function PDFImage() {}
|
||||
|
||||
PDFImage.open = function(src, label) {
|
||||
var data, match;
|
||||
if (Buffer.isBuffer(src)) {
|
||||
data = src;
|
||||
} else if (src instanceof ArrayBuffer) {
|
||||
data = new Buffer(new Uint8Array(src));
|
||||
} else {
|
||||
if (match = /^data:.+;base64,(.*)$/.exec(src)) {
|
||||
data = new Buffer(match[1], 'base64');
|
||||
} else {
|
||||
data = fs.readFileSync(src);
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data[0] === 0xff && data[1] === 0xd8) {
|
||||
return new JPEG(data, label);
|
||||
} else if (data[0] === 0x89 && data.toString('ascii', 1, 4) === 'PNG') {
|
||||
return new PNG(data, label);
|
||||
} else {
|
||||
throw new Error('Unknown image format.');
|
||||
}
|
||||
};
|
||||
|
||||
return PDFImage;
|
||||
|
||||
})();
|
||||
|
||||
module.exports = PDFImage;
|
||||
|
||||
}).call(this);
|
@ -0,0 +1,59 @@
|
||||
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
|
||||
throw "SOI not found in JPEG"
|
||||
|
||||
pos = 2
|
||||
while pos < @data.length
|
||||
marker = @data.readUInt16BE(pos)
|
||||
pos += 2
|
||||
break if marker in MARKERS
|
||||
pos += @data.readUInt16BE(pos)
|
||||
|
||||
throw "Invalid JPEG." unless marker in MARKERS
|
||||
pos += 2
|
||||
|
||||
@bits = @data[pos++]
|
||||
@height = @data.readUInt16BE(pos)
|
||||
pos += 2
|
||||
|
||||
@width = @data.readUInt16BE(pos)
|
||||
pos += 2
|
||||
|
||||
channels = @data[pos++]
|
||||
@colorSpace = switch channels
|
||||
when 1 then 'DeviceGray'
|
||||
when 3 then 'DeviceRGB'
|
||||
when 4 then 'DeviceCMYK'
|
||||
|
||||
@obj = null
|
||||
|
||||
embed: (document) ->
|
||||
return if @obj
|
||||
|
||||
@obj = document.ref
|
||||
Type: 'XObject'
|
||||
Subtype: 'Image'
|
||||
BitsPerComponent: @bits
|
||||
Width: @width
|
||||
Height: @height
|
||||
ColorSpace: @colorSpace
|
||||
Filter: 'DCTDecode'
|
||||
|
||||
# add extra decode params for CMYK images. By swapping the
|
||||
# min and max values from the default, we invert the colors. See
|
||||
# section 4.8.4 of the spec.
|
||||
if @colorSpace is 'DeviceCMYK'
|
||||
@obj.data['Decode'] = [1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]
|
||||
|
||||
@obj.end @data
|
||||
|
||||
# free memory
|
||||
@data = null
|
||||
|
||||
module.exports = JPEG
|
@ -0,0 +1,134 @@
|
||||
zlib = require 'zlib'
|
||||
PNG = require 'png-js'
|
||||
|
||||
class PNGImage
|
||||
constructor: (data, @label) ->
|
||||
@image = new PNG(data)
|
||||
@width = @image.width
|
||||
@height = @image.height
|
||||
@imgData = @image.imgData
|
||||
@obj = null
|
||||
|
||||
embed: (@document) ->
|
||||
return if @obj
|
||||
|
||||
@obj = @document.ref
|
||||
Type: 'XObject'
|
||||
Subtype: 'Image'
|
||||
BitsPerComponent: @image.bits
|
||||
Width: @width
|
||||
Height: @height
|
||||
Filter: 'FlateDecode'
|
||||
|
||||
unless @image.hasAlphaChannel
|
||||
params = @document.ref
|
||||
Predictor: 15
|
||||
Colors: @image.colors
|
||||
BitsPerComponent: @image.bits
|
||||
Columns: @width
|
||||
|
||||
@obj.data['DecodeParms'] = params
|
||||
params.end()
|
||||
|
||||
if @image.palette.length is 0
|
||||
@obj.data['ColorSpace'] = @image.colorSpace
|
||||
else
|
||||
# embed the color palette in the PDF as an object stream
|
||||
palette = @document.ref()
|
||||
palette.end new Buffer @image.palette
|
||||
|
||||
# build the color space array for the image
|
||||
@obj.data['ColorSpace'] = ['Indexed', 'DeviceRGB', (@image.palette.length / 3) - 1, palette]
|
||||
|
||||
# For PNG color types 0, 2 and 3, the transparency data is stored in
|
||||
# a dedicated PNG chunk.
|
||||
if @image.transparency.grayscale
|
||||
# Use Color Key Masking (spec section 4.8.5)
|
||||
# An array with N elements, where N is two times the number of color components.
|
||||
val = @image.transparency.greyscale
|
||||
@obj.data['Mask'] = [val, val]
|
||||
|
||||
else if @image.transparency.rgb
|
||||
# Use Color Key Masking (spec section 4.8.5)
|
||||
# An array with N elements, where N is two times the number of color components.
|
||||
rgb = @image.transparency.rgb
|
||||
mask = []
|
||||
for x in rgb
|
||||
mask.push x, x
|
||||
|
||||
@obj.data['Mask'] = mask
|
||||
|
||||
else if @image.transparency.indexed
|
||||
# Create a transparency SMask for the image based on the data
|
||||
# in the PLTE and tRNS sections. See below for details on SMasks.
|
||||
@loadIndexedAlphaChannel()
|
||||
|
||||
else if @image.hasAlphaChannel
|
||||
# For PNG color types 4 and 6, the transparency data is stored as a alpha
|
||||
# channel mixed in with the main image data. Separate this data out into an
|
||||
# SMask object and store it separately in the PDF.
|
||||
@splitAlphaChannel()
|
||||
|
||||
else
|
||||
@finalize()
|
||||
|
||||
finalize: ->
|
||||
if @alphaChannel
|
||||
sMask = @document.ref
|
||||
Type: 'XObject'
|
||||
Subtype: 'Image'
|
||||
Height: @height
|
||||
Width: @width
|
||||
BitsPerComponent: 8
|
||||
Filter: 'FlateDecode'
|
||||
ColorSpace: 'DeviceGray'
|
||||
Decode: [0, 1]
|
||||
|
||||
sMask.end @alphaChannel
|
||||
@obj.data['SMask'] = sMask
|
||||
|
||||
# add the actual image data
|
||||
@obj.end @imgData
|
||||
|
||||
# free memory
|
||||
@image = null
|
||||
@imgData = null
|
||||
|
||||
splitAlphaChannel: ->
|
||||
@image.decodePixels (pixels) =>
|
||||
colorByteSize = @image.colors * @image.bits / 8
|
||||
pixelCount = @width * @height
|
||||
imgData = new Buffer(pixelCount * colorByteSize)
|
||||
alphaChannel = new Buffer(pixelCount)
|
||||
|
||||
i = p = a = 0
|
||||
len = pixels.length
|
||||
while i < len
|
||||
imgData[p++] = pixels[i++]
|
||||
imgData[p++] = pixels[i++]
|
||||
imgData[p++] = pixels[i++]
|
||||
alphaChannel[a++] = pixels[i++]
|
||||
|
||||
done = 0
|
||||
zlib.deflate imgData, (err, @imgData) =>
|
||||
throw err if err
|
||||
@finalize() if ++done is 2
|
||||
|
||||
zlib.deflate alphaChannel, (err, @alphaChannel) =>
|
||||
throw err if err
|
||||
@finalize() if ++done is 2
|
||||
|
||||
loadIndexedAlphaChannel: (fn) ->
|
||||
transparency = @image.transparency.indexed
|
||||
@image.decodePixels (pixels) =>
|
||||
alphaChannel = new Buffer(@width * @height)
|
||||
|
||||
i = 0
|
||||
for j in [0...pixels.length] by 1
|
||||
alphaChannel[i++] = transparency[pixels[j]]
|
||||
|
||||
zlib.deflate alphaChannel, (err, @alphaChannel) =>
|
||||
throw err if err
|
||||
@finalize()
|
||||
|
||||
module.exports = PNGImage
|
@ -0,0 +1,230 @@
|
||||
{EventEmitter} = require 'events'
|
||||
LineBreaker = require 'linebreak'
|
||||
|
||||
class LineWrapper extends EventEmitter
|
||||
constructor: (@document, options) ->
|
||||
@indent = options.indent 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?
|
||||
@height = options.height
|
||||
@maxY = @startY + options.height
|
||||
else
|
||||
@maxY = @document.page.maxY()
|
||||
|
||||
# handle paragraph indents
|
||||
@on 'firstLine', (options) =>
|
||||
# if this is the first line of the text segment, and
|
||||
# we're continuing where we left off, indent that much
|
||||
# otherwise use the user specified indent option
|
||||
indent = @continuedX or @indent
|
||||
@document.x += indent
|
||||
@lineWidth -= indent
|
||||
|
||||
@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
|
||||
@on 'lastLine', (options) =>
|
||||
align = options.align
|
||||
options.align = 'left' if align is 'justify'
|
||||
@lastLine = true
|
||||
|
||||
@once 'line', =>
|
||||
@document.y += options.paragraphGap or 0
|
||||
options.align = align
|
||||
@lastLine = false
|
||||
|
||||
wordWidth: (word) ->
|
||||
return @document.widthOfString(word, this) + @characterSpacing + @wordSpacing
|
||||
|
||||
eachWord: (text, fn) ->
|
||||
# setup a unicode line breaker
|
||||
breaker = new LineBreaker(text)
|
||||
last = null
|
||||
wordWidths = Object.create(null)
|
||||
|
||||
while bk = breaker.nextBreak()
|
||||
word = text.slice(last?.position or 0, bk.position)
|
||||
w = wordWidths[word] ?= @wordWidth word
|
||||
|
||||
# if the word is longer than the whole line, chop it up
|
||||
# TODO: break by grapheme clusters, not JS string characters
|
||||
if w > @lineWidth + @continuedX
|
||||
# make some fake break objects
|
||||
lbk = last
|
||||
fbk = {}
|
||||
|
||||
while word.length
|
||||
# fit as much of the word as possible into the space we have
|
||||
l = word.length
|
||||
while w > @spaceLeft
|
||||
w = @wordWidth word.slice(0, --l)
|
||||
|
||||
# send a required break unless this is the last piece
|
||||
fbk.required = l < word.length
|
||||
shouldContinue = fn word.slice(0, l), w, fbk, lbk
|
||||
lbk = required: false
|
||||
|
||||
# get the remaining piece of the word
|
||||
word = word.slice(l)
|
||||
w = @wordWidth word
|
||||
|
||||
break if shouldContinue is no
|
||||
else
|
||||
# otherwise just emit the break as it was given to us
|
||||
shouldContinue = fn word, w, bk, last
|
||||
|
||||
break if shouldContinue is no
|
||||
last = bk
|
||||
|
||||
return
|
||||
|
||||
wrap: (text, options) ->
|
||||
# override options from previous continued fragments
|
||||
@indent = options.indent if options.indent?
|
||||
@characterSpacing = options.characterSpacing if options.characterSpacing?
|
||||
@wordSpacing = options.wordSpacing if options.wordSpacing?
|
||||
@ellipsis = options.ellipsis if options.ellipsis?
|
||||
|
||||
# make sure we're actually on the page
|
||||
# and that the first line of is never by
|
||||
# itself at the bottom of a page (orphans)
|
||||
nextY = @document.y + @document.currentLineHeight(true)
|
||||
if @document.y > @maxY or nextY > @maxY
|
||||
@nextSection()
|
||||
|
||||
buffer = ''
|
||||
textWidth = 0
|
||||
wc = 0
|
||||
lc = 0
|
||||
|
||||
y = @document.y # used to reset Y pos if options.continued (below)
|
||||
emitLine = =>
|
||||
options.textWidth = textWidth + @wordSpacing * (wc - 1)
|
||||
options.wordCount = wc
|
||||
options.lineWidth = @lineWidth
|
||||
y = @document.y
|
||||
@emit 'line', buffer, options, this
|
||||
lc++
|
||||
|
||||
@emit 'sectionStart', options, this
|
||||
|
||||
@eachWord text, (word, w, bk, last) =>
|
||||
if not last? or last.required
|
||||
@emit 'firstLine', options, this
|
||||
@spaceLeft = @lineWidth
|
||||
|
||||
if w <= @spaceLeft
|
||||
buffer += word
|
||||
textWidth += w
|
||||
wc++
|
||||
|
||||
if bk.required or w > @spaceLeft
|
||||
if bk.required
|
||||
@emit 'lastLine', options, this
|
||||
|
||||
# if the user specified a max height and an ellipsis, and is about to pass the
|
||||
# max height and max columns after the next line, append the ellipsis
|
||||
lh = @document.currentLineHeight(true)
|
||||
if @height? and @ellipsis and @document.y + lh * 2 > @maxY and @column >= @columns
|
||||
@ellipsis = '…' if @ellipsis is true # map default ellipsis character
|
||||
buffer = buffer.replace(/\s+$/, '')
|
||||
textWidth = @wordWidth buffer + @ellipsis
|
||||
|
||||
# remove characters from the buffer until the ellipsis fits
|
||||
while textWidth > @lineWidth
|
||||
buffer = buffer.slice(0, -1).replace(/\s+$/, '')
|
||||
textWidth = @wordWidth buffer + @ellipsis
|
||||
|
||||
buffer = buffer + @ellipsis
|
||||
|
||||
if bk.required and w > @spaceLeft
|
||||
buffer = word
|
||||
textWidth = w
|
||||
wc = 1
|
||||
|
||||
emitLine()
|
||||
|
||||
# if we've reached the edge of the page,
|
||||
# continue on a new page or column
|
||||
if @document.y + lh > @maxY
|
||||
shouldContinue = @nextSection()
|
||||
|
||||
# stop if we reached the maximum height
|
||||
unless shouldContinue
|
||||
wc = 0
|
||||
buffer = ''
|
||||
return no
|
||||
|
||||
# reset the space left and buffer
|
||||
if bk.required
|
||||
@spaceLeft = @lineWidth
|
||||
buffer = ''
|
||||
textWidth = 0
|
||||
wc = 0
|
||||
else
|
||||
# reset the space left and buffer
|
||||
@spaceLeft = @lineWidth - w
|
||||
buffer = word
|
||||
textWidth = w
|
||||
wc = 1
|
||||
else
|
||||
@spaceLeft -= w
|
||||
|
||||
if wc > 0
|
||||
@emit 'lastLine', options, this
|
||||
emitLine()
|
||||
|
||||
@emit 'sectionEnd', options, this
|
||||
|
||||
# if the wrap is set to be continued, save the X position
|
||||
# to start the first line of the next segment at, and reset
|
||||
# the y position
|
||||
if options.continued is yes
|
||||
@continuedX = 0 if lc > 1
|
||||
@continuedX += options.textWidth
|
||||
@document.y = y
|
||||
else
|
||||
@document.x = @startX
|
||||
|
||||
nextSection: (options) ->
|
||||
@emit 'sectionEnd', options, this
|
||||
|
||||
if ++@column > @columns
|
||||
# if a max height was specified by the user, we're done.
|
||||
# otherwise, the default is to make a new page at the bottom.
|
||||
return false if @height?
|
||||
|
||||
@document.addPage()
|
||||
@column = 1
|
||||
@startY = @document.page.margins.top
|
||||
@maxY = @document.page.maxY()
|
||||
@document.x = @startX
|
||||
@document.fillColor @document._fillColor... if @document._fillColor
|
||||
@emit 'pageBreak', options, this
|
||||
else
|
||||
@document.x += @lineWidth + @columnGap
|
||||
@document.y = @startY
|
||||
@emit 'columnBreak', options, this
|
||||
|
||||
@emit 'sectionStart', options, this
|
||||
return true
|
||||
|
||||
module.exports = LineWrapper
|
@ -0,0 +1,252 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
(function() {
|
||||
var EventEmitter, LineBreaker, LineWrapper,
|
||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
|
||||
LineBreaker = require('linebreak');
|
||||
|
||||
LineWrapper = (function(superClass) {
|
||||
extend(LineWrapper, superClass);
|
||||
|
||||
function LineWrapper(document, options) {
|
||||
var ref;
|
||||
this.document = document;
|
||||
this.indent = options.indent || 0;
|
||||
this.characterSpacing = options.characterSpacing || 0;
|
||||
this.wordSpacing = options.wordSpacing === 0;
|
||||
this.columns = options.columns || 1;
|
||||
this.columnGap = (ref = options.columnGap) != null ? ref : 18;
|
||||
this.lineWidth = (options.width - (this.columnGap * (this.columns - 1))) / this.columns;
|
||||
this.spaceLeft = this.lineWidth;
|
||||
this.startX = this.document.x;
|
||||
this.startY = this.document.y;
|
||||
this.column = 1;
|
||||
this.ellipsis = options.ellipsis;
|
||||
this.continuedX = 0;
|
||||
this.features = options.features;
|
||||
if (options.height != null) {
|
||||
this.height = options.height;
|
||||
this.maxY = this.startY + options.height;
|
||||
} else {
|
||||
this.maxY = this.document.page.maxY();
|
||||
}
|
||||
this.on('firstLine', (function(_this) {
|
||||
return function(options) {
|
||||
var indent;
|
||||
indent = _this.continuedX || _this.indent;
|
||||
_this.document.x += indent;
|
||||
_this.lineWidth -= indent;
|
||||
return _this.once('line', function() {
|
||||
_this.document.x -= indent;
|
||||
_this.lineWidth += indent;
|
||||
if (options.continued && !_this.continuedX) {
|
||||
_this.continuedX = _this.indent;
|
||||
}
|
||||
if (!options.continued) {
|
||||
return _this.continuedX = 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
})(this));
|
||||
this.on('lastLine', (function(_this) {
|
||||
return function(options) {
|
||||
var align;
|
||||
align = options.align;
|
||||
if (align === 'justify') {
|
||||
options.align = 'left';
|
||||
}
|
||||
_this.lastLine = true;
|
||||
return _this.once('line', function() {
|
||||
_this.document.y += options.paragraphGap || 0;
|
||||
options.align = align;
|
||||
return _this.lastLine = false;
|
||||
});
|
||||
};
|
||||
})(this));
|
||||
}
|
||||
|
||||
LineWrapper.prototype.wordWidth = function(word) {
|
||||
return this.document.widthOfString(word, this) + this.characterSpacing + this.wordSpacing;
|
||||
};
|
||||
|
||||
LineWrapper.prototype.eachWord = function(text, fn) {
|
||||
var bk, breaker, fbk, l, last, lbk, shouldContinue, w, word, wordWidths;
|
||||
breaker = new LineBreaker(text);
|
||||
last = null;
|
||||
wordWidths = Object.create(null);
|
||||
while (bk = breaker.nextBreak()) {
|
||||
word = text.slice((last != null ? last.position : void 0) || 0, bk.position);
|
||||
w = wordWidths[word] != null ? wordWidths[word] : wordWidths[word] = this.wordWidth(word);
|
||||
if (w > this.lineWidth + this.continuedX) {
|
||||
lbk = last;
|
||||
fbk = {};
|
||||
while (word.length) {
|
||||
l = word.length;
|
||||
while (w > this.spaceLeft) {
|
||||
w = this.wordWidth(word.slice(0, --l));
|
||||
}
|
||||
fbk.required = l < word.length;
|
||||
shouldContinue = fn(word.slice(0, l), w, fbk, lbk);
|
||||
lbk = {
|
||||
required: false
|
||||
};
|
||||
word = word.slice(l);
|
||||
w = this.wordWidth(word);
|
||||
if (shouldContinue === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
shouldContinue = fn(word, w, bk, last);
|
||||
}
|
||||
if (shouldContinue === false) {
|
||||
break;
|
||||
}
|
||||
last = bk;
|
||||
}
|
||||
};
|
||||
|
||||
LineWrapper.prototype.wrap = function(text, options) {
|
||||
var buffer, emitLine, lc, nextY, textWidth, wc, y;
|
||||
if (options.indent != null) {
|
||||
this.indent = options.indent;
|
||||
}
|
||||
if (options.characterSpacing != null) {
|
||||
this.characterSpacing = options.characterSpacing;
|
||||
}
|
||||
if (options.wordSpacing != null) {
|
||||
this.wordSpacing = options.wordSpacing;
|
||||
}
|
||||
if (options.ellipsis != null) {
|
||||
this.ellipsis = options.ellipsis;
|
||||
}
|
||||
nextY = this.document.y + this.document.currentLineHeight(true);
|
||||
if (this.document.y > this.maxY || nextY > this.maxY) {
|
||||
this.nextSection();
|
||||
}
|
||||
buffer = '';
|
||||
textWidth = 0;
|
||||
wc = 0;
|
||||
lc = 0;
|
||||
y = this.document.y;
|
||||
emitLine = (function(_this) {
|
||||
return function() {
|
||||
options.textWidth = textWidth + _this.wordSpacing * (wc - 1);
|
||||
options.wordCount = wc;
|
||||
options.lineWidth = _this.lineWidth;
|
||||
y = _this.document.y;
|
||||
_this.emit('line', buffer, options, _this);
|
||||
return lc++;
|
||||
};
|
||||
})(this);
|
||||
this.emit('sectionStart', options, this);
|
||||
this.eachWord(text, (function(_this) {
|
||||
return function(word, w, bk, last) {
|
||||
var lh, shouldContinue;
|
||||
if ((last == null) || last.required) {
|
||||
_this.emit('firstLine', options, _this);
|
||||
_this.spaceLeft = _this.lineWidth;
|
||||
}
|
||||
if (w <= _this.spaceLeft) {
|
||||
buffer += word;
|
||||
textWidth += w;
|
||||
wc++;
|
||||
}
|
||||
if (bk.required || w > _this.spaceLeft) {
|
||||
if (bk.required) {
|
||||
_this.emit('lastLine', options, _this);
|
||||
}
|
||||
lh = _this.document.currentLineHeight(true);
|
||||
if ((_this.height != null) && _this.ellipsis && _this.document.y + lh * 2 > _this.maxY && _this.column >= _this.columns) {
|
||||
if (_this.ellipsis === true) {
|
||||
_this.ellipsis = '…';
|
||||
}
|
||||
buffer = buffer.replace(/\s+$/, '');
|
||||
textWidth = _this.wordWidth(buffer + _this.ellipsis);
|
||||
while (textWidth > _this.lineWidth) {
|
||||
buffer = buffer.slice(0, -1).replace(/\s+$/, '');
|
||||
textWidth = _this.wordWidth(buffer + _this.ellipsis);
|
||||
}
|
||||
buffer = buffer + _this.ellipsis;
|
||||
}
|
||||
if (bk.required && w > _this.spaceLeft) {
|
||||
buffer = word;
|
||||
textWidth = w;
|
||||
wc = 1;
|
||||
}
|
||||
emitLine();
|
||||
if (_this.document.y + lh > _this.maxY) {
|
||||
shouldContinue = _this.nextSection();
|
||||
if (!shouldContinue) {
|
||||
wc = 0;
|
||||
buffer = '';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (bk.required) {
|
||||
_this.spaceLeft = _this.lineWidth;
|
||||
buffer = '';
|
||||
textWidth = 0;
|
||||
return wc = 0;
|
||||
} else {
|
||||
_this.spaceLeft = _this.lineWidth - w;
|
||||
buffer = word;
|
||||
textWidth = w;
|
||||
return wc = 1;
|
||||
}
|
||||
} else {
|
||||
return _this.spaceLeft -= w;
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
if (wc > 0) {
|
||||
this.emit('lastLine', options, this);
|
||||
emitLine();
|
||||
}
|
||||
this.emit('sectionEnd', options, this);
|
||||
if (options.continued === true) {
|
||||
if (lc > 1) {
|
||||
this.continuedX = 0;
|
||||
}
|
||||
this.continuedX += options.textWidth;
|
||||
return this.document.y = y;
|
||||
} else {
|
||||
return this.document.x = this.startX;
|
||||
}
|
||||
};
|
||||
|
||||
LineWrapper.prototype.nextSection = function(options) {
|
||||
var ref;
|
||||
this.emit('sectionEnd', options, this);
|
||||
if (++this.column > this.columns) {
|
||||
if (this.height != null) {
|
||||
return false;
|
||||
}
|
||||
this.document.addPage();
|
||||
this.column = 1;
|
||||
this.startY = this.document.page.margins.top;
|
||||
this.maxY = this.document.page.maxY();
|
||||
this.document.x = this.startX;
|
||||
if (this.document._fillColor) {
|
||||
(ref = this.document).fillColor.apply(ref, this.document._fillColor);
|
||||
}
|
||||
this.emit('pageBreak', options, this);
|
||||
} else {
|
||||
this.document.x += this.lineWidth + this.columnGap;
|
||||
this.document.y = this.startY;
|
||||
this.emit('columnBreak', options, this);
|
||||
}
|
||||
this.emit('sectionStart', options, this);
|
||||
return true;
|
||||
};
|
||||
|
||||
return LineWrapper;
|
||||
|
||||
})(EventEmitter);
|
||||
|
||||
module.exports = LineWrapper;
|
||||
|
||||
}).call(this);
|
@ -0,0 +1,93 @@
|
||||
module.exports =
|
||||
annotate: (x, y, w, h, options) ->
|
||||
options.Type = 'Annot'
|
||||
options.Rect = @_convertRect x, y, w, h
|
||||
options.Border = [0, 0, 0]
|
||||
options.C ?= @_normalizeColor(options.color or [0, 0, 0]) unless options.Subtype is 'Link' # convert colors
|
||||
delete options.color
|
||||
|
||||
if typeof options.Dest is 'string'
|
||||
options.Dest = new String options.Dest
|
||||
|
||||
# Capitalize keys
|
||||
for key, val of options
|
||||
options[key[0].toUpperCase() + key.slice(1)] = val
|
||||
|
||||
ref = @ref options
|
||||
@page.annotations.push ref
|
||||
ref.end()
|
||||
return this
|
||||
|
||||
note: (x, y, w, h, contents, options = {}) ->
|
||||
options.Subtype = 'Text'
|
||||
options.Contents = new String contents
|
||||
options.Name = 'Comment'
|
||||
options.color ?= [243, 223, 92]
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
link: (x, y, w, h, url, options = {}) ->
|
||||
options.Subtype = 'Link'
|
||||
options.A = @ref
|
||||
S: 'URI'
|
||||
URI: new String url
|
||||
|
||||
options.A.end()
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
_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 = new String
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
highlight: (x, y, w, h, options = {}) ->
|
||||
options.Subtype = 'Highlight'
|
||||
options.color ?= [241, 238, 148]
|
||||
@_markup x, y, w, h, options
|
||||
|
||||
underline: (x, y, w, h, options = {}) ->
|
||||
options.Subtype = 'Underline'
|
||||
@_markup x, y, w, h, options
|
||||
|
||||
strike: (x, y, w, h, options = {}) ->
|
||||
options.Subtype = 'StrikeOut'
|
||||
@_markup x, y, w, h, options
|
||||
|
||||
lineAnnotation: (x1, y1, x2, y2, options = {}) ->
|
||||
options.Subtype = 'Line'
|
||||
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 = new String
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
ellipseAnnotation: (x, y, w, h, options = {}) ->
|
||||
options.Subtype = 'Circle'
|
||||
options.Contents = new String
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
textAnnotation: (x, y, w, h, text, options = {}) ->
|
||||
options.Subtype = 'FreeText'
|
||||
options.Contents = new String text
|
||||
options.DA = new String
|
||||
@annotate x, y, w, h, options
|
||||
|
||||
_convertRect: (x1, y1, w, h) ->
|
||||
# flip y1 and y2
|
||||
y2 = y1
|
||||
y1 += h
|
||||
|
||||
# make x2
|
||||
x2 = x1 + w
|
||||
|
||||
# apply current transformation matrix to points
|
||||
[m0, m1, m2, m3, m4, m5] = @_ctm
|
||||
x1 = m0 * x1 + m2 * y1 + m4
|
||||
y1 = m1 * x1 + m3 * y1 + m5
|
||||
x2 = m0 * x2 + m2 * y2 + m4
|
||||
y2 = m1 * x2 + m3 * y2 + m5
|
||||
|
||||
return [x1, y1, x2, y2]
|
@ -0,0 +1,262 @@
|
||||
{PDFGradient, PDFLinearGradient, PDFRadialGradient} = require '../gradient'
|
||||
|
||||
module.exports =
|
||||
initColor: ->
|
||||
# The opacity dictionaries
|
||||
@_opacityRegistry = {}
|
||||
@_opacityCount = 0
|
||||
@_gradCount = 0
|
||||
|
||||
_normalizeColor: (color) ->
|
||||
if color instanceof PDFGradient
|
||||
return color
|
||||
|
||||
if typeof color is 'string'
|
||||
if color.charAt(0) is '#'
|
||||
color = color.replace(/#([0-9A-F])([0-9A-F])([0-9A-F])/i, "#$1$1$2$2$3$3") if color.length is 4
|
||||
hex = parseInt(color.slice(1), 16)
|
||||
color = [hex >> 16, hex >> 8 & 0xff, hex & 0xff]
|
||||
|
||||
else if namedColors[color]
|
||||
color = namedColors[color]
|
||||
|
||||
if Array.isArray color
|
||||
# RGB
|
||||
if color.length is 3
|
||||
color = (part / 255 for part in color)
|
||||
|
||||
# CMYK
|
||||
else if color.length is 4
|
||||
color = (part / 100 for part in color)
|
||||
|
||||
return color
|
||||
|
||||
return null
|
||||
|
||||
_setColor: (color, stroke) ->
|
||||
color = @_normalizeColor color
|
||||
return no unless color
|
||||
|
||||
op = if stroke then 'SCN' else 'scn'
|
||||
|
||||
if color instanceof PDFGradient
|
||||
@_setColorSpace 'Pattern', stroke
|
||||
color.apply(op)
|
||||
else
|
||||
space = if color.length is 4 then 'DeviceCMYK' else 'DeviceRGB'
|
||||
@_setColorSpace space, stroke
|
||||
|
||||
color = color.join ' '
|
||||
@addContent "#{color} #{op}"
|
||||
|
||||
return yes
|
||||
|
||||
_setColorSpace: (space, stroke) ->
|
||||
op = if stroke then 'CS' else 'cs'
|
||||
@addContent "/#{space} #{op}"
|
||||
|
||||
fillColor: (color, opacity = 1) ->
|
||||
set = @_setColor color, no
|
||||
@fillOpacity opacity if set
|
||||
|
||||
# save this for text wrapper, which needs to reset
|
||||
# the fill color on new pages
|
||||
@_fillColor = [color, opacity]
|
||||
return this
|
||||
|
||||
strokeColor: (color, opacity = 1) ->
|
||||
set = @_setColor color, yes
|
||||
@strokeOpacity opacity if set
|
||||
return this
|
||||
|
||||
opacity: (opacity) ->
|
||||
@_doOpacity opacity, opacity
|
||||
return this
|
||||
|
||||
fillOpacity: (opacity) ->
|
||||
@_doOpacity opacity, null
|
||||
return this
|
||||
|
||||
strokeOpacity: (opacity) ->
|
||||
@_doOpacity null, opacity
|
||||
return this
|
||||
|
||||
_doOpacity: (fillOpacity, strokeOpacity) ->
|
||||
return unless fillOpacity? or strokeOpacity?
|
||||
|
||||
fillOpacity = Math.max 0, Math.min 1, fillOpacity if fillOpacity?
|
||||
strokeOpacity = Math.max 0, Math.min 1, strokeOpacity if strokeOpacity?
|
||||
key = "#{fillOpacity}_#{strokeOpacity}"
|
||||
|
||||
if @_opacityRegistry[key]
|
||||
[dictionary, name] = @_opacityRegistry[key]
|
||||
else
|
||||
dictionary =
|
||||
Type: 'ExtGState'
|
||||
|
||||
dictionary.ca = fillOpacity if fillOpacity?
|
||||
dictionary.CA = strokeOpacity if strokeOpacity?
|
||||
|
||||
dictionary = @ref dictionary
|
||||
dictionary.end()
|
||||
id = ++@_opacityCount
|
||||
name = "Gs#{id}"
|
||||
@_opacityRegistry[key] = [dictionary, name]
|
||||
|
||||
@page.ext_gstates[name] = dictionary
|
||||
@addContent "/#{name} gs"
|
||||
|
||||
linearGradient: (x1, y1, x2, y2) ->
|
||||
return new PDFLinearGradient(this, x1, y1, x2, y2)
|
||||
|
||||
radialGradient: (x1, y1, r1, x2, y2, r2) ->
|
||||
return new PDFRadialGradient(this, x1, y1, r1, x2, y2, r2)
|
||||
|
||||
namedColors =
|
||||
aliceblue: [240, 248, 255]
|
||||
antiquewhite: [250, 235, 215]
|
||||
aqua: [0, 255, 255]
|
||||
aquamarine: [127, 255, 212]
|
||||
azure: [240, 255, 255]
|
||||
beige: [245, 245, 220]
|
||||
bisque: [255, 228, 196]
|
||||
black: [0, 0, 0]
|
||||
blanchedalmond: [255, 235, 205]
|
||||
blue: [0, 0, 255]
|
||||
blueviolet: [138, 43, 226]
|
||||
brown: [165, 42, 42]
|
||||
burlywood: [222, 184, 135]
|
||||
cadetblue: [95, 158, 160]
|
||||
chartreuse: [127, 255, 0]
|
||||
chocolate: [210, 105, 30]
|
||||
coral: [255, 127, 80]
|
||||
cornflowerblue: [100, 149, 237]
|
||||
cornsilk: [255, 248, 220]
|
||||
crimson: [220, 20, 60]
|
||||
cyan: [0, 255, 255]
|
||||
darkblue: [0, 0, 139]
|
||||
darkcyan: [0, 139, 139]
|
||||
darkgoldenrod: [184, 134, 11]
|
||||
darkgray: [169, 169, 169]
|
||||
darkgreen: [0, 100, 0]
|
||||
darkgrey: [169, 169, 169]
|
||||
darkkhaki: [189, 183, 107]
|
||||
darkmagenta: [139, 0, 139]
|
||||
darkolivegreen: [85, 107, 47]
|
||||
darkorange: [255, 140, 0]
|
||||
darkorchid: [153, 50, 204]
|
||||
darkred: [139, 0, 0]
|
||||
darksalmon: [233, 150, 122]
|
||||
darkseagreen: [143, 188, 143]
|
||||
darkslateblue: [72, 61, 139]
|
||||
darkslategray: [47, 79, 79]
|
||||
darkslategrey: [47, 79, 79]
|
||||
darkturquoise: [0, 206, 209]
|
||||
darkviolet: [148, 0, 211]
|
||||
deeppink: [255, 20, 147]
|
||||
deepskyblue: [0, 191, 255]
|
||||
dimgray: [105, 105, 105]
|
||||
dimgrey: [105, 105, 105]
|
||||
dodgerblue: [30, 144, 255]
|
||||
firebrick: [178, 34, 34]
|
||||
floralwhite: [255, 250, 240]
|
||||
forestgreen: [34, 139, 34]
|
||||
fuchsia: [255, 0, 255]
|
||||
gainsboro: [220, 220, 220]
|
||||
ghostwhite: [248, 248, 255]
|
||||
gold: [255, 215, 0]
|
||||
goldenrod: [218, 165, 32]
|
||||
gray: [128, 128, 128]
|
||||
grey: [128, 128, 128]
|
||||
green: [0, 128, 0]
|
||||
greenyellow: [173, 255, 47]
|
||||
honeydew: [240, 255, 240]
|
||||
hotpink: [255, 105, 180]
|
||||
indianred: [205, 92, 92]
|
||||
indigo: [75, 0, 130]
|
||||
ivory: [255, 255, 240]
|
||||
khaki: [240, 230, 140]
|
||||
lavender: [230, 230, 250]
|
||||
lavenderblush: [255, 240, 245]
|
||||
lawngreen: [124, 252, 0]
|
||||
lemonchiffon: [255, 250, 205]
|
||||
lightblue: [173, 216, 230]
|
||||
lightcoral: [240, 128, 128]
|
||||
lightcyan: [224, 255, 255]
|
||||
lightgoldenrodyellow: [250, 250, 210]
|
||||
lightgray: [211, 211, 211]
|
||||
lightgreen: [144, 238, 144]
|
||||
lightgrey: [211, 211, 211]
|
||||
lightpink: [255, 182, 193]
|
||||
lightsalmon: [255, 160, 122]
|
||||
lightseagreen: [32, 178, 170]
|
||||
lightskyblue: [135, 206, 250]
|
||||
lightslategray: [119, 136, 153]
|
||||
lightslategrey: [119, 136, 153]
|
||||
lightsteelblue: [176, 196, 222]
|
||||
lightyellow: [255, 255, 224]
|
||||
lime: [0, 255, 0]
|
||||
limegreen: [50, 205, 50]
|
||||
linen: [250, 240, 230]
|
||||
magenta: [255, 0, 255]
|
||||
maroon: [128, 0, 0]
|
||||
mediumaquamarine: [102, 205, 170]
|
||||
mediumblue: [0, 0, 205]
|
||||
mediumorchid: [186, 85, 211]
|
||||
mediumpurple: [147, 112, 219]
|
||||
mediumseagreen: [60, 179, 113]
|
||||
mediumslateblue: [123, 104, 238]
|
||||
mediumspringgreen: [0, 250, 154]
|
||||
mediumturquoise: [72, 209, 204]
|
||||
mediumvioletred: [199, 21, 133]
|
||||
midnightblue: [25, 25, 112]
|
||||
mintcream: [245, 255, 250]
|
||||
mistyrose: [255, 228, 225]
|
||||
moccasin: [255, 228, 181]
|
||||
navajowhite: [255, 222, 173]
|
||||
navy: [0, 0, 128]
|
||||
oldlace: [253, 245, 230]
|
||||
olive: [128, 128, 0]
|
||||
olivedrab: [107, 142, 35]
|
||||
orange: [255, 165, 0]
|
||||
orangered: [255, 69, 0]
|
||||
orchid: [218, 112, 214]
|
||||
palegoldenrod: [238, 232, 170]
|
||||
palegreen: [152, 251, 152]
|
||||
paleturquoise: [175, 238, 238]
|
||||
palevioletred: [219, 112, 147]
|
||||
papayawhip: [255, 239, 213]
|
||||
peachpuff: [255, 218, 185]
|
||||
peru: [205, 133, 63]
|
||||
pink: [255, 192, 203]
|
||||
plum: [221, 160, 221]
|
||||
powderblue: [176, 224, 230]
|
||||
purple: [128, 0, 128]
|
||||
red: [255, 0, 0]
|
||||
rosybrown: [188, 143, 143]
|
||||
royalblue: [65, 105, 225]
|
||||
saddlebrown: [139, 69, 19]
|
||||
salmon: [250, 128, 114]
|
||||
sandybrown: [244, 164, 96]
|
||||
seagreen: [46, 139, 87]
|
||||
seashell: [255, 245, 238]
|
||||
sienna: [160, 82, 45]
|
||||
silver: [192, 192, 192]
|
||||
skyblue: [135, 206, 235]
|
||||
slateblue: [106, 90, 205]
|
||||
slategray: [112, 128, 144]
|
||||
slategrey: [112, 128, 144]
|
||||
snow: [255, 250, 250]
|
||||
springgreen: [0, 255, 127]
|
||||
steelblue: [70, 130, 180]
|
||||
tan: [210, 180, 140]
|
||||
teal: [0, 128, 128]
|
||||
thistle: [216, 191, 216]
|
||||
tomato: [255, 99, 71]
|
||||
turquoise: [64, 224, 208]
|
||||
violet: [238, 130, 238]
|
||||
wheat: [245, 222, 179]
|
||||
white: [255, 255, 255]
|
||||
whitesmoke: [245, 245, 245]
|
||||
yellow: [255, 255, 0]
|
||||
yellowgreen: [154, 205, 50]
|
@ -0,0 +1,66 @@
|
||||
PDFFont = require '../font'
|
||||
|
||||
module.exports =
|
||||
initFonts: ->
|
||||
# Lookup table for embedded fonts
|
||||
@_fontFamilies = {}
|
||||
@_fontCount = 0
|
||||
|
||||
# Font state
|
||||
@_fontSize = 12
|
||||
@_font = null
|
||||
|
||||
@_registeredFonts = {}
|
||||
|
||||
# Set the default font
|
||||
@font 'Helvetica'
|
||||
|
||||
font: (src, family, size) ->
|
||||
if typeof family is 'number'
|
||||
size = family
|
||||
family = null
|
||||
|
||||
# check registered fonts if src is a string
|
||||
if typeof src is 'string' and @_registeredFonts[src]
|
||||
cacheKey = src
|
||||
{src, family} = @_registeredFonts[src]
|
||||
else
|
||||
cacheKey = family or src
|
||||
cacheKey = null unless typeof cacheKey is 'string'
|
||||
|
||||
@fontSize size if size?
|
||||
|
||||
# fast path: check if the font is already in the PDF
|
||||
if font = @_fontFamilies[cacheKey]
|
||||
@_font = font
|
||||
return this
|
||||
|
||||
# load the font
|
||||
id = 'F' + (++@_fontCount)
|
||||
@_font = PDFFont.open(this, src, family, id)
|
||||
|
||||
# check for existing font familes with the same name already in the PDF
|
||||
# useful if the font was passed as a buffer
|
||||
if font = @_fontFamilies[@_font.name]
|
||||
@_font = font
|
||||
return this
|
||||
|
||||
# save the font for reuse later
|
||||
if cacheKey
|
||||
@_fontFamilies[cacheKey] = @_font
|
||||
|
||||
@_fontFamilies[@_font.name] = @_font
|
||||
return this
|
||||
|
||||
fontSize: (@_fontSize) ->
|
||||
return this
|
||||
|
||||
currentLineHeight: (includeGap = false) ->
|
||||
@_font.lineHeight @_fontSize, includeGap
|
||||
|
||||
registerFont: (name, src, family) ->
|
||||
@_registeredFonts[name] =
|
||||
src: src
|
||||
family: family
|
||||
|
||||
return this
|
@ -0,0 +1,99 @@
|
||||
PDFImage = require '../image'
|
||||
|
||||
module.exports =
|
||||
initImages: ->
|
||||
@_imageRegistry = {}
|
||||
@_imageCount = 0
|
||||
|
||||
image: (src, x, y, options = {}) ->
|
||||
if typeof x is 'object'
|
||||
options = x
|
||||
x = null
|
||||
|
||||
x = x ? options.x ? @x
|
||||
y = y ? options.y ? @y
|
||||
|
||||
if typeof src is 'string'
|
||||
image = @_imageRegistry[src]
|
||||
|
||||
if not image
|
||||
if src.width and src.height
|
||||
image = src
|
||||
else
|
||||
image = @openImage src
|
||||
|
||||
unless image.obj
|
||||
image.embed this
|
||||
|
||||
@page.xobjects[image.label] ?= image.obj
|
||||
|
||||
w = options.width or image.width
|
||||
h = options.height or image.height
|
||||
|
||||
if options.width and not options.height
|
||||
wp = w / image.width
|
||||
w = image.width * wp
|
||||
h = image.height * wp
|
||||
|
||||
else if options.height and not options.width
|
||||
hp = h / image.height
|
||||
w = image.width * hp
|
||||
h = image.height * hp
|
||||
|
||||
else if options.scale
|
||||
w = image.width * options.scale
|
||||
h = image.height * options.scale
|
||||
|
||||
else if options.fit
|
||||
[bw, bh] = options.fit
|
||||
bp = bw / bh
|
||||
ip = image.width / image.height
|
||||
if ip > bp
|
||||
w = bw
|
||||
h = bw / ip
|
||||
else
|
||||
h = bh
|
||||
w = bh * ip
|
||||
|
||||
else if options.cover
|
||||
[bw, bh] = options.cover
|
||||
bp = bw / bh
|
||||
ip = image.width / image.height
|
||||
if ip > bp
|
||||
h = bh
|
||||
w = bh * ip
|
||||
else
|
||||
w = bw
|
||||
h = bw / ip
|
||||
|
||||
if options.fit or options.cover
|
||||
if options.align is 'center'
|
||||
x = x + bw / 2 - w / 2
|
||||
else if options.align is 'right'
|
||||
x = x + bw - w
|
||||
|
||||
if options.valign is 'center'
|
||||
y = y + bh / 2 - h / 2
|
||||
else if options.valign is 'bottom'
|
||||
y = y + bh - h
|
||||
|
||||
# Set the current y position to below the image if it is in the document flow
|
||||
@y += h if @y is y
|
||||
|
||||
@save()
|
||||
@transform w, 0, 0, -h, x, y + h
|
||||
@addContent "/#{image.label} Do"
|
||||
@restore()
|
||||
|
||||
return this
|
||||
|
||||
openImage: (src) ->
|
||||
if typeof src is 'string'
|
||||
image = @_imageRegistry[src]
|
||||
|
||||
if not image
|
||||
image = PDFImage.open src, 'I' + (++@_imageCount)
|
||||
if typeof src is 'string'
|
||||
@_imageRegistry[src] = image
|
||||
|
||||
return image
|
@ -0,0 +1,313 @@
|
||||
LineWrapper = require '../line_wrapper'
|
||||
{number} = require '../object'
|
||||
|
||||
module.exports =
|
||||
initText: ->
|
||||
# Current coordinates
|
||||
@x = 0
|
||||
@y = 0
|
||||
@_lineGap = 0
|
||||
|
||||
lineGap: (@_lineGap) ->
|
||||
return this
|
||||
|
||||
moveDown: (lines = 1) ->
|
||||
@y += @currentLineHeight(true) * lines + @_lineGap
|
||||
return this
|
||||
|
||||
moveUp: (lines = 1) ->
|
||||
@y -= @currentLineHeight(true) * lines + @_lineGap
|
||||
return this
|
||||
|
||||
_text: (text, x, y, options, lineCallback) ->
|
||||
options = @_initOptions(x, y, options)
|
||||
|
||||
# Convert text to a string
|
||||
text = '' + text
|
||||
|
||||
# if the wordSpacing option is specified, remove multiple consecutive spaces
|
||||
if options.wordSpacing
|
||||
text = text.replace(/\s{2,}/g, ' ')
|
||||
|
||||
# word wrapping
|
||||
if options.width
|
||||
wrapper = @_wrapper
|
||||
unless wrapper
|
||||
wrapper = new LineWrapper(this, options)
|
||||
wrapper.on 'line', lineCallback
|
||||
|
||||
@_wrapper = if options.continued then wrapper else null
|
||||
@_textOptions = if options.continued then options else null
|
||||
wrapper.wrap text, options
|
||||
|
||||
# render paragraphs as single lines
|
||||
else
|
||||
lineCallback line, options for line in text.split '\n'
|
||||
|
||||
return this
|
||||
|
||||
text: (text, x, y, options) ->
|
||||
@_text text, x, y, options, @_line.bind(this)
|
||||
|
||||
widthOfString: (string, options = {}) ->
|
||||
@_font.widthOfString(string, @_fontSize, options.features) + (options.characterSpacing or 0) * (string.length - 1)
|
||||
|
||||
heightOfString: (text, options = {}) ->
|
||||
{x,y} = this
|
||||
|
||||
options = @_initOptions(options)
|
||||
options.height = Infinity # don't break pages
|
||||
|
||||
lineGap = options.lineGap or @_lineGap or 0
|
||||
@_text text, @x, @y, options, (line, options) =>
|
||||
@y += @currentLineHeight(true) + lineGap
|
||||
|
||||
height = @y - y
|
||||
@x = x
|
||||
@y = y
|
||||
|
||||
return height
|
||||
|
||||
list: (list, x, y, options, wrapper) ->
|
||||
options = @_initOptions(x, y, options)
|
||||
|
||||
midLine = Math.round (@_font.ascender / 1000 * @_fontSize) / 2
|
||||
r = options.bulletRadius or Math.round (@_font.ascender / 1000 * @_fontSize) / 3
|
||||
indent = options.textIndent or r * 5
|
||||
itemIndent = options.bulletIndent or r * 8
|
||||
|
||||
level = 1
|
||||
items = []
|
||||
levels = []
|
||||
|
||||
flatten = (list) ->
|
||||
for item, i in list
|
||||
if Array.isArray(item)
|
||||
level++
|
||||
flatten(item)
|
||||
level--
|
||||
else
|
||||
items.push(item)
|
||||
levels.push(level)
|
||||
|
||||
flatten(list)
|
||||
|
||||
wrapper = new LineWrapper(this, options)
|
||||
wrapper.on 'line', @_line.bind(this)
|
||||
|
||||
level = 1
|
||||
i = 0
|
||||
wrapper.on 'firstLine', =>
|
||||
if (l = levels[i++]) isnt level
|
||||
diff = itemIndent * (l - level)
|
||||
@x += diff
|
||||
wrapper.lineWidth -= diff
|
||||
level = l
|
||||
|
||||
@circle @x - indent + r, @y + midLine, r
|
||||
@fill()
|
||||
|
||||
wrapper.on 'sectionStart', =>
|
||||
pos = indent + itemIndent * (level - 1)
|
||||
@x += pos
|
||||
wrapper.lineWidth -= pos
|
||||
|
||||
wrapper.on 'sectionEnd', =>
|
||||
pos = indent + itemIndent * (level - 1)
|
||||
@x -= pos
|
||||
wrapper.lineWidth += pos
|
||||
|
||||
wrapper.wrap items.join('\n'), options
|
||||
|
||||
return this
|
||||
|
||||
_initOptions: (x = {}, y, options = {}) ->
|
||||
if typeof x is 'object'
|
||||
options = x
|
||||
x = null
|
||||
|
||||
# clone options object
|
||||
options = do ->
|
||||
opts = {}
|
||||
opts[k] = v for k, v of options
|
||||
return opts
|
||||
|
||||
# extend options with previous values for continued text
|
||||
if @_textOptions
|
||||
for key, val of @_textOptions when key isnt 'continued'
|
||||
options[key] ?= val
|
||||
|
||||
# Update the current position
|
||||
if x?
|
||||
@x = x
|
||||
if y?
|
||||
@y = y
|
||||
|
||||
# wrap to margins if no x or y position passed
|
||||
unless options.lineBreak is false
|
||||
margins = @page.margins
|
||||
options.width ?= @page.width - @x - margins.right
|
||||
|
||||
options.columns ||= 0
|
||||
options.columnGap ?= 18 # 1/4 inch
|
||||
|
||||
return options
|
||||
|
||||
_line: (text, options = {}, wrapper) ->
|
||||
@_fragment text, @x, @y, options
|
||||
lineGap = options.lineGap or @_lineGap or 0
|
||||
|
||||
if not wrapper
|
||||
@x += @widthOfString text
|
||||
else
|
||||
@y += @currentLineHeight(true) + lineGap
|
||||
|
||||
_fragment: (text, x, y, options) ->
|
||||
text = ('' + text).replace(/\n/g, '')
|
||||
return if text.length is 0
|
||||
|
||||
# handle options
|
||||
align = options.align or 'left'
|
||||
wordSpacing = options.wordSpacing or 0
|
||||
characterSpacing = options.characterSpacing or 0
|
||||
|
||||
# text alignments
|
||||
if options.width
|
||||
switch align
|
||||
when 'right'
|
||||
textWidth = @widthOfString text.replace(/\s+$/, ''), options
|
||||
x += options.lineWidth - textWidth
|
||||
|
||||
when 'center'
|
||||
x += options.lineWidth / 2 - options.textWidth / 2
|
||||
|
||||
when 'justify'
|
||||
# calculate the word spacing value
|
||||
words = text.trim().split(/\s+/)
|
||||
textWidth = @widthOfString(text.replace(/\s+/g, ''), options)
|
||||
spaceWidth = @widthOfString(' ') + characterSpacing
|
||||
wordSpacing = Math.max 0, (options.lineWidth - textWidth) / Math.max(1, words.length - 1) - spaceWidth
|
||||
|
||||
# calculate the actual rendered width of the string after word and character spacing
|
||||
renderedWidth = options.textWidth + (wordSpacing * (options.wordCount - 1)) + (characterSpacing * (text.length - 1))
|
||||
|
||||
# create link annotations if the link option is given
|
||||
if options.link
|
||||
@link x, y, renderedWidth, @currentLineHeight(), options.link
|
||||
|
||||
# create underline or strikethrough line
|
||||
if options.underline or options.strike
|
||||
@save()
|
||||
@strokeColor @_fillColor... unless options.stroke
|
||||
|
||||
lineWidth = if @_fontSize < 10 then 0.5 else Math.floor(@_fontSize / 10)
|
||||
@lineWidth lineWidth
|
||||
|
||||
d = if options.underline then 1 else 2
|
||||
lineY = y + @currentLineHeight() / d
|
||||
lineY -= lineWidth if options.underline
|
||||
|
||||
@moveTo x, lineY
|
||||
@lineTo x + renderedWidth, lineY
|
||||
@stroke()
|
||||
@restore()
|
||||
|
||||
# flip coordinate system
|
||||
@save()
|
||||
@transform 1, 0, 0, -1, 0, @page.height
|
||||
y = @page.height - y - (@_font.ascender / 1000 * @_fontSize)
|
||||
|
||||
# add current font to page if necessary
|
||||
@page.fonts[@_font.id] ?= @_font.ref()
|
||||
|
||||
# begin the text object
|
||||
@addContent "BT"
|
||||
|
||||
# text position
|
||||
@addContent "1 0 0 1 #{number(x)} #{number(y)} Tm"
|
||||
|
||||
# font and font size
|
||||
@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 "#{number(characterSpacing)} Tc" if characterSpacing
|
||||
|
||||
# Add the actual text
|
||||
# If we have a word spacing value, we need to encode each word separately
|
||||
# since the normal Tw operator only works on character code 32, which isn't
|
||||
# used for embedded fonts.
|
||||
if wordSpacing
|
||||
words = text.trim().split(/\s+/)
|
||||
wordSpacing += @widthOfString(' ') + characterSpacing
|
||||
wordSpacing *= 1000 / @_fontSize
|
||||
|
||||
encoded = []
|
||||
positions = []
|
||||
for word in words
|
||||
[encodedWord, positionsWord] = @_font.encode(word, options.features)
|
||||
encoded.push encodedWord...
|
||||
positions.push positionsWord...
|
||||
|
||||
# add the word spacing to the end of the word
|
||||
positions[positions.length - 1].xAdvance += wordSpacing
|
||||
else
|
||||
[encoded, positions] = @_font.encode(text, options.features)
|
||||
|
||||
scale = @_fontSize / 1000
|
||||
commands = []
|
||||
last = 0
|
||||
hadOffset = no
|
||||
|
||||
# Adds a segment of text to the TJ command buffer
|
||||
addSegment = (cur) =>
|
||||
if last < cur
|
||||
hex = encoded.slice(last, cur).join ''
|
||||
advance = positions[cur - 1].xAdvance - positions[cur - 1].advanceWidth
|
||||
commands.push "<#{hex}> #{number(-advance)}"
|
||||
|
||||
last = cur
|
||||
|
||||
# Flushes the current TJ commands to the output stream
|
||||
flush = (i) =>
|
||||
addSegment i
|
||||
|
||||
if commands.length > 0
|
||||
@addContent "[#{commands.join ' '}] TJ"
|
||||
commands.length = 0
|
||||
|
||||
for pos, i in positions
|
||||
# If we have an x or y offset, we have to break out of the current TJ command
|
||||
# so we can move the text position.
|
||||
if pos.xOffset or pos.yOffset
|
||||
# Flush the current buffer
|
||||
flush i
|
||||
|
||||
# Move the text position and flush just the current character
|
||||
@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 #{number(x)} #{number(y)} Tm"
|
||||
hadOffset = no
|
||||
|
||||
# Group segments that don't have any advance adjustments
|
||||
unless pos.xAdvance - pos.advanceWidth is 0
|
||||
addSegment i + 1
|
||||
|
||||
x += pos.xAdvance * scale
|
||||
|
||||
# Flush any remaining commands
|
||||
flush i
|
||||
|
||||
# end the text object
|
||||
@addContent "ET"
|
||||
|
||||
# restore flipped coordinate system
|
||||
@restore()
|
@ -0,0 +1,204 @@
|
||||
SVGPath = require '../path'
|
||||
{number} = require '../object'
|
||||
|
||||
# This constant is used to approximate a symmetrical arc using a cubic
|
||||
# Bezier curve.
|
||||
KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0)
|
||||
module.exports =
|
||||
initVector: ->
|
||||
@_ctm = [1, 0, 0, 1, 0, 0] # current transformation matrix
|
||||
@_ctmStack = []
|
||||
|
||||
save: ->
|
||||
@_ctmStack.push @_ctm.slice()
|
||||
# TODO: save/restore colorspace and styles so not setting it unnessesarily all the time?
|
||||
@addContent 'q'
|
||||
|
||||
restore: ->
|
||||
@_ctm = @_ctmStack.pop() or [1, 0, 0, 1, 0, 0]
|
||||
@addContent 'Q'
|
||||
|
||||
closePath: ->
|
||||
@addContent 'h'
|
||||
|
||||
lineWidth: (w) ->
|
||||
@addContent "#{number(w)} w"
|
||||
|
||||
_CAP_STYLES:
|
||||
BUTT: 0
|
||||
ROUND: 1
|
||||
SQUARE: 2
|
||||
|
||||
lineCap: (c) ->
|
||||
c = @_CAP_STYLES[c.toUpperCase()] if typeof c is 'string'
|
||||
@addContent "#{c} J"
|
||||
|
||||
_JOIN_STYLES:
|
||||
MITER: 0
|
||||
ROUND: 1
|
||||
BEVEL: 2
|
||||
|
||||
lineJoin: (j) ->
|
||||
j = @_JOIN_STYLES[j.toUpperCase()] if typeof j is 'string'
|
||||
@addContent "#{j} j"
|
||||
|
||||
miterLimit: (m) ->
|
||||
@addContent "#{number(m)} M"
|
||||
|
||||
dash: (length, options = {}) ->
|
||||
return this unless length?
|
||||
if Array.isArray length
|
||||
length = (number(v) for v in length).join(' ')
|
||||
phase = options.phase or 0
|
||||
@addContent "[#{length}] #{number(phase)} d"
|
||||
else
|
||||
space = options.space ? length
|
||||
phase = options.phase or 0
|
||||
@addContent "[#{number(length)} #{number(space)}] #{number(phase)} d"
|
||||
|
||||
undash: ->
|
||||
@addContent "[] 0 d"
|
||||
|
||||
moveTo: (x, y) ->
|
||||
@addContent "#{number(x)} #{number(y)} m"
|
||||
|
||||
lineTo: (x, y) ->
|
||||
@addContent "#{number(x)} #{number(y)} l"
|
||||
|
||||
bezierCurveTo: (cp1x, cp1y, cp2x, cp2y, x, y) ->
|
||||
@addContent "#{number(cp1x)} #{number(cp1y)} #{number(cp2x)} #{number(cp2y)} #{number(x)} #{number(y)} c"
|
||||
|
||||
quadraticCurveTo: (cpx, cpy, x, y) ->
|
||||
@addContent "#{number(cpx)} #{number(cpy)} #{number(x)} #{number(y)} v"
|
||||
|
||||
rect: (x, y, w, h) ->
|
||||
@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)
|
||||
|
||||
# amount to inset control points from corners (see `ellipse`)
|
||||
c = r * (1.0 - KAPPA)
|
||||
|
||||
@moveTo x + r, y
|
||||
@lineTo x + w - r, y
|
||||
@bezierCurveTo x + w - c, y, x + w, y + c, x + w, y + r
|
||||
@lineTo x + w, y + h - r
|
||||
@bezierCurveTo x + w, y + h - c, x + w - c, y + h, x + w - r, y + h
|
||||
@lineTo x + r, y + h
|
||||
@bezierCurveTo x + c, y + h, x, y + h - c, x, y + h - r
|
||||
@lineTo x, y + r
|
||||
@bezierCurveTo x, y + c, x + c, y, x + r, y
|
||||
@closePath()
|
||||
|
||||
ellipse: (x, y, r1, r2 = r1) ->
|
||||
# based on http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas/2173084#2173084
|
||||
x -= r1
|
||||
y -= r2
|
||||
ox = r1 * KAPPA
|
||||
oy = r2 * KAPPA
|
||||
xe = x + r1 * 2
|
||||
ye = y + r2 * 2
|
||||
xm = x + r1
|
||||
ym = y + r2
|
||||
|
||||
@moveTo(x, ym)
|
||||
@bezierCurveTo(x, ym - oy, xm - ox, y, xm, y)
|
||||
@bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym)
|
||||
@bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye)
|
||||
@bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym)
|
||||
@closePath()
|
||||
|
||||
circle: (x, y, radius) ->
|
||||
@ellipse x, y, radius
|
||||
|
||||
polygon: (points...) ->
|
||||
@moveTo points.shift()...
|
||||
@lineTo point... for point in points
|
||||
@closePath()
|
||||
|
||||
path: (path) ->
|
||||
SVGPath.apply this, path
|
||||
return this
|
||||
|
||||
_windingRule: (rule) ->
|
||||
if /even-?odd/.test(rule)
|
||||
return '*'
|
||||
|
||||
return ''
|
||||
|
||||
fill: (color, rule) ->
|
||||
if /(even-?odd)|(non-?zero)/.test(color)
|
||||
rule = color
|
||||
color = null
|
||||
|
||||
@fillColor color if color
|
||||
@addContent 'f' + @_windingRule(rule)
|
||||
|
||||
stroke: (color) ->
|
||||
@strokeColor color if color
|
||||
@addContent 'S'
|
||||
|
||||
fillAndStroke: (fillColor, strokeColor = fillColor, rule) ->
|
||||
isFillRule = /(even-?odd)|(non-?zero)/
|
||||
if isFillRule.test(fillColor)
|
||||
rule = fillColor
|
||||
fillColor = null
|
||||
|
||||
if isFillRule.test(strokeColor)
|
||||
rule = strokeColor
|
||||
strokeColor = fillColor
|
||||
|
||||
if fillColor
|
||||
@fillColor fillColor
|
||||
@strokeColor strokeColor
|
||||
|
||||
@addContent 'B' + @_windingRule(rule)
|
||||
|
||||
clip: (rule) ->
|
||||
@addContent 'W' + @_windingRule(rule) + ' n'
|
||||
|
||||
transform: (m11, m12, m21, m22, dx, dy) ->
|
||||
# keep track of the current transformation matrix
|
||||
m = @_ctm
|
||||
[m0, m1, m2, m3, m4, m5] = m
|
||||
m[0] = m0 * m11 + m2 * m12
|
||||
m[1] = m1 * m11 + m3 * m12
|
||||
m[2] = m0 * m21 + m2 * m22
|
||||
m[3] = m1 * m21 + m3 * m22
|
||||
m[4] = m0 * dx + m2 * dy + m4
|
||||
m[5] = m1 * dx + m3 * dy + m5
|
||||
|
||||
values = (number(v) for v in [m11, m12, m21, m22, dx, dy]).join(' ')
|
||||
@addContent "#{values} cm"
|
||||
|
||||
translate: (x, y) ->
|
||||
@transform 1, 0, 0, 1, x, y
|
||||
|
||||
rotate: (angle, options = {}) ->
|
||||
rad = angle * Math.PI / 180
|
||||
cos = Math.cos(rad)
|
||||
sin = Math.sin(rad)
|
||||
x = y = 0
|
||||
|
||||
if options.origin?
|
||||
[x, y] = options.origin
|
||||
x1 = x * cos - y * sin
|
||||
y1 = x * sin + y * cos
|
||||
x -= x1
|
||||
y -= y1
|
||||
|
||||
@transform cos, sin, -sin, cos, x, y
|
||||
|
||||
scale: (xFactor, yFactor = xFactor, options = {}) ->
|
||||
if arguments.length is 2
|
||||
yFactor = xFactor
|
||||
options = yFactor
|
||||
|
||||
x = y = 0
|
||||
if options.origin?
|
||||
[x, y] = options.origin
|
||||
x -= xFactor * x
|
||||
y -= yFactor * y
|
||||
|
||||
@transform xFactor, 0, 0, yFactor, x, y
|
@ -0,0 +1,421 @@
|
||||
0 info it worked if it ends with ok
|
||||
1 verbose cli [ '/usr/local/bin/node',
|
||||
1 verbose cli '/usr/local/bin/npm',
|
||||
1 verbose cli 'unlink',
|
||||
1 verbose cli 'pdfkit' ]
|
||||
2 info using npm@3.10.10
|
||||
3 info using node@v6.10.3
|
||||
4 silly loadCurrentTree Starting
|
||||
5 silly install loadCurrentTree
|
||||
6 silly install readLocalPackageData
|
||||
7 silly install normalizeTree
|
||||
8 silly loadCurrentTree Finishing
|
||||
9 silly loadIdealTree Starting
|
||||
10 silly install loadIdealTree
|
||||
11 silly cloneCurrentTree Starting
|
||||
12 silly install cloneCurrentTreeToIdealTree
|
||||
13 silly cloneCurrentTree Finishing
|
||||
14 silly loadShrinkwrap Starting
|
||||
15 silly install loadShrinkwrap
|
||||
16 silly loadShrinkwrap Finishing
|
||||
17 silly loadAllDepsIntoIdealTree Starting
|
||||
18 silly uninstall loadAllDepsIntoIdealtree
|
||||
19 silly loadAllDepsIntoIdealTree Finishing
|
||||
20 silly loadIdealTree Finishing
|
||||
21 silly currentTree pdfkit@0.8.0
|
||||
21 silly currentTree ├── abbrev@1.1.0
|
||||
21 silly currentTree ├── acorn@4.0.11
|
||||
21 silly currentTree ├── amdefine@1.0.1
|
||||
21 silly currentTree ├── assert@1.1.2
|
||||
21 silly currentTree ├─┬ ast-transform@0.0.0
|
||||
21 silly currentTree │ ├── escodegen@1.2.0
|
||||
21 silly currentTree │ └── esprima@1.0.4
|
||||
21 silly currentTree ├── ast-types@0.7.8
|
||||
21 silly currentTree ├── astw@2.2.0
|
||||
21 silly currentTree ├── async@0.2.10
|
||||
21 silly currentTree ├── babel-runtime@6.23.0
|
||||
21 silly currentTree ├── base64-js@1.2.0
|
||||
21 silly currentTree ├── Base64@0.2.1
|
||||
21 silly currentTree ├── blob-stream@0.1.3
|
||||
21 silly currentTree ├── blob@0.0.4
|
||||
21 silly currentTree ├── brace@0.2.1
|
||||
21 silly currentTree ├─┬ brfs@1.0.2
|
||||
21 silly currentTree │ └── through@2.2.7
|
||||
21 silly currentTree ├── brotli@1.3.2
|
||||
21 silly currentTree ├─┬ browser-pack@2.0.1
|
||||
21 silly currentTree │ └─┬ JSONStream@0.6.4
|
||||
21 silly currentTree │ └── through@2.2.7
|
||||
21 silly currentTree ├─┬ browser-resolve@1.11.2
|
||||
21 silly currentTree │ └── resolve@1.1.7
|
||||
21 silly currentTree ├── browserify-optional@1.0.0
|
||||
21 silly currentTree ├── browserify-zlib@0.1.4
|
||||
21 silly currentTree ├─┬ browserify@3.46.1
|
||||
21 silly currentTree │ ├── browser-resolve@1.2.4
|
||||
21 silly currentTree │ └── deep-equal@0.1.2
|
||||
21 silly currentTree ├─┬ buffer@2.1.13
|
||||
21 silly currentTree │ └── base64-js@0.0.8
|
||||
21 silly currentTree ├── builtins@0.0.7
|
||||
21 silly currentTree ├── callsite@1.0.0
|
||||
21 silly currentTree ├── camelcase@1.2.1
|
||||
21 silly currentTree ├── character-parser@1.2.0
|
||||
21 silly currentTree ├── clone@1.0.2
|
||||
21 silly currentTree ├── codemirror@3.20.0
|
||||
21 silly currentTree ├── coffee-script@1.12.5
|
||||
21 silly currentTree ├─┬ coffeeify@0.6.0
|
||||
21 silly currentTree │ └── coffee-script@1.7.1
|
||||
21 silly currentTree ├── combine-source-map@0.3.0
|
||||
21 silly currentTree ├── commander@2.1.0
|
||||
21 silly currentTree ├── commondir@0.0.1
|
||||
21 silly currentTree ├── concat-stream@1.4.10
|
||||
21 silly currentTree ├── console-browserify@1.0.3
|
||||
21 silly currentTree ├── constantinople@1.0.2
|
||||
21 silly currentTree ├── constants-browserify@0.0.1
|
||||
21 silly currentTree ├── convert-source-map@0.3.5
|
||||
21 silly currentTree ├── core-js@2.4.1
|
||||
21 silly currentTree ├── core-util-is@1.0.2
|
||||
21 silly currentTree ├── crypto-browserify@1.0.9
|
||||
21 silly currentTree ├── css-parse@1.0.4
|
||||
21 silly currentTree ├── css-stringify@1.0.5
|
||||
21 silly currentTree ├── css@1.0.8
|
||||
21 silly currentTree ├── decamelize@1.2.0
|
||||
21 silly currentTree ├── deep-equal@1.0.1
|
||||
21 silly currentTree ├── defined@0.0.0
|
||||
21 silly currentTree ├─┬ deps-sort@0.1.2
|
||||
21 silly currentTree │ └─┬ JSONStream@0.6.4
|
||||
21 silly currentTree │ └── through@2.2.7
|
||||
21 silly currentTree ├─┬ derequire@0.8.0
|
||||
21 silly currentTree │ └── esprima-fb@3001.1.0-dev-harmony-fb
|
||||
21 silly currentTree ├─┬ detective@3.1.0
|
||||
21 silly currentTree │ ├── escodegen@1.1.0
|
||||
21 silly currentTree │ └── esprima-fb@3001.1.0-dev-harmony-fb
|
||||
21 silly currentTree ├── dfa@1.0.0
|
||||
21 silly currentTree ├── domain-browser@1.1.7
|
||||
21 silly currentTree ├── duplexer@0.1.1
|
||||
21 silly currentTree ├── duplexer2@0.0.2
|
||||
21 silly currentTree ├─┬ escodegen@0.0.17
|
||||
21 silly currentTree │ └── estraverse@0.0.4
|
||||
21 silly currentTree ├── escope@0.0.16
|
||||
21 silly currentTree ├── esprima@1.0.4
|
||||
21 silly currentTree ├─┬ esrefactor@0.1.0
|
||||
21 silly currentTree │ └── estraverse@0.0.4
|
||||
21 silly currentTree ├── estraverse@1.5.1
|
||||
21 silly currentTree ├── esutils@1.0.0
|
||||
21 silly currentTree ├── events@1.0.2
|
||||
21 silly currentTree ├─┬ exorcist@0.1.6
|
||||
21 silly currentTree │ └── minimist@0.0.5
|
||||
21 silly currentTree ├── falafel@0.1.6
|
||||
21 silly currentTree ├── fontkit@1.6.0
|
||||
21 silly currentTree ├── glob@3.2.11
|
||||
21 silly currentTree ├── http-browserify@1.3.2
|
||||
21 silly currentTree ├── https-browserify@0.0.1
|
||||
21 silly currentTree ├── iconv-lite@0.4.17
|
||||
21 silly currentTree ├── ieee754@1.1.8
|
||||
21 silly currentTree ├── indexof@0.0.1
|
||||
21 silly currentTree ├── inherits@2.0.3
|
||||
21 silly currentTree ├─┬ inline-source-map@0.3.1
|
||||
21 silly currentTree │ └── source-map@0.3.0
|
||||
21 silly currentTree ├─┬ insert-module-globals@6.0.0
|
||||
21 silly currentTree │ └── process@0.6.0
|
||||
21 silly currentTree ├── is-promise@1.0.1
|
||||
21 silly currentTree ├── isarray@0.0.1
|
||||
21 silly currentTree ├── jade@1.1.5
|
||||
21 silly currentTree ├── jsonparse@0.0.5
|
||||
21 silly currentTree ├── JSONStream@0.7.4
|
||||
21 silly currentTree ├── lexical-scope@1.1.1
|
||||
21 silly currentTree ├─┬ linebreak@0.1.2
|
||||
21 silly currentTree │ └── unicode-trie@0.1.2
|
||||
21 silly currentTree ├── lru-cache@2.7.3
|
||||
21 silly currentTree ├── markdown@0.5.0
|
||||
21 silly currentTree ├── minimatch@0.3.0
|
||||
21 silly currentTree ├── minimist@0.0.10
|
||||
21 silly currentTree ├── mkdirp@0.3.5
|
||||
21 silly currentTree ├─┬ module-deps@2.0.6
|
||||
21 silly currentTree │ ├── browser-resolve@1.2.4
|
||||
21 silly currentTree │ ├── parents@0.0.2
|
||||
21 silly currentTree │ └── stream-combiner@0.1.0
|
||||
21 silly currentTree ├── monocle@1.1.51
|
||||
21 silly currentTree ├── nopt@2.1.2
|
||||
21 silly currentTree ├── object-keys@0.4.0
|
||||
21 silly currentTree ├── optimist@0.3.7
|
||||
21 silly currentTree ├── os-browserify@0.1.2
|
||||
21 silly currentTree ├── pako@0.2.9
|
||||
21 silly currentTree ├── parents@0.0.3
|
||||
21 silly currentTree ├── path-browserify@0.0.0
|
||||
21 silly currentTree ├── path-platform@0.0.1
|
||||
21 silly currentTree ├── png-js@0.1.1
|
||||
21 silly currentTree ├── process@0.7.0
|
||||
21 silly currentTree ├── promise@2.0.0
|
||||
21 silly currentTree ├── punycode@1.2.4
|
||||
21 silly currentTree ├── querystring-es3@0.2.0
|
||||
21 silly currentTree ├── querystring@0.2.0
|
||||
21 silly currentTree ├─┬ readable-stream@1.1.14
|
||||
21 silly currentTree │ └── string_decoder@0.10.31
|
||||
21 silly currentTree ├── readdirp@0.2.5
|
||||
21 silly currentTree ├── regenerator-runtime@0.10.5
|
||||
21 silly currentTree ├── resolve@0.6.3
|
||||
21 silly currentTree ├── restructure@0.5.4
|
||||
21 silly currentTree ├─┬ rfile@1.0.0
|
||||
21 silly currentTree │ └── resolve@0.3.1
|
||||
21 silly currentTree ├─┬ ruglify@1.0.0
|
||||
21 silly currentTree │ └── uglify-js@2.2.5
|
||||
21 silly currentTree ├── shallow-copy@0.0.1
|
||||
21 silly currentTree ├── shell-quote@0.0.1
|
||||
21 silly currentTree ├── sigmund@1.0.1
|
||||
21 silly currentTree ├── source-map@0.1.43
|
||||
21 silly currentTree ├─┬ stream-browserify@0.1.3
|
||||
21 silly currentTree │ └── process@0.5.2
|
||||
21 silly currentTree ├── stream-combiner@0.0.4
|
||||
21 silly currentTree ├── string_decoder@0.0.1
|
||||
21 silly currentTree ├── subarg@0.0.1
|
||||
21 silly currentTree ├─┬ syntax-error@1.1.6
|
||||
21 silly currentTree │ └── acorn@2.7.0
|
||||
21 silly currentTree ├── through@2.3.8
|
||||
21 silly currentTree ├─┬ through2@0.4.2
|
||||
21 silly currentTree │ ├── readable-stream@1.0.34
|
||||
21 silly currentTree │ ├── string_decoder@0.10.31
|
||||
21 silly currentTree │ └── xtend@2.1.2
|
||||
21 silly currentTree ├─┬ timers-browserify@1.0.3
|
||||
21 silly currentTree │ └── process@0.5.2
|
||||
21 silly currentTree ├── tiny-inflate@1.0.2
|
||||
21 silly currentTree ├─┬ transformers@2.1.0
|
||||
21 silly currentTree │ └── uglify-js@2.2.5
|
||||
21 silly currentTree ├── tty-browserify@0.0.0
|
||||
21 silly currentTree ├── typedarray@0.0.6
|
||||
21 silly currentTree ├─┬ uglify-js@2.4.24
|
||||
21 silly currentTree │ └── source-map@0.1.34
|
||||
21 silly currentTree ├── uglify-to-browserify@1.0.2
|
||||
21 silly currentTree ├── umd@2.0.0
|
||||
21 silly currentTree ├── unicode-properties@1.1.0
|
||||
21 silly currentTree ├── unicode-trie@0.3.1
|
||||
21 silly currentTree ├─┬ url@0.10.3
|
||||
21 silly currentTree │ └── punycode@1.3.2
|
||||
21 silly currentTree ├─┬ util@0.10.3
|
||||
21 silly currentTree │ └── inherits@2.0.1
|
||||
21 silly currentTree ├── vm-browserify@0.0.4
|
||||
21 silly currentTree ├── w3c-blob@0.0.1
|
||||
21 silly currentTree ├── window-size@0.1.0
|
||||
21 silly currentTree ├─┬ with@2.0.0
|
||||
21 silly currentTree │ └── uglify-js@2.4.0
|
||||
21 silly currentTree ├── wordwrap@0.0.3
|
||||
21 silly currentTree ├── xtend@3.0.0
|
||||
21 silly currentTree └─┬ yargs@3.5.4
|
||||
21 silly currentTree └── wordwrap@0.0.2
|
||||
22 silly idealTree pdfkit@0.8.0
|
||||
22 silly idealTree ├── abbrev@1.1.0
|
||||
22 silly idealTree ├── acorn@4.0.11
|
||||
22 silly idealTree ├── amdefine@1.0.1
|
||||
22 silly idealTree ├── assert@1.1.2
|
||||
22 silly idealTree ├─┬ ast-transform@0.0.0
|
||||
22 silly idealTree │ ├── escodegen@1.2.0
|
||||
22 silly idealTree │ └── esprima@1.0.4
|
||||
22 silly idealTree ├── ast-types@0.7.8
|
||||
22 silly idealTree ├── astw@2.2.0
|
||||
22 silly idealTree ├── async@0.2.10
|
||||
22 silly idealTree ├── babel-runtime@6.23.0
|
||||
22 silly idealTree ├── base64-js@1.2.0
|
||||
22 silly idealTree ├── Base64@0.2.1
|
||||
22 silly idealTree ├── blob-stream@0.1.3
|
||||
22 silly idealTree ├── blob@0.0.4
|
||||
22 silly idealTree ├── brace@0.2.1
|
||||
22 silly idealTree ├─┬ brfs@1.0.2
|
||||
22 silly idealTree │ └── through@2.2.7
|
||||
22 silly idealTree ├── brotli@1.3.2
|
||||
22 silly idealTree ├─┬ browser-pack@2.0.1
|
||||
22 silly idealTree │ └─┬ JSONStream@0.6.4
|
||||
22 silly idealTree │ └── through@2.2.7
|
||||
22 silly idealTree ├─┬ browser-resolve@1.11.2
|
||||
22 silly idealTree │ └── resolve@1.1.7
|
||||
22 silly idealTree ├── browserify-optional@1.0.0
|
||||
22 silly idealTree ├── browserify-zlib@0.1.4
|
||||
22 silly idealTree ├─┬ browserify@3.46.1
|
||||
22 silly idealTree │ ├── browser-resolve@1.2.4
|
||||
22 silly idealTree │ └── deep-equal@0.1.2
|
||||
22 silly idealTree ├─┬ buffer@2.1.13
|
||||
22 silly idealTree │ └── base64-js@0.0.8
|
||||
22 silly idealTree ├── builtins@0.0.7
|
||||
22 silly idealTree ├── callsite@1.0.0
|
||||
22 silly idealTree ├── camelcase@1.2.1
|
||||
22 silly idealTree ├── character-parser@1.2.0
|
||||
22 silly idealTree ├── clone@1.0.2
|
||||
22 silly idealTree ├── codemirror@3.20.0
|
||||
22 silly idealTree ├── coffee-script@1.12.5
|
||||
22 silly idealTree ├─┬ coffeeify@0.6.0
|
||||
22 silly idealTree │ └── coffee-script@1.7.1
|
||||
22 silly idealTree ├── combine-source-map@0.3.0
|
||||
22 silly idealTree ├── commander@2.1.0
|
||||
22 silly idealTree ├── commondir@0.0.1
|
||||
22 silly idealTree ├── concat-stream@1.4.10
|
||||
22 silly idealTree ├── console-browserify@1.0.3
|
||||
22 silly idealTree ├── constantinople@1.0.2
|
||||
22 silly idealTree ├── constants-browserify@0.0.1
|
||||
22 silly idealTree ├── convert-source-map@0.3.5
|
||||
22 silly idealTree ├── core-js@2.4.1
|
||||
22 silly idealTree ├── core-util-is@1.0.2
|
||||
22 silly idealTree ├── crypto-browserify@1.0.9
|
||||
22 silly idealTree ├── css-parse@1.0.4
|
||||
22 silly idealTree ├── css-stringify@1.0.5
|
||||
22 silly idealTree ├── css@1.0.8
|
||||
22 silly idealTree ├── decamelize@1.2.0
|
||||
22 silly idealTree ├── deep-equal@1.0.1
|
||||
22 silly idealTree ├── defined@0.0.0
|
||||
22 silly idealTree ├─┬ deps-sort@0.1.2
|
||||
22 silly idealTree │ └─┬ JSONStream@0.6.4
|
||||
22 silly idealTree │ └── through@2.2.7
|
||||
22 silly idealTree ├─┬ derequire@0.8.0
|
||||
22 silly idealTree │ └── esprima-fb@3001.1.0-dev-harmony-fb
|
||||
22 silly idealTree ├─┬ detective@3.1.0
|
||||
22 silly idealTree │ ├── escodegen@1.1.0
|
||||
22 silly idealTree │ └── esprima-fb@3001.1.0-dev-harmony-fb
|
||||
22 silly idealTree ├── dfa@1.0.0
|
||||
22 silly idealTree ├── domain-browser@1.1.7
|
||||
22 silly idealTree ├── duplexer@0.1.1
|
||||
22 silly idealTree ├── duplexer2@0.0.2
|
||||
22 silly idealTree ├─┬ escodegen@0.0.17
|
||||
22 silly idealTree │ └── estraverse@0.0.4
|
||||
22 silly idealTree ├── escope@0.0.16
|
||||
22 silly idealTree ├── esprima@1.0.4
|
||||
22 silly idealTree ├─┬ esrefactor@0.1.0
|
||||
22 silly idealTree │ └── estraverse@0.0.4
|
||||
22 silly idealTree ├── estraverse@1.5.1
|
||||
22 silly idealTree ├── esutils@1.0.0
|
||||
22 silly idealTree ├── events@1.0.2
|
||||
22 silly idealTree ├─┬ exorcist@0.1.6
|
||||
22 silly idealTree │ └── minimist@0.0.5
|
||||
22 silly idealTree ├── falafel@0.1.6
|
||||
22 silly idealTree ├── fontkit@1.6.0
|
||||
22 silly idealTree ├── glob@3.2.11
|
||||
22 silly idealTree ├── http-browserify@1.3.2
|
||||
22 silly idealTree ├── https-browserify@0.0.1
|
||||
22 silly idealTree ├── iconv-lite@0.4.17
|
||||
22 silly idealTree ├── ieee754@1.1.8
|
||||
22 silly idealTree ├── indexof@0.0.1
|
||||
22 silly idealTree ├── inherits@2.0.3
|
||||
22 silly idealTree ├─┬ inline-source-map@0.3.1
|
||||
22 silly idealTree │ └── source-map@0.3.0
|
||||
22 silly idealTree ├─┬ insert-module-globals@6.0.0
|
||||
22 silly idealTree │ └── process@0.6.0
|
||||
22 silly idealTree ├── is-promise@1.0.1
|
||||
22 silly idealTree ├── isarray@0.0.1
|
||||
22 silly idealTree ├── jade@1.1.5
|
||||
22 silly idealTree ├── jsonparse@0.0.5
|
||||
22 silly idealTree ├── JSONStream@0.7.4
|
||||
22 silly idealTree ├── lexical-scope@1.1.1
|
||||
22 silly idealTree ├─┬ linebreak@0.1.2
|
||||
22 silly idealTree │ └── unicode-trie@0.1.2
|
||||
22 silly idealTree ├── lru-cache@2.7.3
|
||||
22 silly idealTree ├── markdown@0.5.0
|
||||
22 silly idealTree ├── minimatch@0.3.0
|
||||
22 silly idealTree ├── minimist@0.0.10
|
||||
22 silly idealTree ├── mkdirp@0.3.5
|
||||
22 silly idealTree ├─┬ module-deps@2.0.6
|
||||
22 silly idealTree │ ├── browser-resolve@1.2.4
|
||||
22 silly idealTree │ ├── parents@0.0.2
|
||||
22 silly idealTree │ └── stream-combiner@0.1.0
|
||||
22 silly idealTree ├── monocle@1.1.51
|
||||
22 silly idealTree ├── nopt@2.1.2
|
||||
22 silly idealTree ├── object-keys@0.4.0
|
||||
22 silly idealTree ├── optimist@0.3.7
|
||||
22 silly idealTree ├── os-browserify@0.1.2
|
||||
22 silly idealTree ├── pako@0.2.9
|
||||
22 silly idealTree ├── parents@0.0.3
|
||||
22 silly idealTree ├── path-browserify@0.0.0
|
||||
22 silly idealTree ├── path-platform@0.0.1
|
||||
22 silly idealTree ├── png-js@0.1.1
|
||||
22 silly idealTree ├── process@0.7.0
|
||||
22 silly idealTree ├── promise@2.0.0
|
||||
22 silly idealTree ├── punycode@1.2.4
|
||||
22 silly idealTree ├── querystring-es3@0.2.0
|
||||
22 silly idealTree ├── querystring@0.2.0
|
||||
22 silly idealTree ├─┬ readable-stream@1.1.14
|
||||
22 silly idealTree │ └── string_decoder@0.10.31
|
||||
22 silly idealTree ├── readdirp@0.2.5
|
||||
22 silly idealTree ├── regenerator-runtime@0.10.5
|
||||
22 silly idealTree ├── resolve@0.6.3
|
||||
22 silly idealTree ├── restructure@0.5.4
|
||||
22 silly idealTree ├─┬ rfile@1.0.0
|
||||
22 silly idealTree │ └── resolve@0.3.1
|
||||
22 silly idealTree ├─┬ ruglify@1.0.0
|
||||
22 silly idealTree │ └── uglify-js@2.2.5
|
||||
22 silly idealTree ├── shallow-copy@0.0.1
|
||||
22 silly idealTree ├── shell-quote@0.0.1
|
||||
22 silly idealTree ├── sigmund@1.0.1
|
||||
22 silly idealTree ├── source-map@0.1.43
|
||||
22 silly idealTree ├─┬ stream-browserify@0.1.3
|
||||
22 silly idealTree │ └── process@0.5.2
|
||||
22 silly idealTree ├── stream-combiner@0.0.4
|
||||
22 silly idealTree ├── string_decoder@0.0.1
|
||||
22 silly idealTree ├── subarg@0.0.1
|
||||
22 silly idealTree ├─┬ syntax-error@1.1.6
|
||||
22 silly idealTree │ └── acorn@2.7.0
|
||||
22 silly idealTree ├── through@2.3.8
|
||||
22 silly idealTree ├─┬ through2@0.4.2
|
||||
22 silly idealTree │ ├── readable-stream@1.0.34
|
||||
22 silly idealTree │ ├── string_decoder@0.10.31
|
||||
22 silly idealTree │ └── xtend@2.1.2
|
||||
22 silly idealTree ├─┬ timers-browserify@1.0.3
|
||||
22 silly idealTree │ └── process@0.5.2
|
||||
22 silly idealTree ├── tiny-inflate@1.0.2
|
||||
22 silly idealTree ├─┬ transformers@2.1.0
|
||||
22 silly idealTree │ └── uglify-js@2.2.5
|
||||
22 silly idealTree ├── tty-browserify@0.0.0
|
||||
22 silly idealTree ├── typedarray@0.0.6
|
||||
22 silly idealTree ├─┬ uglify-js@2.4.24
|
||||
22 silly idealTree │ └── source-map@0.1.34
|
||||
22 silly idealTree ├── uglify-to-browserify@1.0.2
|
||||
22 silly idealTree ├── umd@2.0.0
|
||||
22 silly idealTree ├── unicode-properties@1.1.0
|
||||
22 silly idealTree ├── unicode-trie@0.3.1
|
||||
22 silly idealTree ├─┬ url@0.10.3
|
||||
22 silly idealTree │ └── punycode@1.3.2
|
||||
22 silly idealTree ├─┬ util@0.10.3
|
||||
22 silly idealTree │ └── inherits@2.0.1
|
||||
22 silly idealTree ├── vm-browserify@0.0.4
|
||||
22 silly idealTree ├── w3c-blob@0.0.1
|
||||
22 silly idealTree ├── window-size@0.1.0
|
||||
22 silly idealTree ├─┬ with@2.0.0
|
||||
22 silly idealTree │ └── uglify-js@2.4.0
|
||||
22 silly idealTree ├── wordwrap@0.0.3
|
||||
22 silly idealTree ├── xtend@3.0.0
|
||||
22 silly idealTree └─┬ yargs@3.5.4
|
||||
22 silly idealTree └── wordwrap@0.0.2
|
||||
23 silly generateActionsToTake Starting
|
||||
24 silly install generateActionsToTake
|
||||
25 silly generateActionsToTake Finishing
|
||||
26 silly diffTrees action count 0
|
||||
27 silly decomposeActions action count 0
|
||||
28 silly runTopLevelLifecycles Starting
|
||||
29 silly executeActions Starting
|
||||
30 silly install executeActions
|
||||
31 silly doSerial global-install 0
|
||||
32 silly doParallel fetch 0
|
||||
33 verbose correctMkdir /Users/MB/.npm/_locks correctMkdir not in flight; initializing
|
||||
34 verbose lock using /Users/MB/.npm/_locks/staging-73efde40ed96aa4a.lock for /Users/MB/git/pitfall/pdfkit/node_modules/.staging
|
||||
35 verbose unlock done using /Users/MB/.npm/_locks/staging-73efde40ed96aa4a.lock for /Users/MB/git/pitfall/pdfkit/node_modules/.staging
|
||||
36 silly rollbackFailedOptional Starting
|
||||
37 silly rollbackFailedOptional Finishing
|
||||
38 silly runTopLevelLifecycles Finishing
|
||||
39 silly install printInstalled
|
||||
40 warn pdfkit@0.8.0 No license field.
|
||||
41 verbose If you need help, you may report this error at:
|
||||
41 verbose <https://github.com/npm/npm/issues>
|
||||
42 verbose stack Error: EACCES: permission denied, mkdir '/Users/MB/git/pitfall/pdfkit/node_modules/.staging'
|
||||
42 verbose stack at Error (native)
|
||||
43 verbose cwd /Users/MB/git/pitfall/pdfkit/lib
|
||||
44 error Darwin 16.5.0
|
||||
45 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "unlink" "pdfkit"
|
||||
46 error node v6.10.3
|
||||
47 error npm v3.10.10
|
||||
48 error path /Users/MB/git/pitfall/pdfkit/node_modules/.staging
|
||||
49 error code EACCES
|
||||
50 error errno -13
|
||||
51 error syscall mkdir
|
||||
52 error Error: EACCES: permission denied, mkdir '/Users/MB/git/pitfall/pdfkit/node_modules/.staging'
|
||||
52 error at Error (native)
|
||||
52 error { Error: EACCES: permission denied, mkdir '/Users/MB/git/pitfall/pdfkit/node_modules/.staging'
|
||||
52 error at Error (native)
|
||||
52 error errno: -13,
|
||||
52 error code: 'EACCES',
|
||||
52 error syscall: 'mkdir',
|
||||
52 error path: '/Users/MB/git/pitfall/pdfkit/node_modules/.staging' }
|
||||
53 error Please try running this command again as root/Administrator.
|
||||
54 verbose exit [ -13, true ]
|
@ -0,0 +1,99 @@
|
||||
###
|
||||
PDFObject - converts JavaScript types into their corrisponding PDF types.
|
||||
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) ->
|
||||
# String literals are converted to the PDF name type
|
||||
if typeof object is 'string'
|
||||
'/' + 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() + 1, 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
|
||||
out.push '/' + key + ' ' + PDFObject.convert(val)
|
||||
|
||||
out.push '>>'
|
||||
out.join '\n'
|
||||
|
||||
else if typeof object is 'number'
|
||||
PDFObject.number object
|
||||
|
||||
else
|
||||
'' + object
|
||||
|
||||
@number: (n) ->
|
||||
if n > -1e21 and n < 1e21
|
||||
return Math.round(n * 1e6) / 1e6
|
||||
|
||||
throw new Error "unsupported number: #{n}"
|
||||
|
||||
module.exports = PDFObject
|
||||
PDFReference = require './reference'
|
@ -0,0 +1,114 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
|
||||
/*
|
||||
PDFObject - converts JavaScript types into their corrisponding PDF types.
|
||||
By Devon Govett
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var PDFObject, PDFReference;
|
||||
|
||||
PDFObject = (function() {
|
||||
var escapable, escapableRe, pad, swapBytes;
|
||||
|
||||
function PDFObject() {}
|
||||
|
||||
pad = function(str, length) {
|
||||
return (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',
|
||||
'\\': '\\\\',
|
||||
'(': '\\(',
|
||||
')': '\\)'
|
||||
};
|
||||
|
||||
swapBytes = function(buff) {
|
||||
var a, i, j, l, ref;
|
||||
l = buff.length;
|
||||
if (l & 0x01) {
|
||||
throw new Error("Buffer length must be even");
|
||||
} else {
|
||||
for (i = j = 0, ref = l - 1; j < ref; i = j += 2) {
|
||||
a = buff[i];
|
||||
buff[i] = buff[i + 1];
|
||||
buff[i + 1] = a;
|
||||
}
|
||||
}
|
||||
return buff;
|
||||
};
|
||||
|
||||
PDFObject.convert = function(object) {
|
||||
var e, i, isUnicode, items, j, key, out, ref, string, val;
|
||||
if (typeof object === 'string') {
|
||||
return '/' + object;
|
||||
} else if (object instanceof String) {
|
||||
string = object.replace(escapableRe, function(c) {
|
||||
return escapable[c];
|
||||
});
|
||||
isUnicode = false;
|
||||
for (i = j = 0, ref = string.length; j < ref; i = j += 1) {
|
||||
if (string.charCodeAt(i) > 0x7f) {
|
||||
isUnicode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isUnicode) {
|
||||
string = swapBytes(new Buffer('\ufeff' + string, 'utf16le')).toString('binary');
|
||||
}
|
||||
return '(' + string + ')';
|
||||
} else if (Buffer.isBuffer(object)) {
|
||||
return '<' + object.toString('hex') + '>';
|
||||
} else if (object instanceof PDFReference) {
|
||||
return object.toString();
|
||||
} else if (object instanceof Date) {
|
||||
return '(D:' + pad(object.getUTCFullYear(), 4) + pad(object.getUTCMonth() + 1, 2) + pad(object.getUTCDate(), 2) + pad(object.getUTCHours(), 2) + pad(object.getUTCMinutes(), 2) + pad(object.getUTCSeconds(), 2) + 'Z)';
|
||||
} else if (Array.isArray(object)) {
|
||||
items = ((function() {
|
||||
var k, len, results;
|
||||
results = [];
|
||||
for (k = 0, len = object.length; k < len; k++) {
|
||||
e = object[k];
|
||||
results.push(PDFObject.convert(e));
|
||||
}
|
||||
return results;
|
||||
})()).join(' ');
|
||||
return '[' + items + ']';
|
||||
} else if ({}.toString.call(object) === '[object Object]') {
|
||||
out = ['<<'];
|
||||
for (key in object) {
|
||||
val = object[key];
|
||||
out.push('/' + key + ' ' + PDFObject.convert(val));
|
||||
}
|
||||
out.push('>>');
|
||||
return out.join('\n');
|
||||
} else if (typeof object === 'number') {
|
||||
return PDFObject.number(object);
|
||||
} else {
|
||||
return '' + object;
|
||||
}
|
||||
};
|
||||
|
||||
PDFObject.number = function(n) {
|
||||
if (n > -1e21 && n < 1e21) {
|
||||
return Math.round(n * 1e6) / 1e6;
|
||||
}
|
||||
throw new Error("unsupported number: " + n);
|
||||
};
|
||||
|
||||
return PDFObject;
|
||||
|
||||
})();
|
||||
|
||||
module.exports = PDFObject;
|
||||
|
||||
PDFReference = require('./reference');
|
||||
|
||||
}).call(this);
|
@ -0,0 +1,124 @@
|
||||
###
|
||||
PDFPage - represents a single page in the PDF document
|
||||
By Devon Govett
|
||||
###
|
||||
|
||||
class PDFPage
|
||||
constructor: (@document, options = {}) ->
|
||||
@size = options.size or 'letter'
|
||||
@layout = options.layout or 'portrait'
|
||||
|
||||
# process margins
|
||||
if typeof options.margin is 'number'
|
||||
@margins =
|
||||
top: options.margin
|
||||
left: options.margin
|
||||
bottom: options.margin
|
||||
right: options.margin
|
||||
|
||||
# default to 1 inch margins
|
||||
else
|
||||
@margins = options.margins or DEFAULT_MARGINS
|
||||
|
||||
# calculate page dimensions
|
||||
dimensions = if Array.isArray(@size) then @size else SIZES[@size.toUpperCase()]
|
||||
@width = dimensions[if @layout is 'portrait' then 0 else 1]
|
||||
@height = dimensions[if @layout is 'portrait' then 1 else 0]
|
||||
|
||||
@content = @document.ref()
|
||||
|
||||
# Initialize the Font, XObject, and ExtGState dictionaries
|
||||
@resources = @document.ref
|
||||
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI']
|
||||
|
||||
# Lazily create these dictionaries
|
||||
Object.defineProperties this,
|
||||
fonts:
|
||||
get: => @resources.data.Font ?= {}
|
||||
xobjects:
|
||||
get: => @resources.data.XObject ?= {}
|
||||
ext_gstates:
|
||||
get: => @resources.data.ExtGState ?= {}
|
||||
patterns:
|
||||
get: => @resources.data.Pattern ?= {}
|
||||
annotations:
|
||||
get: => @dictionary.data.Annots ?= []
|
||||
|
||||
# The page dictionary
|
||||
@dictionary = @document.ref
|
||||
Type: 'Page'
|
||||
Parent: @document._root.data.Pages
|
||||
MediaBox: [0, 0, @width, @height]
|
||||
Contents: @content
|
||||
Resources: @resources
|
||||
|
||||
maxY: ->
|
||||
@height - @margins.bottom
|
||||
|
||||
write: (chunk) ->
|
||||
@content.write chunk
|
||||
|
||||
end: ->
|
||||
@dictionary.end()
|
||||
@resources.end()
|
||||
@content.end()
|
||||
|
||||
DEFAULT_MARGINS =
|
||||
top: 72
|
||||
left: 72
|
||||
bottom: 72
|
||||
right: 72
|
||||
|
||||
SIZES =
|
||||
'4A0': [4767.87, 6740.79]
|
||||
'2A0': [3370.39, 4767.87]
|
||||
A0: [2383.94, 3370.39]
|
||||
A1: [1683.78, 2383.94]
|
||||
A2: [1190.55, 1683.78]
|
||||
A3: [841.89, 1190.55]
|
||||
A4: [595.28, 841.89]
|
||||
A5: [419.53, 595.28]
|
||||
A6: [297.64, 419.53]
|
||||
A7: [209.76, 297.64]
|
||||
A8: [147.40, 209.76]
|
||||
A9: [104.88, 147.40]
|
||||
A10: [73.70, 104.88]
|
||||
B0: [2834.65, 4008.19]
|
||||
B1: [2004.09, 2834.65]
|
||||
B2: [1417.32, 2004.09]
|
||||
B3: [1000.63, 1417.32]
|
||||
B4: [708.66, 1000.63]
|
||||
B5: [498.90, 708.66]
|
||||
B6: [354.33, 498.90]
|
||||
B7: [249.45, 354.33]
|
||||
B8: [175.75, 249.45]
|
||||
B9: [124.72, 175.75]
|
||||
B10: [87.87, 124.72]
|
||||
C0: [2599.37, 3676.54]
|
||||
C1: [1836.85, 2599.37]
|
||||
C2: [1298.27, 1836.85]
|
||||
C3: [918.43, 1298.27]
|
||||
C4: [649.13, 918.43]
|
||||
C5: [459.21, 649.13]
|
||||
C6: [323.15, 459.21]
|
||||
C7: [229.61, 323.15]
|
||||
C8: [161.57, 229.61]
|
||||
C9: [113.39, 161.57]
|
||||
C10: [79.37, 113.39]
|
||||
RA0: [2437.80, 3458.27]
|
||||
RA1: [1729.13, 2437.80]
|
||||
RA2: [1218.90, 1729.13]
|
||||
RA3: [864.57, 1218.90]
|
||||
RA4: [609.45, 864.57]
|
||||
SRA0: [2551.18, 3628.35]
|
||||
SRA1: [1814.17, 2551.18]
|
||||
SRA2: [1275.59, 1814.17]
|
||||
SRA3: [907.09, 1275.59]
|
||||
SRA4: [637.80, 907.09]
|
||||
EXECUTIVE: [521.86, 756.00]
|
||||
FOLIO: [612.00, 936.00]
|
||||
LEGAL: [612.00, 1008.00]
|
||||
LETTER: [612.00, 792.00]
|
||||
TABLOID: [792.00, 1224.00]
|
||||
|
||||
module.exports = PDFPage
|
@ -0,0 +1,170 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
|
||||
/*
|
||||
PDFPage - represents a single page in the PDF document
|
||||
By Devon Govett
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var PDFPage;
|
||||
|
||||
PDFPage = (function() {
|
||||
var DEFAULT_MARGINS, SIZES;
|
||||
|
||||
function PDFPage(document, options) {
|
||||
var dimensions;
|
||||
this.document = document;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
this.size = options.size || 'letter';
|
||||
this.layout = options.layout || 'portrait';
|
||||
if (typeof options.margin === 'number') {
|
||||
this.margins = {
|
||||
top: options.margin,
|
||||
left: options.margin,
|
||||
bottom: options.margin,
|
||||
right: options.margin
|
||||
};
|
||||
} else {
|
||||
this.margins = options.margins || DEFAULT_MARGINS;
|
||||
}
|
||||
dimensions = Array.isArray(this.size) ? this.size : SIZES[this.size.toUpperCase()];
|
||||
this.width = dimensions[this.layout === 'portrait' ? 0 : 1];
|
||||
this.height = dimensions[this.layout === 'portrait' ? 1 : 0];
|
||||
this.content = this.document.ref();
|
||||
this.resources = this.document.ref({
|
||||
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI']
|
||||
});
|
||||
Object.defineProperties(this, {
|
||||
fonts: {
|
||||
get: (function(_this) {
|
||||
return function() {
|
||||
var base;
|
||||
return (base = _this.resources.data).Font != null ? base.Font : base.Font = {};
|
||||
};
|
||||
})(this)
|
||||
},
|
||||
xobjects: {
|
||||
get: (function(_this) {
|
||||
return function() {
|
||||
var base;
|
||||
return (base = _this.resources.data).XObject != null ? base.XObject : base.XObject = {};
|
||||
};
|
||||
})(this)
|
||||
},
|
||||
ext_gstates: {
|
||||
get: (function(_this) {
|
||||
return function() {
|
||||
var base;
|
||||
return (base = _this.resources.data).ExtGState != null ? base.ExtGState : base.ExtGState = {};
|
||||
};
|
||||
})(this)
|
||||
},
|
||||
patterns: {
|
||||
get: (function(_this) {
|
||||
return function() {
|
||||
var base;
|
||||
return (base = _this.resources.data).Pattern != null ? base.Pattern : base.Pattern = {};
|
||||
};
|
||||
})(this)
|
||||
},
|
||||
annotations: {
|
||||
get: (function(_this) {
|
||||
return function() {
|
||||
var base;
|
||||
return (base = _this.dictionary.data).Annots != null ? base.Annots : base.Annots = [];
|
||||
};
|
||||
})(this)
|
||||
}
|
||||
});
|
||||
this.dictionary = this.document.ref({
|
||||
Type: 'Page',
|
||||
Parent: this.document._root.data.Pages,
|
||||
MediaBox: [0, 0, this.width, this.height],
|
||||
Contents: this.content,
|
||||
Resources: this.resources
|
||||
});
|
||||
}
|
||||
|
||||
PDFPage.prototype.maxY = function() {
|
||||
return this.height - this.margins.bottom;
|
||||
};
|
||||
|
||||
PDFPage.prototype.write = function(chunk) {
|
||||
return this.content.write(chunk);
|
||||
};
|
||||
|
||||
PDFPage.prototype.end = function() {
|
||||
this.dictionary.end();
|
||||
this.resources.end();
|
||||
return this.content.end();
|
||||
};
|
||||
|
||||
DEFAULT_MARGINS = {
|
||||
top: 72,
|
||||
left: 72,
|
||||
bottom: 72,
|
||||
right: 72
|
||||
};
|
||||
|
||||
SIZES = {
|
||||
'4A0': [4767.87, 6740.79],
|
||||
'2A0': [3370.39, 4767.87],
|
||||
A0: [2383.94, 3370.39],
|
||||
A1: [1683.78, 2383.94],
|
||||
A2: [1190.55, 1683.78],
|
||||
A3: [841.89, 1190.55],
|
||||
A4: [595.28, 841.89],
|
||||
A5: [419.53, 595.28],
|
||||
A6: [297.64, 419.53],
|
||||
A7: [209.76, 297.64],
|
||||
A8: [147.40, 209.76],
|
||||
A9: [104.88, 147.40],
|
||||
A10: [73.70, 104.88],
|
||||
B0: [2834.65, 4008.19],
|
||||
B1: [2004.09, 2834.65],
|
||||
B2: [1417.32, 2004.09],
|
||||
B3: [1000.63, 1417.32],
|
||||
B4: [708.66, 1000.63],
|
||||
B5: [498.90, 708.66],
|
||||
B6: [354.33, 498.90],
|
||||
B7: [249.45, 354.33],
|
||||
B8: [175.75, 249.45],
|
||||
B9: [124.72, 175.75],
|
||||
B10: [87.87, 124.72],
|
||||
C0: [2599.37, 3676.54],
|
||||
C1: [1836.85, 2599.37],
|
||||
C2: [1298.27, 1836.85],
|
||||
C3: [918.43, 1298.27],
|
||||
C4: [649.13, 918.43],
|
||||
C5: [459.21, 649.13],
|
||||
C6: [323.15, 459.21],
|
||||
C7: [229.61, 323.15],
|
||||
C8: [161.57, 229.61],
|
||||
C9: [113.39, 161.57],
|
||||
C10: [79.37, 113.39],
|
||||
RA0: [2437.80, 3458.27],
|
||||
RA1: [1729.13, 2437.80],
|
||||
RA2: [1218.90, 1729.13],
|
||||
RA3: [864.57, 1218.90],
|
||||
RA4: [609.45, 864.57],
|
||||
SRA0: [2551.18, 3628.35],
|
||||
SRA1: [1814.17, 2551.18],
|
||||
SRA2: [1275.59, 1814.17],
|
||||
SRA3: [907.09, 1275.59],
|
||||
SRA4: [637.80, 907.09],
|
||||
EXECUTIVE: [521.86, 756.00],
|
||||
FOLIO: [612.00, 936.00],
|
||||
LEGAL: [612.00, 1008.00],
|
||||
LETTER: [612.00, 792.00],
|
||||
TABLOID: [792.00, 1224.00]
|
||||
};
|
||||
|
||||
return PDFPage;
|
||||
|
||||
})();
|
||||
|
||||
module.exports = PDFPage;
|
||||
|
||||
}).call(this);
|
@ -0,0 +1,326 @@
|
||||
class SVGPath
|
||||
@apply: (doc, path) ->
|
||||
commands = parse path
|
||||
apply commands, doc
|
||||
|
||||
parameters =
|
||||
A: 7
|
||||
a: 7
|
||||
C: 6
|
||||
c: 6
|
||||
H: 1
|
||||
h: 1
|
||||
L: 2
|
||||
l: 2
|
||||
M: 2
|
||||
m: 2
|
||||
Q: 4
|
||||
q: 4
|
||||
S: 4
|
||||
s: 4
|
||||
T: 2
|
||||
t: 2
|
||||
V: 1
|
||||
v: 1
|
||||
Z: 0
|
||||
z: 0
|
||||
|
||||
parse = (path) ->
|
||||
ret = []
|
||||
args = []
|
||||
curArg = ""
|
||||
foundDecimal = no
|
||||
params = 0
|
||||
|
||||
for c in path
|
||||
if parameters[c]?
|
||||
params = parameters[c]
|
||||
if cmd # save existing command
|
||||
args[args.length] = +curArg if curArg.length > 0
|
||||
ret[ret.length] = {cmd,args}
|
||||
|
||||
args = []
|
||||
curArg = ""
|
||||
foundDecimal = no
|
||||
|
||||
cmd = c
|
||||
|
||||
else if c in [" ", ","] or (c is "-" and curArg.length > 0 and curArg[curArg.length - 1] isnt 'e') or (c is "." and foundDecimal)
|
||||
continue if curArg.length is 0
|
||||
|
||||
if args.length is params # handle reused commands
|
||||
ret[ret.length] = {cmd,args}
|
||||
args = [+curArg]
|
||||
|
||||
# handle assumed commands
|
||||
cmd = "L" if cmd is "M"
|
||||
cmd = "l" if cmd is "m"
|
||||
|
||||
else
|
||||
args[args.length] = +curArg
|
||||
|
||||
foundDecimal = (c is ".")
|
||||
|
||||
# fix for negative numbers or repeated decimals with no delimeter between commands
|
||||
curArg = if c in ['-', '.'] then c else ''
|
||||
|
||||
else
|
||||
curArg += c
|
||||
foundDecimal = true if c is '.'
|
||||
|
||||
# add the last command
|
||||
if curArg.length > 0
|
||||
if args.length is params # handle reused commands
|
||||
ret[ret.length] = {cmd, args}
|
||||
args = [+curArg]
|
||||
|
||||
# handle assumed commands
|
||||
cmd = "L" if cmd is "M"
|
||||
cmd = "l" if cmd is "m"
|
||||
else
|
||||
args[args.length] = +curArg
|
||||
|
||||
ret[ret.length] = {cmd,args}
|
||||
|
||||
return ret
|
||||
|
||||
cx = cy = px = py = sx = sy = 0
|
||||
apply = (commands, doc) ->
|
||||
# current point, control point, and subpath starting point
|
||||
cx = cy = px = py = sx = sy = 0
|
||||
|
||||
# run the commands
|
||||
for c, i in commands
|
||||
runners[c.cmd]?(doc, c.args)
|
||||
|
||||
cx = cy = px = py = 0
|
||||
|
||||
runners =
|
||||
M: (doc, a) ->
|
||||
cx = a[0]
|
||||
cy = a[1]
|
||||
px = py = null
|
||||
sx = cx
|
||||
sy = cy
|
||||
doc.moveTo cx, cy
|
||||
|
||||
m: (doc, a) ->
|
||||
cx += a[0]
|
||||
cy += a[1]
|
||||
px = py = null
|
||||
sx = cx
|
||||
sy = cy
|
||||
doc.moveTo cx, cy
|
||||
|
||||
C: (doc, a) ->
|
||||
cx = a[4]
|
||||
cy = a[5]
|
||||
px = a[2]
|
||||
py = a[3]
|
||||
doc.bezierCurveTo a...
|
||||
|
||||
c: (doc, a) ->
|
||||
doc.bezierCurveTo a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy, a[4] + cx, a[5] + cy
|
||||
px = cx + a[2]
|
||||
py = cy + a[3]
|
||||
cx += a[4]
|
||||
cy += a[5]
|
||||
|
||||
S: (doc, a) ->
|
||||
if px is null
|
||||
px = cx
|
||||
py = cy
|
||||
|
||||
doc.bezierCurveTo cx-(px-cx), cy-(py-cy), a[0], a[1], a[2], a[3]
|
||||
px = a[0]
|
||||
py = a[1]
|
||||
cx = a[2]
|
||||
cy = a[3]
|
||||
|
||||
s: (doc, a) ->
|
||||
if px is null
|
||||
px = cx
|
||||
py = cy
|
||||
|
||||
doc.bezierCurveTo cx-(px-cx), cy-(py-cy), cx + a[0], cy + a[1], cx + a[2], cy + a[3]
|
||||
px = cx + a[0]
|
||||
py = cy + a[1]
|
||||
cx += a[2]
|
||||
cy += a[3]
|
||||
|
||||
Q: (doc, a) ->
|
||||
px = a[0]
|
||||
py = a[1]
|
||||
cx = a[2]
|
||||
cy = a[3]
|
||||
doc.quadraticCurveTo(a[0], a[1], cx, cy)
|
||||
|
||||
q: (doc, a) ->
|
||||
doc.quadraticCurveTo(a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy)
|
||||
px = cx + a[0]
|
||||
py = cy + a[1]
|
||||
cx += a[2]
|
||||
cy += a[3]
|
||||
|
||||
T: (doc, a) ->
|
||||
if px is null
|
||||
px = cx
|
||||
py = cy
|
||||
else
|
||||
px = cx-(px-cx)
|
||||
py = cy-(py-cy)
|
||||
|
||||
doc.quadraticCurveTo(px, py, a[0], a[1])
|
||||
px = cx-(px-cx)
|
||||
py = cy-(py-cy)
|
||||
cx = a[0]
|
||||
cy = a[1]
|
||||
|
||||
t: (doc, a) ->
|
||||
if px is null
|
||||
px = cx
|
||||
py = cy
|
||||
else
|
||||
px = cx-(px-cx)
|
||||
py = cy-(py-cy)
|
||||
|
||||
doc.quadraticCurveTo(px, py, cx + a[0], cy + a[1])
|
||||
cx += a[0]
|
||||
cy += a[1]
|
||||
|
||||
A: (doc, a) ->
|
||||
solveArc(doc, cx, cy, a)
|
||||
cx = a[5]
|
||||
cy = a[6]
|
||||
|
||||
a: (doc, a) ->
|
||||
a[5] += cx
|
||||
a[6] += cy
|
||||
solveArc(doc, cx, cy, a)
|
||||
cx = a[5]
|
||||
cy = a[6]
|
||||
|
||||
L: (doc, a) ->
|
||||
cx = a[0]
|
||||
cy = a[1]
|
||||
px = py = null
|
||||
doc.lineTo(cx, cy)
|
||||
|
||||
l: (doc, a) ->
|
||||
cx += a[0]
|
||||
cy += a[1]
|
||||
px = py = null
|
||||
doc.lineTo(cx, cy)
|
||||
|
||||
H: (doc, a) ->
|
||||
cx = a[0]
|
||||
px = py = null
|
||||
doc.lineTo(cx, cy)
|
||||
|
||||
h: (doc, a) ->
|
||||
cx += a[0]
|
||||
px = py = null
|
||||
doc.lineTo(cx, cy)
|
||||
|
||||
V: (doc, a) ->
|
||||
cy = a[0]
|
||||
px = py = null
|
||||
doc.lineTo(cx, cy)
|
||||
|
||||
v: (doc, a) ->
|
||||
cy += a[0]
|
||||
px = py = null
|
||||
doc.lineTo(cx, cy)
|
||||
|
||||
Z: (doc) ->
|
||||
doc.closePath()
|
||||
cx = sx
|
||||
cy = sy
|
||||
|
||||
z: (doc) ->
|
||||
doc.closePath()
|
||||
cx = sx
|
||||
cy = sy
|
||||
|
||||
solveArc = (doc, x, y, coords) ->
|
||||
[rx,ry,rot,large,sweep,ex,ey] = coords
|
||||
segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y)
|
||||
|
||||
for seg in segs
|
||||
bez = segmentToBezier seg...
|
||||
doc.bezierCurveTo bez...
|
||||
|
||||
# from Inkscape svgtopdf, thanks!
|
||||
arcToSegments = (x, y, rx, ry, large, sweep, rotateX, ox, oy) ->
|
||||
th = rotateX * (Math.PI/180)
|
||||
sin_th = Math.sin(th)
|
||||
cos_th = Math.cos(th)
|
||||
rx = Math.abs(rx)
|
||||
ry = Math.abs(ry)
|
||||
px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5
|
||||
py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5
|
||||
pl = (px*px) / (rx*rx) + (py*py) / (ry*ry)
|
||||
if pl > 1
|
||||
pl = Math.sqrt(pl)
|
||||
rx *= pl
|
||||
ry *= pl
|
||||
|
||||
a00 = cos_th / rx
|
||||
a01 = sin_th / rx
|
||||
a10 = (-sin_th) / ry
|
||||
a11 = (cos_th) / ry
|
||||
x0 = a00 * ox + a01 * oy
|
||||
y0 = a10 * ox + a11 * oy
|
||||
x1 = a00 * x + a01 * y
|
||||
y1 = a10 * x + a11 * y
|
||||
|
||||
d = (x1-x0) * (x1-x0) + (y1-y0) * (y1-y0)
|
||||
sfactor_sq = 1 / d - 0.25
|
||||
sfactor_sq = 0 if sfactor_sq < 0
|
||||
sfactor = Math.sqrt(sfactor_sq)
|
||||
sfactor = -sfactor if sweep is large
|
||||
|
||||
xc = 0.5 * (x0 + x1) - sfactor * (y1-y0)
|
||||
yc = 0.5 * (y0 + y1) + sfactor * (x1-x0)
|
||||
|
||||
th0 = Math.atan2(y0-yc, x0-xc)
|
||||
th1 = Math.atan2(y1-yc, x1-xc)
|
||||
|
||||
th_arc = th1-th0
|
||||
if th_arc < 0 && sweep is 1
|
||||
th_arc += 2*Math.PI
|
||||
else if th_arc > 0 && sweep is 0
|
||||
th_arc -= 2 * Math.PI
|
||||
|
||||
segments = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)))
|
||||
result = []
|
||||
|
||||
for i in [0...segments]
|
||||
th2 = th0 + i * th_arc / segments
|
||||
th3 = th0 + (i+1) * th_arc / segments
|
||||
result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th]
|
||||
|
||||
return result
|
||||
|
||||
segmentToBezier = (cx, cy, th0, th1, rx, ry, sin_th, cos_th) ->
|
||||
a00 = cos_th * rx
|
||||
a01 = -sin_th * ry
|
||||
a10 = sin_th * rx
|
||||
a11 = cos_th * ry
|
||||
|
||||
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 = 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,
|
||||
a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
|
||||
a00 * x3 + a01 * y3, a10 * x3 + a11 * y3
|
||||
]
|
||||
|
||||
module.exports = SVGPath
|
@ -0,0 +1,366 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
(function() {
|
||||
var SVGPath;
|
||||
|
||||
SVGPath = (function() {
|
||||
var apply, arcToSegments, cx, cy, parameters, parse, px, py, runners, segmentToBezier, solveArc, sx, sy;
|
||||
|
||||
function SVGPath() {}
|
||||
|
||||
SVGPath.apply = function(doc, path) {
|
||||
var commands;
|
||||
commands = parse(path);
|
||||
return apply(commands, doc);
|
||||
};
|
||||
|
||||
parameters = {
|
||||
A: 7,
|
||||
a: 7,
|
||||
C: 6,
|
||||
c: 6,
|
||||
H: 1,
|
||||
h: 1,
|
||||
L: 2,
|
||||
l: 2,
|
||||
M: 2,
|
||||
m: 2,
|
||||
Q: 4,
|
||||
q: 4,
|
||||
S: 4,
|
||||
s: 4,
|
||||
T: 2,
|
||||
t: 2,
|
||||
V: 1,
|
||||
v: 1,
|
||||
Z: 0,
|
||||
z: 0
|
||||
};
|
||||
|
||||
parse = function(path) {
|
||||
var args, c, cmd, curArg, foundDecimal, j, len, params, ret;
|
||||
ret = [];
|
||||
args = [];
|
||||
curArg = "";
|
||||
foundDecimal = false;
|
||||
params = 0;
|
||||
for (j = 0, len = path.length; j < len; j++) {
|
||||
c = path[j];
|
||||
if (parameters[c] != null) {
|
||||
params = parameters[c];
|
||||
if (cmd) {
|
||||
if (curArg.length > 0) {
|
||||
args[args.length] = +curArg;
|
||||
}
|
||||
ret[ret.length] = {
|
||||
cmd: cmd,
|
||||
args: args
|
||||
};
|
||||
args = [];
|
||||
curArg = "";
|
||||
foundDecimal = false;
|
||||
}
|
||||
cmd = c;
|
||||
} else if ((c === " " || c === ",") || (c === "-" && curArg.length > 0 && curArg[curArg.length - 1] !== 'e') || (c === "." && foundDecimal)) {
|
||||
if (curArg.length === 0) {
|
||||
continue;
|
||||
}
|
||||
if (args.length === params) {
|
||||
ret[ret.length] = {
|
||||
cmd: cmd,
|
||||
args: args
|
||||
};
|
||||
args = [+curArg];
|
||||
if (cmd === "M") {
|
||||
cmd = "L";
|
||||
}
|
||||
if (cmd === "m") {
|
||||
cmd = "l";
|
||||
}
|
||||
} else {
|
||||
args[args.length] = +curArg;
|
||||
}
|
||||
foundDecimal = c === ".";
|
||||
curArg = c === '-' || c === '.' ? c : '';
|
||||
} else {
|
||||
curArg += c;
|
||||
if (c === '.') {
|
||||
foundDecimal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (curArg.length > 0) {
|
||||
if (args.length === params) {
|
||||
ret[ret.length] = {
|
||||
cmd: cmd,
|
||||
args: args
|
||||
};
|
||||
args = [+curArg];
|
||||
if (cmd === "M") {
|
||||
cmd = "L";
|
||||
}
|
||||
if (cmd === "m") {
|
||||
cmd = "l";
|
||||
}
|
||||
} else {
|
||||
args[args.length] = +curArg;
|
||||
}
|
||||
}
|
||||
ret[ret.length] = {
|
||||
cmd: cmd,
|
||||
args: args
|
||||
};
|
||||
return ret;
|
||||
};
|
||||
|
||||
cx = cy = px = py = sx = sy = 0;
|
||||
|
||||
apply = function(commands, doc) {
|
||||
var c, i, j, len, name;
|
||||
cx = cy = px = py = sx = sy = 0;
|
||||
for (i = j = 0, len = commands.length; j < len; i = ++j) {
|
||||
c = commands[i];
|
||||
if (typeof runners[name = c.cmd] === "function") {
|
||||
runners[name](doc, c.args);
|
||||
}
|
||||
}
|
||||
return cx = cy = px = py = 0;
|
||||
};
|
||||
|
||||
runners = {
|
||||
M: function(doc, a) {
|
||||
cx = a[0];
|
||||
cy = a[1];
|
||||
px = py = null;
|
||||
sx = cx;
|
||||
sy = cy;
|
||||
return doc.moveTo(cx, cy);
|
||||
},
|
||||
m: function(doc, a) {
|
||||
cx += a[0];
|
||||
cy += a[1];
|
||||
px = py = null;
|
||||
sx = cx;
|
||||
sy = cy;
|
||||
return doc.moveTo(cx, cy);
|
||||
},
|
||||
C: function(doc, a) {
|
||||
cx = a[4];
|
||||
cy = a[5];
|
||||
px = a[2];
|
||||
py = a[3];
|
||||
return doc.bezierCurveTo.apply(doc, a);
|
||||
},
|
||||
c: function(doc, a) {
|
||||
doc.bezierCurveTo(a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy, a[4] + cx, a[5] + cy);
|
||||
px = cx + a[2];
|
||||
py = cy + a[3];
|
||||
cx += a[4];
|
||||
return cy += a[5];
|
||||
},
|
||||
S: function(doc, a) {
|
||||
if (px === null) {
|
||||
px = cx;
|
||||
py = cy;
|
||||
}
|
||||
doc.bezierCurveTo(cx - (px - cx), cy - (py - cy), a[0], a[1], a[2], a[3]);
|
||||
px = a[0];
|
||||
py = a[1];
|
||||
cx = a[2];
|
||||
return cy = a[3];
|
||||
},
|
||||
s: function(doc, a) {
|
||||
if (px === null) {
|
||||
px = cx;
|
||||
py = cy;
|
||||
}
|
||||
doc.bezierCurveTo(cx - (px - cx), cy - (py - cy), cx + a[0], cy + a[1], cx + a[2], cy + a[3]);
|
||||
px = cx + a[0];
|
||||
py = cy + a[1];
|
||||
cx += a[2];
|
||||
return cy += a[3];
|
||||
},
|
||||
Q: function(doc, a) {
|
||||
px = a[0];
|
||||
py = a[1];
|
||||
cx = a[2];
|
||||
cy = a[3];
|
||||
return doc.quadraticCurveTo(a[0], a[1], cx, cy);
|
||||
},
|
||||
q: function(doc, a) {
|
||||
doc.quadraticCurveTo(a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy);
|
||||
px = cx + a[0];
|
||||
py = cy + a[1];
|
||||
cx += a[2];
|
||||
return cy += a[3];
|
||||
},
|
||||
T: function(doc, a) {
|
||||
if (px === null) {
|
||||
px = cx;
|
||||
py = cy;
|
||||
} else {
|
||||
px = cx - (px - cx);
|
||||
py = cy - (py - cy);
|
||||
}
|
||||
doc.quadraticCurveTo(px, py, a[0], a[1]);
|
||||
px = cx - (px - cx);
|
||||
py = cy - (py - cy);
|
||||
cx = a[0];
|
||||
return cy = a[1];
|
||||
},
|
||||
t: function(doc, a) {
|
||||
if (px === null) {
|
||||
px = cx;
|
||||
py = cy;
|
||||
} else {
|
||||
px = cx - (px - cx);
|
||||
py = cy - (py - cy);
|
||||
}
|
||||
doc.quadraticCurveTo(px, py, cx + a[0], cy + a[1]);
|
||||
cx += a[0];
|
||||
return cy += a[1];
|
||||
},
|
||||
A: function(doc, a) {
|
||||
solveArc(doc, cx, cy, a);
|
||||
cx = a[5];
|
||||
return cy = a[6];
|
||||
},
|
||||
a: function(doc, a) {
|
||||
a[5] += cx;
|
||||
a[6] += cy;
|
||||
solveArc(doc, cx, cy, a);
|
||||
cx = a[5];
|
||||
return cy = a[6];
|
||||
},
|
||||
L: function(doc, a) {
|
||||
cx = a[0];
|
||||
cy = a[1];
|
||||
px = py = null;
|
||||
return doc.lineTo(cx, cy);
|
||||
},
|
||||
l: function(doc, a) {
|
||||
cx += a[0];
|
||||
cy += a[1];
|
||||
px = py = null;
|
||||
return doc.lineTo(cx, cy);
|
||||
},
|
||||
H: function(doc, a) {
|
||||
cx = a[0];
|
||||
px = py = null;
|
||||
return doc.lineTo(cx, cy);
|
||||
},
|
||||
h: function(doc, a) {
|
||||
cx += a[0];
|
||||
px = py = null;
|
||||
return doc.lineTo(cx, cy);
|
||||
},
|
||||
V: function(doc, a) {
|
||||
cy = a[0];
|
||||
px = py = null;
|
||||
return doc.lineTo(cx, cy);
|
||||
},
|
||||
v: function(doc, a) {
|
||||
cy += a[0];
|
||||
px = py = null;
|
||||
return doc.lineTo(cx, cy);
|
||||
},
|
||||
Z: function(doc) {
|
||||
doc.closePath();
|
||||
cx = sx;
|
||||
return cy = sy;
|
||||
},
|
||||
z: function(doc) {
|
||||
doc.closePath();
|
||||
cx = sx;
|
||||
return cy = sy;
|
||||
}
|
||||
};
|
||||
|
||||
solveArc = function(doc, x, y, coords) {
|
||||
var bez, ex, ey, j, large, len, results, rot, rx, ry, seg, segs, sweep;
|
||||
rx = coords[0], ry = coords[1], rot = coords[2], large = coords[3], sweep = coords[4], ex = coords[5], ey = coords[6];
|
||||
segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y);
|
||||
results = [];
|
||||
for (j = 0, len = segs.length; j < len; j++) {
|
||||
seg = segs[j];
|
||||
bez = segmentToBezier.apply(null, seg);
|
||||
results.push(doc.bezierCurveTo.apply(doc, bez));
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
arcToSegments = function(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
|
||||
var a00, a01, a10, a11, cos_th, d, i, j, pl, ref, result, segments, sfactor, sfactor_sq, sin_th, th, th0, th1, th2, th3, th_arc, x0, x1, xc, y0, y1, yc;
|
||||
th = rotateX * (Math.PI / 180);
|
||||
sin_th = Math.sin(th);
|
||||
cos_th = Math.cos(th);
|
||||
rx = Math.abs(rx);
|
||||
ry = Math.abs(ry);
|
||||
px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
|
||||
py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
|
||||
pl = (px * px) / (rx * rx) + (py * py) / (ry * ry);
|
||||
if (pl > 1) {
|
||||
pl = Math.sqrt(pl);
|
||||
rx *= pl;
|
||||
ry *= pl;
|
||||
}
|
||||
a00 = cos_th / rx;
|
||||
a01 = sin_th / rx;
|
||||
a10 = (-sin_th) / ry;
|
||||
a11 = cos_th / ry;
|
||||
x0 = a00 * ox + a01 * oy;
|
||||
y0 = a10 * ox + a11 * oy;
|
||||
x1 = a00 * x + a01 * y;
|
||||
y1 = a10 * x + a11 * y;
|
||||
d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
|
||||
sfactor_sq = 1 / d - 0.25;
|
||||
if (sfactor_sq < 0) {
|
||||
sfactor_sq = 0;
|
||||
}
|
||||
sfactor = Math.sqrt(sfactor_sq);
|
||||
if (sweep === large) {
|
||||
sfactor = -sfactor;
|
||||
}
|
||||
xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
|
||||
yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
|
||||
th0 = Math.atan2(y0 - yc, x0 - xc);
|
||||
th1 = Math.atan2(y1 - yc, x1 - xc);
|
||||
th_arc = th1 - th0;
|
||||
if (th_arc < 0 && sweep === 1) {
|
||||
th_arc += 2 * Math.PI;
|
||||
} else if (th_arc > 0 && sweep === 0) {
|
||||
th_arc -= 2 * Math.PI;
|
||||
}
|
||||
segments = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)));
|
||||
result = [];
|
||||
for (i = j = 0, ref = segments; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
|
||||
th2 = th0 + i * th_arc / segments;
|
||||
th3 = th0 + (i + 1) * th_arc / segments;
|
||||
result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
segmentToBezier = function(cx, cy, th0, th1, rx, ry, sin_th, cos_th) {
|
||||
var a00, a01, a10, a11, t, th_half, x1, x2, x3, y1, y2, y3;
|
||||
a00 = cos_th * rx;
|
||||
a01 = -sin_th * ry;
|
||||
a10 = sin_th * rx;
|
||||
a11 = cos_th * ry;
|
||||
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 = 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, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3];
|
||||
};
|
||||
|
||||
return SVGPath;
|
||||
|
||||
})();
|
||||
|
||||
module.exports = SVGPath;
|
||||
|
||||
}).call(this);
|
@ -0,0 +1,73 @@
|
||||
###
|
||||
PDFReference - represents a reference to another object in the PDF object heirarchy
|
||||
By Devon Govett
|
||||
###
|
||||
|
||||
zlib = require 'zlib'
|
||||
stream = require 'stream'
|
||||
|
||||
class PDFReference extends stream.Writable
|
||||
constructor: (@document, @id, @data = {}) ->
|
||||
super decodeStrings: no
|
||||
@gen = 0
|
||||
@deflate = null
|
||||
@compress = @document.compress and not @data.Filter
|
||||
@uncompressedLength = 0
|
||||
@chunks = []
|
||||
|
||||
initDeflate: ->
|
||||
@data.Filter = 'FlateDecode'
|
||||
|
||||
@deflate = zlib.createDeflate()
|
||||
@deflate.on 'data', (chunk) =>
|
||||
@chunks.push chunk
|
||||
@data.Length += chunk.length
|
||||
|
||||
@deflate.on 'end', @finalize
|
||||
|
||||
_write: (chunk, encoding, callback) ->
|
||||
unless Buffer.isBuffer(chunk)
|
||||
chunk = new Buffer(chunk + '\n', 'binary')
|
||||
|
||||
@uncompressedLength += chunk.length
|
||||
@data.Length ?= 0
|
||||
|
||||
if @compress
|
||||
@initDeflate() if not @deflate
|
||||
@deflate.write chunk
|
||||
else
|
||||
@chunks.push chunk
|
||||
@data.Length += chunk.length
|
||||
|
||||
callback()
|
||||
|
||||
end: (chunk) ->
|
||||
super
|
||||
|
||||
if @deflate
|
||||
@deflate.end()
|
||||
else
|
||||
@finalize()
|
||||
|
||||
finalize: =>
|
||||
@offset = @document._offset
|
||||
|
||||
@document._write "#{@id} #{@gen} obj"
|
||||
@document._write PDFObject.convert(@data)
|
||||
|
||||
if @chunks.length
|
||||
@document._write 'stream'
|
||||
for chunk in @chunks
|
||||
@document._write chunk
|
||||
|
||||
@chunks.length = 0 # free up memory
|
||||
@document._write '\nendstream'
|
||||
|
||||
@document._write 'endobj'
|
||||
@document._refEnd(this)
|
||||
|
||||
toString: ->
|
||||
return "#{@id} #{@gen} R"
|
||||
|
||||
module.exports = PDFReference
|
||||
PDFObject = require './object'
|
@ -0,0 +1,109 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
|
||||
/*
|
||||
PDFReference - represents a reference to another object in the PDF object heirarchy
|
||||
By Devon Govett
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var PDFObject, PDFReference, stream, zlib,
|
||||
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
zlib = require('zlib');
|
||||
|
||||
stream = require('stream');
|
||||
|
||||
PDFReference = (function(superClass) {
|
||||
extend(PDFReference, superClass);
|
||||
|
||||
function PDFReference(document, id, data) {
|
||||
this.document = document;
|
||||
this.id = id;
|
||||
this.data = data != null ? data : {};
|
||||
this.finalize = bind(this.finalize, this);
|
||||
PDFReference.__super__.constructor.call(this, {
|
||||
decodeStrings: false
|
||||
});
|
||||
this.gen = 0;
|
||||
this.deflate = null;
|
||||
this.compress = this.document.compress && !this.data.Filter;
|
||||
this.uncompressedLength = 0;
|
||||
this.chunks = [];
|
||||
}
|
||||
|
||||
PDFReference.prototype.initDeflate = function() {
|
||||
this.data.Filter = 'FlateDecode';
|
||||
this.deflate = zlib.createDeflate();
|
||||
this.deflate.on('data', (function(_this) {
|
||||
return function(chunk) {
|
||||
_this.chunks.push(chunk);
|
||||
return _this.data.Length += chunk.length;
|
||||
};
|
||||
})(this));
|
||||
return this.deflate.on('end', this.finalize);
|
||||
};
|
||||
|
||||
PDFReference.prototype._write = function(chunk, encoding, callback) {
|
||||
var base;
|
||||
if (!Buffer.isBuffer(chunk)) {
|
||||
chunk = new Buffer(chunk + '\n', 'binary');
|
||||
}
|
||||
this.uncompressedLength += chunk.length;
|
||||
if ((base = this.data).Length == null) {
|
||||
base.Length = 0;
|
||||
}
|
||||
if (this.compress) {
|
||||
if (!this.deflate) {
|
||||
this.initDeflate();
|
||||
}
|
||||
this.deflate.write(chunk);
|
||||
} else {
|
||||
this.chunks.push(chunk);
|
||||
this.data.Length += chunk.length;
|
||||
}
|
||||
return callback();
|
||||
};
|
||||
|
||||
PDFReference.prototype.end = function(chunk) {
|
||||
PDFReference.__super__.end.apply(this, arguments);
|
||||
if (this.deflate) {
|
||||
return this.deflate.end();
|
||||
} else {
|
||||
return this.finalize();
|
||||
}
|
||||
};
|
||||
|
||||
PDFReference.prototype.finalize = function() {
|
||||
var chunk, i, len, ref;
|
||||
this.offset = this.document._offset;
|
||||
this.document._write(this.id + " " + this.gen + " obj");
|
||||
this.document._write(PDFObject.convert(this.data));
|
||||
if (this.chunks.length) {
|
||||
this.document._write('stream');
|
||||
ref = this.chunks;
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
chunk = ref[i];
|
||||
this.document._write(chunk);
|
||||
}
|
||||
this.chunks.length = 0;
|
||||
this.document._write('\nendstream');
|
||||
}
|
||||
this.document._write('endobj');
|
||||
return this.document._refEnd(this);
|
||||
};
|
||||
|
||||
PDFReference.prototype.toString = function() {
|
||||
return this.id + " " + this.gen + " R";
|
||||
};
|
||||
|
||||
return PDFReference;
|
||||
|
||||
})(stream.Writable);
|
||||
|
||||
module.exports = PDFReference;
|
||||
|
||||
PDFObject = require('./object');
|
||||
|
||||
}).call(this);
|
@ -0,0 +1 @@
|
||||
../acorn/bin/acorn
|
@ -0,0 +1 @@
|
||||
../brfs/bin/cmd.js
|
@ -0,0 +1 @@
|
||||
../browser-pack/bin/cmd.js
|
@ -0,0 +1 @@
|
||||
../browserify/bin/cmd.js
|
@ -0,0 +1 @@
|
||||
../coffee-script/bin/cake
|
@ -0,0 +1 @@
|
||||
../coffee-script/bin/coffee
|
@ -0,0 +1 @@
|
||||
../deps-sort/bin/cmd.js
|
@ -0,0 +1 @@
|
||||
../escodegen/bin/escodegen.js
|
@ -0,0 +1 @@
|
||||
../escodegen/bin/esgenerate.js
|
@ -0,0 +1 @@
|
||||
../esprima/bin/esparse.js
|
@ -0,0 +1 @@
|
||||
../esprima/bin/esvalidate.js
|
@ -0,0 +1 @@
|
||||
../exorcist/bin/exorcist.js
|
@ -0,0 +1 @@
|
||||
../insert-module-globals/bin/cmd.js
|
@ -0,0 +1 @@
|
||||
../jade/bin/jade.js
|
@ -0,0 +1 @@
|
||||
../markdown/bin/md2html.js
|
@ -0,0 +1 @@
|
||||
../module-deps/cmd.js
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue