├── .gitignore
├── .npmrc
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── binding.gyp
├── examples
└── docker
│ ├── .dockerignore
│ ├── Dockerfile
│ ├── index.js
│ └── package.json
├── gs4js-env-dll.js
├── gs4js-env-home.js
├── gs4js-env-lib.js
├── index.js
├── lib
├── ghostscript4js.js
└── index.js
├── macOS-lib-path-finder.js
├── node-love-ghostscript.png
├── package.json
├── src
├── ghostscript4js.cc
├── ghostscript4js.h
└── iapi.h
└── test
├── ghostscript4js.js
├── invalid.pdf
├── jasmine.json
├── node-love-ghostscript.pdf
└── node-love-ghostscript.ps
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | npm-debug.log*
3 |
4 | # Compiled binary addons (http://nodejs.org/api/addons.html)
5 | build
6 |
7 | # Dependency directories
8 | node_modules
9 |
10 | # Metadata for IntelliJ IDEA IDEs
11 | .idea
12 |
13 | # Metadata for VSCode
14 | .vscode
15 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 3.2.3 / 2024-06-24
4 |
5 | * Fixed error on `package.json`.
6 |
7 | ## 3.2.2 / 2024-06-24
8 |
9 | * Fixed build error on macOS [#69](https://github.com/NickNaso/ghostscript4js/pull/69).
10 |
11 | ## 3.2.1 / 2020-02-24
12 |
13 | * Fixed typo on error message.
14 |
15 | ## 3.2.0 / 2020-02-24
16 |
17 | * Segmentation fault on multiple runs - Fix issue [#47](https://github.com/NickNaso/ghostscript4js/issues/47)
18 | * Execution stop with: double free or corruption - Fix issue [#49](https://github.com/NickNaso/ghostscript4js/issues/49)
19 | * Error when calling gs.executeSync - Fix issue [#50](https://github.com/NickNaso/ghostscript4js/issues/50)
20 |
21 | ## 3.1.1 / 2019-07-23
22 |
23 | * Improvements on documentation
24 |
25 | ## 3.1.0 / 2019-03-18
26 |
27 | * Fixed and improved the error handling. For more explanations see the PR [#41](https://github.com/NickNaso/ghostscript4js/pull/41)
28 | - Add unit test to intercept the error
29 | - Change GhostscriptManager to throw string instead of char*
30 | - Change SetError call to set exception string
31 | - Fix test to not hardcode ghostscript version to 2017
32 |
33 | ## 3.0.0 / 2018-07-05
34 |
35 | * Complete the port to N-API using node-addon-api
36 | * Undefinedfilename error on Windows if file path contains spaces - Fix issue [#33](https://github.com/NickNaso/ghostscript4js/issues/33)
37 | * Added code of conduct
38 | * Small updates on documentation - executeSync and execute function allow to pass array of strings as arguments.
39 | * Verified and updated the compatibility against the ghostscript version 9.23
40 |
41 | ## 2.0.11-n-api / 2018-03-22
42 |
43 | * Empty output with when using pdfwrite - Fix issue [#30](https://github.com/NickNaso/ghostscript4js/issues/30)
44 | * N-API porting of ghostscript4js - Fix issue [#29](https://github.com/NickNaso/ghostscript4js/issues/29)
45 | * Ghostscript 9.22 - Fix issue [#27](https://github.com/NickNaso/ghostscript4js/issues/27)
46 |
47 | ## 2.0.7 / 2017-02-09
48 |
49 | * Issue with the new update ghostscript4js@2.0.5 - Fix issue [#24](https://github.com/NickNaso/ghostscript4js/issues/24)
50 |
51 | ## 2.0.5 / 2017-01-09
52 |
53 | * GS4JS_LIB variable isn't used - Fix issue [#23](https://github.com/NickNaso/ghostscript4js/issues/23)
54 |
55 | ## 2.0.3 / 2017-30-06
56 |
57 | * Specify --c++11 and --libc++ cplusplus flags in node-gyp settings - PR [#22](https://github.com/NickNaso/ghostscript4js/pull/22)
58 |
59 | * Removed V8 API in the initialization code for the add-ons
60 |
61 | ## 2.0.1 / 2017-18-04
62 |
63 | * Warning on Microsoft compiler - Fix issue [#18](https://github.com/NickNaso/ghostscript4js/issues/18)
64 |
65 | * Removed unused file **g4js-env-home.js**
66 |
67 | ## 2.0.0 / 2017-18-04
68 |
69 | * **`ghostscript4js`** support for Ghostscript **9.21**. For more info see the [changelog](https://ghostscript.com/doc/9.21/News.htm).
70 |
71 | * Fix typo and other little errors in documentation.
72 |
73 | * Problem calling execute method multiple time consecutively - Fix issue [#15](https://github.com/NickNaso/ghostscript4js/issues/15).
74 |
75 | ## 1.0.19 / 2017-06-04
76 |
77 | * Invalid file path problem - Fix issue [#16](https://github.com/NickNaso/ghostscript4js/issues/16).
78 |
79 | ## 1.0.11 / 2017-11-03
80 |
81 | * Installation problem - Fix issue [#13](https://github.com/NickNaso/ghostscript4js/issues/14).
82 |
83 | ## 1.0.7 / 2017-03-03
84 |
85 | * Added compatibility with Ghostscript version.
86 |
87 | * Fix issue [#13](https://github.com/NickNaso/ghostscript4js/issues/13).
88 |
89 | ## 1.0.5 / 2017-02-22
90 |
91 | * Fix in documentation of **`ghostscript4js`**.
92 |
93 | ## 1.0.3 / 2017-02-20
94 |
95 | * Fix in documentation of **`ghostscript4js`**.
96 |
97 | ## 1.0.0 / 2017-02-20
98 |
99 | * Initial version of **`ghostscript4js`** binds the Ghostscript C API to bring Ghostscript power to the Node.JS world.
100 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | education, socio-economic status, nationality, personal appearance, race,
10 | religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at nicoladelgobbo@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Ghostscript4JS
6 | ## This module binds the Ghostscript C API to bring its power to the Node.JS world
7 |
8 | * [Introduction](#introduction)
9 | * [Motivations](#motivations)
10 | * [Prerequisites](#prerequisites)
11 | * [Installation](#install)
12 | * [Installation options](#installoptions)
13 | * [Usage](#usage)
14 | * [Docker](#docker)
15 | * [Code of conduct](CODE_OF_CONDUCT.md)
16 | * [Team](#team)
17 | * [Acknowledgements](#acknowledgements)
18 | * [License](#license)
19 |
20 |
21 |
22 |
23 | ## Introduction
24 |
25 | **Ghostscript** is a suite of software based on an interpreter for Adobe Systems' PostScript and Portable Document Format (PDF)
26 | page description languages. Its main purposes are the rasterization or rendering of such page description language files,
27 | for the display or printing of document pages, and the conversion between PostScript and PDF files.
28 |
29 | Ghostscript can be used as a raster image processor (RIP) for raster computer printers—for instance, as an input filter
30 | of line printer daemon—or as the RIP engine behind PostScript and PDF viewers.
31 |
32 | Ghostscript can also be used as a file format converter, such as PostScript to PDF converter. The **ps2pdf** conversion program,
33 | which comes with the ghostscript distribution, is described by its documentation as a "work-alike for nearly all the functionality
34 | (but not the user interface) of Adobe's Acrobat Distiller product".[3] This converter is basically a thin wrapper around
35 | ghostscript's pdfwrite output device, which supports PDF/A-1 and PDF/A-2 as well as PDF/X-3 output.[3]
36 |
37 | Ghostscript can also serve as the back-end for **PDF** to **raster image** (png, tiff, jpeg, etc.) converter; this is often
38 | combined with a PostScript printer driver in "virtual printer" PDF creators.
39 |
40 | As it takes the form of a language interpreter, Ghostscript can also be used as a general purpose programming environment.
41 |
42 | Ghostscript has been ported to many operating systems, including Unix-like systems, classic **Mac OS**, **OpenVMS**, **Microsoft Windows**,
43 | **Plan 9**, **MS-DOS**, **FreeDOS**, **OS/2**, **Atari TOS and AmigaOS**.
44 |
45 | ### More resource and info about Ghostscript
46 |
47 | * [Introduction to Ghostscript](https://www.gnu.org/software/ghostscript/intro.html)
48 |
49 | * [Ghostscript on Wikipedia](https://en.wikipedia.org/wiki/Ghostscript)
50 |
51 | * [Ghostscript documentation](https://www.ghostscript.com/Documentation.html)
52 |
53 |
54 |
55 | ## Motivations
56 |
57 | At the time i created this module i was not able to find any module on npm that execute Ghostscript command through its C API,
58 | otherwise there were some module that call Ghostscript through the execution of the corresponding shell command. This is a
59 | good way to start using some library from node, but there are the following drawbacks:
60 |
61 | * **Performance** - The call to the shell command take more time and more resources than calling a library C or C++ API directly from Node.js environment.
62 |
63 | * **Errror handler** - Sometimes you cannot intercept and handle errors in a good and a proper way.
64 |
65 | To fit all needs Ghostscript4JS has sync and async methods so it could be used in a web application where it's very important
66 | to not block the event loop, so all requests will be served without any delay originated by our application.
67 |
68 | [Understanding Node.js event loop](https://nodesource.com/blog/understanding-the-nodejs-event-loop/)
69 |
70 |
71 |
72 | ## Prerequisites
73 |
74 | Before installing Ghostscript4JS you need to assure you have the following prerequisites:
75 |
76 | * **Node.JS** see: [Installing Node.js via package manager](https://nodejs.org/en/download/package-manager/)
77 |
78 | * **Node.js native addon build tool** see: [node-gyp](https://github.com/nodejs/node-gyp)
79 |
80 | * **Ghostscript** for your Operating System.
81 |
82 | ## At moment Ghostscript4JS is fully compatible with Ghostscript from version 9.19 to 9.50
83 |
84 | ## Linux
85 |
86 | ### Debian systems
87 |
88 | Install Ghostscript
89 |
90 | ```bash
91 | apt-get install ghostscript libgs-dev
92 | ```
93 |
94 | At this point you need to set the enviroment variable **GS4JS_HOME** to ```/usr/lib/x86_64-linux-gnu```
95 |
96 | ### Red Hat | Fedora
97 |
98 | ```bash
99 | yum install ghostscript ghostscript-devel
100 | ```
101 |
102 | At this point you need to set the enviroment variable **GS4JS_HOME** to ```/usr/lib64``` or ```/usr/lib``` based on you architecture
103 |
104 | ### Arch Linux
105 | ```
106 | pacman -S ghostscript
107 | ```
108 | At this point you need to set the enviroment variable **GS4JS_HOME** to ```/usr/lib```
109 |
110 | ### Alpine
111 | ```
112 | apk add ghostscript
113 | ```
114 | At this point you need to set the enviroment variable **GS4JS_HOME** to ```/usr/lib```
115 |
116 | In general, based on your Linux OS and architecture, you have to set the environment variable **GS4JS_HOME** to point on folder containing ```libgs.so``` library.
117 |
118 | ## Windows
119 |
120 | * Download last Ghostscript version for your platform [x86](https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs920/gs920w32.exe) or [x64](https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs920/gs920w64.exe)
121 |
122 | * Install Ghostscript on your system, for example in ```C:\gs```
123 |
124 | * Add the environment variable **GS4JS_HOME** to point to a folder containing Ghostscript's DLL and Library files (Es. gsdll64.dll and gsdll64.lib). Typically, they are located in **bin** folder of you ghostscript installation, for example ```C:\gs\bin```
125 |
126 | ## macOS
127 |
128 | * Install Homebrew following the official guide [here](https://brew.sh/index_it.html)
129 |
130 | * Open terminal and install Ghostscript
131 |
132 | ```bash
133 | brew install ghostscript
134 | ```
135 |
136 | * Set the environment variable **GS4JS_HOME** to ```/usr/local/lib```
137 |
138 | ## Official installation guide to install Ghostscript
139 |
140 | * [Installation from official documentation](https://ghostscript.com/doc/current/Install.htm)
141 |
142 | * [Download Ghostscript](https://ghostscript.com/download/gsdnld.html)
143 |
144 |
145 |
146 | ## Installation
147 |
148 | If you want to use ghostscript4js you have to install it. There are two methods for that:
149 |
150 | In dependencies of your ```package.json``` add the following item:
151 |
152 | ```json
153 | "ghostscript4js": "version"
154 | ```
155 |
156 | then digit
157 |
158 | ```console
159 | npm install
160 | ```
161 |
162 | **Example**:
163 |
164 | ```json
165 | "ghostscript4js": "*" for the latest version
166 | "ghostscript4js": "1.0.0" for the version 1.0.0
167 | ```
168 |
169 | **OR**
170 |
171 | launch this command:
172 |
173 | ```console
174 | npm install ghostscript4js --save
175 | ```
176 |
177 |
178 |
179 | ## Installation options
180 |
181 | The module ghostscript4js allows you to use some installation options that you can use when in your operating system something is different against standard installation.
182 |
183 | **--GS4JS_HOME** Set the GS4JS_HOME variable that represents the path in your system where is located the ghostscript library
184 |
185 | Es. ```npm install ghostscript4js --GS4JS_HOME="C:/gs/bin"```
186 |
187 | **--GS4JS_LIB** Set the GS4JS_LIB variable that represents the file name for the ghostscript library installed in your system
188 |
189 | Es. ```npm install ghostscript4js --GS4JS_LIB="libgs.so"```
190 |
191 | ### Only for Windows
192 |
193 | **--GS4JS_DLL** Set the GS4JS_DLL variable that represents the file name for the ghostscript DLL installed in your windows system
194 |
195 | Es. ```npm install ghostscript4js --GS4JS_DLL="gsdll64.dll"```
196 |
197 |
198 |
199 | ## Usage
200 |
201 | ```js
202 | 'use strict'
203 |
204 | const gs = require('ghostscript4js')
205 |
206 | try {
207 | // Take decision based on Ghostscript version
208 | const version = gs.version()
209 | console.log(version)
210 | gs.executeSync('-sDEVICE=pngalpha -o my.png -sDEVICE=pngalpha -r144 my.pdf')
211 | } catch (err) {
212 | // Handle error
213 | throw err
214 | }
215 | ```
216 |
217 | ## API
218 |
219 | ### version
220 |
221 | **version()** method returns an object that contains information about version of Ghostscript library
222 | installed on the system. It is important in those circumstances where you have to take
223 | decision based on different version.
224 | The returned data are similar to the example repoted below:
225 |
226 | ```js
227 | {
228 | product: "GPL Ghostscript",
229 | copyright: "Copyright (C) 2016 Artifex Software, Inc. All rights reserved.",
230 | revision: 919,
231 | revisiondate: 20160323
232 | }
233 | ```
234 |
235 | This is a synchronous method and returns the version info or throws an Error to indicate that
236 | something went wrong during its execution.
237 |
238 | #### Example - version
239 |
240 | ```js
241 | 'use strict'
242 |
243 | const gs = require('ghostscript4js')
244 |
245 | try {
246 | const version = gs.version()
247 | console.log(version)
248 | // Take decision based on Ghostscript version
249 | if (version.revision > 916) {
250 | // ... some stuff
251 | } else {
252 | // ... other stuff
253 | }
254 | } catch (err) {
255 | // Handle error
256 | throw err
257 | }
258 | ```
259 |
260 | ### executeSync
261 |
262 | **executeSync(cmd)** method takes the Ghostscript command parameters in input as a string or array of strings and executes in a synchronous way.
263 | If something wrong happens in calling this method an Error with description and code error will be thrown.
264 |
265 | #### Example - executeSync
266 |
267 | ```js
268 | 'use strict'
269 |
270 | const gs = require('ghostscript4js')
271 |
272 | try {
273 | gs.executeSync('-sDEVICE=pngalpha -o my.png -sDEVICE=pngalpha -r144 my.pdf')
274 | } catch (err) {
275 | // Handle error
276 | throw err
277 | }
278 | ```
279 |
280 | ### execute
281 |
282 | **execute(cmd, callback)** method takes in input the Ghostscript command parameters as a string or array of strings and an optional callback. The execution will be asynchronous so this ensure better performance especially in a web application enviroment, because it'll not block the Node.Js event loop.
283 | This method has an optional callback function as input, in that case, a possible error will be handled by this function. If noone function will be provided the method returns a Promise that will be resolved or rejected as reported in the following example.
284 |
285 | #### Example - execute
286 |
287 | ```js
288 | 'use strict'
289 |
290 | const gs = require('ghostscript4js')
291 |
292 | let cmd = '-sDEVICE=pngalpha -o my.png -sDEVICE=pngalpha -r144 my.pdf'
293 | gs.execute(cmd, function (err) {
294 | if (err) {
295 | console.log("Ooops... something wrong happened")
296 | }
297 | })
298 |
299 | ```
300 |
301 | ```js
302 | 'use strict'
303 |
304 | const gs = require('ghostscript4js')
305 |
306 | let cmd = '-sDEVICE=pngalpha -o my.png -sDEVICE=pngalpha -r144 my.pdf'
307 | gs.execute(cmd)
308 | .then(() => {
309 | console.log("All is ok")
310 | })
311 | .catch((err) => {
312 | console.log("Ooops... something wrong happened")
313 | })
314 |
315 | ```
316 |
317 | ### Error
318 |
319 | The error raised from **ghostscript4js** in all of its method is an instance of Error object that cointains a message that
320 | describes what happened and at the same time cointains the Ghostscript error code so you can inspect what happened in a better
321 | way. At this link [Ghostscript error codes](https://ghostscript.com/doc/current/API.htm#return_codes) you can find all Ghostscript errors code.
322 |
323 | ### Min and Max supported revision
324 |
325 | This module was built based on Ghostscript C API that is compatible with some specifics versions. The module has two
326 | properties **MIN_SUPPORTED_REVISION** and **MAX_SUPPORTED_REVISION** which respectively indicate the minimum and maximum supported Ghostscript's version.
327 |
328 | #### Example - Min and Max supported revision
329 |
330 | ```js
331 | 'use strict'
332 |
333 | const gs = require('ghostscript4js')
334 |
335 | console.log(gs.MIN_SUPPORTED_REVISION)
336 | console.log(gs.MAX_SUPPORTED_REVISION)
337 |
338 | ```
339 |
340 |
341 |
342 | ## Docker
343 |
344 | Check out the example `Dockerfile` in `examples/docker`. It will create an image based on node 8.x and Debian stretch.
345 |
346 | To build the image do:
347 |
348 |
349 | ```
350 | cd examples/docker
351 | docker build -t ghostscript4js .
352 | ```
353 |
354 | Now you can run the image. By default it does `npm start` (which is `node index.js`) and exits.
355 |
356 | ```
357 | docker run ghostscript4js
358 | ```
359 |
360 | Running the container should output something like:
361 |
362 | ```
363 | { product: 'GPL Ghostscript',
364 | copyright: 'Copyright (C) 2016 Artifex Software, Inc. All rights reserved.',
365 | revision: 920,
366 | revisiondate: 20160926 }
367 | ```
368 |
369 | If you want to look around in the container you can get a shell like:
370 |
371 | ```
372 | docker run -it ghostscript4js /bin/bash
373 | gs --version
374 | ```
375 |
376 |
377 |
378 | ## The Team
379 |
380 | ### Nicola Del Gobbo
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 | ### Mauro Doganieri
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 | ## Acknowledgements
399 |
400 | Thank you to all people that encourage me every day.
401 |
402 |
403 |
404 | ## License
405 |
406 | Licensed under [Apache license V2](./LICENSE)
407 |
--------------------------------------------------------------------------------
/binding.gyp:
--------------------------------------------------------------------------------
1 | {
2 | "targets": [
3 | {
4 | "target_name": "ghostscript4js",
5 | "sources": ["src/ghostscript4js.cc"],
6 | 'cflags!': [ '-fno-exceptions' ],
7 | 'cflags_cc!': [ '-fno-exceptions' ],
8 | "include_dirs": [
9 | " (https://www.prinzhorn.it/)",
11 | "license": "Apache-2.0",
12 | "private": true,
13 | "dependencies": {
14 | "ghostscript4js": "^2.0.7"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/gs4js-env-dll.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2017 Nicola Del Gobbo
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 | * use this file except in compliance with the License. You may obtain a copy of
5 | * the license at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
9 | * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | * MERCHANTABLITY OR NON-INFRINGEMENT.
11 | *
12 | * See the Apache Version 2.0 License for specific language governing
13 | * permissions and limitations under the License.
14 | *
15 | * Contributors - initial API implementation:
16 | * Nicola Del Gobbo
17 | * Mauro Doganieri
18 | ******************************************************************************/
19 |
20 | 'use strict'
21 |
22 | let GS4JS_DLL = ""
23 | if (process.env.GS4JS_DLL) {
24 | GS4JS_DLL = process.env.GS4JS_DLL
25 | GS4JS_DLL = GS4JS_DLL.split("\\").join("/")
26 | }
27 | process.stdout.write(GS4JS_DLL)
28 |
--------------------------------------------------------------------------------
/gs4js-env-home.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2017 Nicola Del Gobbo
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 | * use this file except in compliance with the License. You may obtain a copy of
5 | * the license at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
9 | * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | * MERCHANTABLITY OR NON-INFRINGEMENT.
11 | *
12 | * See the Apache Version 2.0 License for specific language governing
13 | * permissions and limitations under the License.
14 | *
15 | * Contributors - initial API implementation:
16 | * Nicola Del Gobbo
17 | * Mauro Doganieri
18 | ******************************************************************************/
19 |
20 | 'use strict'
21 |
22 | let GS4JS_HOME = ""
23 | if (process.env.GS4JS_HOME) {
24 | GS4JS_HOME = process.env.GS4JS_HOME
25 | GS4JS_HOME = GS4JS_HOME.split("\\").join("/")
26 | }
27 | process.stdout.write(GS4JS_HOME)
28 |
--------------------------------------------------------------------------------
/gs4js-env-lib.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2017 Nicola Del Gobbo
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 | * use this file except in compliance with the License. You may obtain a copy of
5 | * the license at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
9 | * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | * MERCHANTABLITY OR NON-INFRINGEMENT.
11 | *
12 | * See the Apache Version 2.0 License for specific language governing
13 | * permissions and limitations under the License.
14 | *
15 | * Contributors - initial API implementation:
16 | * Nicola Del Gobbo
17 | * Mauro Doganieri
18 | ******************************************************************************/
19 |
20 | 'use strict'
21 |
22 | let GS4JS_LIB = ""
23 | if (process.env.GS4JS_LIB) {
24 | GS4JS_LIB = process.env.GS4JS_LIB
25 | GS4JS_LIB = GS4JS_LIB.split("\\").join("/")
26 | }
27 | process.stdout.write(GS4JS_LIB)
28 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2017 Nicola Del Gobbo
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 | * use this file except in compliance with the License. You may obtain a copy of
5 | * the license at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
9 | * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | * MERCHANTABLITY OR NON-INFRINGEMENT.
11 | *
12 | * See the Apache Version 2.0 License for specific language governing
13 | * permissions and limitations under the License.
14 | *
15 | * Contributors - initial API implementation:
16 | * Nicola Del Gobbo
17 | * Mauro Doganieri
18 | ******************************************************************************/
19 |
20 | 'use strict'
21 |
22 | module.exports = require('./lib')
23 |
--------------------------------------------------------------------------------
/lib/ghostscript4js.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2017 Nicola Del Gobbo
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 | * use this file except in compliance with the License. You may obtain a copy of
5 | * the license at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
9 | * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | * MERCHANTABLITY OR NON-INFRINGEMENT.
11 | *
12 | * See the Apache Version 2.0 License for specific language governing
13 | * permissions and limitations under the License.
14 | *
15 | * Contributors - initial API implementation:
16 | * Nicola Del Gobbo
17 | * Mauro Doganieri
18 | ******************************************************************************/
19 |
20 | 'use strict'
21 |
22 | /*!
23 | * Module dependencies
24 | */
25 | const gs = require('bindings')('ghostscript4js')
26 |
27 | module.exports = {
28 |
29 | MAX_SUPPORTED_REVISION: 950,
30 |
31 | MIN_SUPPORTED_REVISION: 919,
32 |
33 | version() {
34 | return gs.version()
35 | },
36 |
37 | execute(cmd, callback) {
38 | if (!callback) {
39 | return new Promise((resolve, reject) => {
40 | gs.execute(cmd, (err) => {
41 | if (err) {
42 | reject(err)
43 | }
44 | resolve()
45 | })
46 | });
47 | } else {
48 | if (typeof callback !== 'function') {
49 | throw new TypeError('Parameter callback must be a function')
50 | }
51 | return gs.execute(cmd, callback)
52 | }
53 | },
54 |
55 | executeSync(cmd) {
56 | return gs.executeSync(cmd)
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2017 Nicola Del Gobbo
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 | * use this file except in compliance with the License. You may obtain a copy of
5 | * the license at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
9 | * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | * MERCHANTABLITY OR NON-INFRINGEMENT.
11 | *
12 | * See the Apache Version 2.0 License for specific language governing
13 | * permissions and limitations under the License.
14 | *
15 | * Contributors - initial API implementation:
16 | * Nicola Del Gobbo
17 | * Mauro Doganieri
18 | ******************************************************************************/
19 |
20 | 'use strict'
21 |
22 | module.exports = require('./ghostscript4js')
--------------------------------------------------------------------------------
/macOS-lib-path-finder.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const { promisify } = require('util')
4 | const exec = promisify(require('child_process').exec)
5 | const {stat} = require('fs').promises
6 | const path = require('path')
7 |
8 |
9 | const LIBRARY = 'libgs.dylib'
10 | const SYSTEM_PATH = '/usr/local/lib'
11 |
12 | const isLibraryExists = async (libraryPath) => {
13 | try {
14 | await stat(libraryPath)
15 | return true
16 | } catch (err) {
17 | return false
18 | }
19 | }
20 |
21 | const isInstalled = async (command) => {
22 | try {
23 | await exec(`which ${command}`)
24 | return true
25 | } catch (err) {
26 | return false
27 | }
28 |
29 | }
30 |
31 |
32 | async function main() {
33 | try {
34 | let isGSExists = false
35 | isGSExists = await isLibraryExists(path.join(SYSTEM_PATH, LIBRARY))
36 | if (isGSExists) {
37 | process.stdout.write(SYSTEM_PATH)
38 | return
39 | } else {
40 | if (!await isInstalled('brew')) {
41 | return 1
42 | }
43 | if (!await isInstalled('gs')) {
44 | return 1
45 | }
46 | const cellarPath = (await exec('brew --cellar')).stdout
47 | const gsVersion = (await exec('gs --version')).stdout
48 | const gsLibraryPath = path.join(cellarPath.trim(), 'ghostscript', gsVersion.trim(), 'lib')
49 | isGSExists = await isLibraryExists(path.join(gsLibraryPath, LIBRARY))
50 |
51 | if (isGSExists) {
52 | process.stdout.write(gsLibraryPath)
53 | return
54 | } else {
55 | return 1
56 | }
57 | }
58 | } catch (err) {
59 | process.emitWarning(err)
60 | return 1
61 | }
62 |
63 | }
64 |
65 | main()
--------------------------------------------------------------------------------
/node-love-ghostscript.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickNaso/ghostscript4js/1b06fe0aa2076b1a7ef9765e6d67daa0e4c87634/node-love-ghostscript.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ghostscript4js",
3 | "description": "Bindings for the Ghostscript C API to the Node.JS world.",
4 | "version": "3.2.3",
5 | "contributors": [
6 | {
7 | "name": "Nicola Del Gobbo",
8 | "email": "nicoladelgobbo@gmail.com"
9 | },
10 | {
11 | "name": "Mauro Doganieri",
12 | "email": "mauro.doganieri@gmail.com"
13 | },
14 | {
15 | "name": "Alexander Prinzhorn",
16 | "email": "alexander@prinzhorn.it"
17 | },
18 | {
19 | "name": "Eric Semeniuc",
20 | "url": "https://github.com/esemeniuc"
21 | },
22 | {
23 | "name": "George Gershevich",
24 | "email": "george.gershevich@gmail.com"
25 | },
26 | {
27 | "name": "Loren Yu",
28 | "email": "loren@navapbc.com"
29 | },
30 | {
31 | "name": "Samuel Bronson",
32 | "url": "https://github.com/SamB"
33 | }
34 | ],
35 | "keywords": [
36 | "ghostscript",
37 | "postscript",
38 | "native",
39 | "pdf",
40 | "ps",
41 | "eps"
42 | ],
43 | "license": "Apache-2.0",
44 | "scripts": {
45 | "test": "node node_modules/jasmine/bin/jasmine.js JASMINE_CONFIG_PATH=test/jasmine.json",
46 | "debug": "node-gyp rebuild --debug"
47 | },
48 | "engines": {
49 | "node": ">= 6.0.0"
50 | },
51 | "gypfile": true,
52 | "repository": {
53 | "type": "git",
54 | "url": "https://github.com/NickNaso/ghostscript4js.git"
55 | },
56 | "bugs": {
57 | "url": "https://github.com/NickNaso/ghostscript4js/issues"
58 | },
59 | "homepage": "http://www.nacios.it/",
60 | "dependencies": {
61 | "bindings": "^1.5.0",
62 | "node-addon-api": "^2.0.0"
63 | },
64 | "devDependencies": {
65 | "jasmine": "^3.5.0"
66 | },
67 | "main": "./index.js",
68 | "files": [
69 | "LICENSE",
70 | "README.md",
71 | "CHANGELOG.md",
72 | "CODE_OF_CONDUCT.md",
73 | "binding.gyp",
74 | "index.js",
75 | "gs4js-env-home.js",
76 | "gs4js-env-lib.js",
77 | "gs4js-env-dll.js",
78 | "macOS-lib-path-finder.js",
79 | "binding.gyp",
80 | "lib/",
81 | "src/"
82 | ]
83 | }
84 |
--------------------------------------------------------------------------------
/src/ghostscript4js.cc:
--------------------------------------------------------------------------------
1 | /* ******************************************************************************
2 | * Copyright (c) 2017 Nicola Del Gobbo
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 | * use this file except in compliance with the License. You may obtain a copy of
5 | * the license at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
9 | * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | * MERCHANTABLITY OR NON-INFRINGEMENT.
11 | *
12 | * See the Apache Version 2.0 License for specific language governing
13 | * permissions and limitations under the License.
14 | *
15 | * Contributors - initial API implementation:
16 | * Nicola Del Gobbo
17 | * Mauro Doganieri
18 | ******************************************************************************/
19 |
20 | #include "ghostscript4js.h"
21 |
22 | // Lifeclycle management for the Ghostscript instance
23 | class GhostscriptManager
24 | {
25 | private:
26 | void *minst;
27 | mutex gs;
28 | static GhostscriptManager *instance;
29 | GhostscriptManager()
30 | {
31 | minst = nullptr;
32 | }
33 | void Init();
34 | void Destroy();
35 | void Exit();
36 |
37 | public:
38 | static GhostscriptManager *GetInstance();
39 | ~GhostscriptManager()
40 | {
41 | minst = nullptr;
42 | };
43 | void Execute(int gsargc, char *gsargv[]);
44 | };
45 |
46 | GhostscriptManager *GhostscriptManager::instance = nullptr;
47 | // Static method that create or simple return the instance of the GhostscriptManager
48 | // following the singleton design pattern
49 | GhostscriptManager *GhostscriptManager::GetInstance()
50 | {
51 | if (instance == nullptr)
52 | {
53 | instance = new GhostscriptManager();
54 | }
55 | return instance;
56 | }
57 |
58 | // Init is an implementation of gsapi_new_instance.
59 | // It returns a global static instance of Ghostscript.
60 | // i.e. Do not call init more than once, otherwise an error will be returned.
61 | void GhostscriptManager::Init()
62 | {
63 | int code = 0;
64 | code = gsapi_new_instance(&minst, NULL);
65 | if (code < 0)
66 | {
67 | throw std::runtime_error("Sorry error happened creating Ghostscript instance. Error code: " + to_string(code));
68 | }
69 | code = gsapi_set_arg_encoding(minst, GS_ARG_ENCODING_UTF8);
70 | if (code < 0)
71 | {
72 | throw std::runtime_error("Sorry error happened in setting the encoding for Ghostscript interpreter. Error code: " + to_string(code));
73 | }
74 | }
75 |
76 | // Execute is an implementation of gsapi_init_with_args.
77 | // It initialises the Ghostscript interpreter given a set of arguments.
78 | void GhostscriptManager::Execute(int gsargc, char *gsargv[])
79 | {
80 | lock_guard lk(gs);
81 | Init();
82 | int code = 0;
83 | code = gsapi_init_with_args(minst, gsargc, gsargv);
84 | Exit();
85 | Destroy();
86 | if (code < 0 && code != gs_error_Quit)
87 | {
88 | throw std::runtime_error("Sorry error happened executing Ghostscript command. Error code: " + to_string(code));
89 | }
90 | }
91 |
92 |
93 | // Exit is an implementation of gsapi_exit.
94 | // It exits the Ghostscript interpreter.
95 | // It must be called if init has been called, and just before destroy.
96 | void GhostscriptManager::Exit()
97 | {
98 | int code = 0;
99 | code = gsapi_exit(minst);
100 | if (code < 0 && code != gs_error_Quit)
101 | {
102 | throw std::runtime_error("Sorry error happened during the exit from the Ghostscript interpreter. Error code: " + to_string(code));
103 | }
104 | }
105 |
106 | // Destroy is an implementation of gsapi_delete_instance.
107 | // It destroys a global static instance of Ghostscript.
108 | // It should be called only after exit has been called if init has been called.
109 | void GhostscriptManager::Destroy()
110 | {
111 | gsapi_delete_instance(minst);
112 | minst = nullptr;
113 | }
114 |
115 | class GhostscriptWorker : public Napi::AsyncWorker
116 | {
117 | public:
118 | GhostscriptWorker(Napi::Function& callback, vector explodedCmd)
119 | : Napi::AsyncWorker(callback, "ghostcript4js"), explodedCmd(explodedCmd) {}
120 | ~GhostscriptWorker() {}
121 |
122 | void Execute()
123 | {
124 | int gsargc = static_cast(explodedCmd.size());
125 | char **gsargv = new char *[gsargc];
126 | for (int i = 0; i < gsargc; i++)
127 | {
128 | gsargv[i] = (char *)explodedCmd[i].c_str();
129 | }
130 | try
131 | {
132 | GhostscriptManager *gm = GhostscriptManager::GetInstance();
133 | gm->Execute(gsargc, gsargv);
134 | delete[] gsargv;
135 | }
136 | catch (exception &e)
137 | {
138 | delete[] gsargv;
139 | SetError(e.what());
140 | }
141 | }
142 |
143 | void OnOk()
144 | {
145 | Napi::HandleScope scope(Env());
146 | Callback().Call({Env().Null()});
147 | }
148 |
149 | private:
150 | vector explodedCmd;
151 | };
152 |
153 | Napi::Value Version(const Napi::CallbackInfo& info) {
154 | Napi::Env env = info.Env();
155 | Napi::Object obj = Napi::Object::New(env);
156 | gsapi_revision_t r;
157 | int res = gsapi_revision(&r, sizeof(r));
158 | if (res == 0) {
159 | obj["product"] = Napi::String::New(env, r.product);
160 | obj["copyright"] = Napi::String::New(env, r.copyright);
161 | obj["revision"] = Napi::Number::New(env, r.revision);
162 | obj["revisiondate"] = Napi::Number::New(env, r.revisiondate);
163 | } else {
164 | std::stringstream msg;
165 | msg << "Sorry error happened retrieving Ghostscript version info. Error code: " << res;
166 | throw Napi::Error::New(env, msg.str());
167 | }
168 | return obj;
169 | }
170 |
171 | vector ConvertArguments(const Napi::CallbackInfo& info) {
172 | Napi::Env env = info.Env();
173 | if (info.Length() < 1)
174 | {
175 | throw Napi::Error::New(env, "Sorry method requires 1 argument that represent the Ghostscript command.");
176 | }
177 | if (!info[0].IsString() && !info[0].IsArray())
178 | {
179 | throw Napi::Error::New(env, "Sorry method's argument should be a string or an array of strings");
180 | }
181 | vector explodedCmd;
182 | if (info[0].IsString())
183 | {
184 | string RAWcmd = info[0].As().Utf8Value();
185 | istringstream iss(RAWcmd);
186 | for (string RAWcmd; iss >> RAWcmd;)
187 | explodedCmd.push_back(RAWcmd);
188 | }
189 | if (info[0].IsArray())
190 | {
191 | Napi::Array array = info[0].As();
192 | for (uint32_t i = 0; i < array.Length(); i++)
193 | {
194 | Napi::Value value = array[i];
195 | if (!value.IsString())
196 | {
197 | throw Napi::Error::New(env, "Sorry method's argument should be a string or an array of strings");
198 | }
199 | string RAWcmd = value.As().Utf8Value();
200 | explodedCmd.push_back(RAWcmd);
201 | }
202 | }
203 | return explodedCmd;
204 | }
205 |
206 | void Execute(const Napi::CallbackInfo& info) {
207 | vector explodedCmd = ConvertArguments(info);
208 | Napi::Function callback = info[1].As();
209 | GhostscriptWorker* gs = new GhostscriptWorker(callback, explodedCmd);
210 | gs->Queue();
211 | }
212 |
213 | void ExecuteSync(const Napi::CallbackInfo& info)
214 | {
215 | Napi::Env env = info.Env();
216 | vector explodedCmd = ConvertArguments(info);
217 | int gsargc = static_cast(explodedCmd.size());
218 | char **gsargv = new char *[gsargc];
219 | for (int i = 0; i < gsargc; i++)
220 | {
221 | gsargv[i] = (char *)explodedCmd[i].c_str();
222 | }
223 | try
224 | {
225 | GhostscriptManager *gm = GhostscriptManager::GetInstance();
226 |
227 | gm->Execute(gsargc, gsargv);
228 | delete[] gsargv;
229 | }
230 | catch (exception &e)
231 | {
232 | delete[] gsargv;
233 | throw Napi::Error::New(env, e.what());
234 | }
235 | }
236 |
237 | //////////////////////////// INIT & CONFIG MODULE //////////////////////////////
238 |
239 | Napi::Object Init(Napi::Env env, Napi::Object exports) {
240 | exports.Set(Napi::String::New(env, "version"), Napi::Function::New(env, Version));
241 | exports.Set(Napi::String::New(env, "execute"), Napi::Function::New(env, Execute));
242 | exports.Set(Napi::String::New(env, "executeSync"), Napi::Function::New(env, ExecuteSync));
243 | return exports;
244 | }
245 |
246 | NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
247 |
248 | ////////////////////////////////////////////////////////////////////////////////
249 |
--------------------------------------------------------------------------------
/src/ghostscript4js.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2017 Nicola Del Gobbo
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 | * use this file except in compliance with the License. You may obtain a copy of
5 | * the license at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
9 | * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | * MERCHANTABLITY OR NON-INFRINGEMENT.
11 | *
12 | * See the Apache Version 2.0 License for specific language governing
13 | * permissions and limitations under the License.
14 | *
15 | * Contributors - initial API implementation:
16 | * Nicola Del Gobbo
17 | * Mauro Doganieri
18 | ******************************************************************************/
19 |
20 | #ifndef GHOSTSCRIPT4JS_H
21 | #define GHOSTSCRIPT4JS_H
22 |
23 | #if defined(_WIN32) && !defined(_Windows)
24 | #define _Windows
25 | #endif
26 | #ifdef _Windows
27 | //#define _WINSOCKAPI_
28 | //#include
29 | #define GSDLLEXPORT __declspec(dllimport)
30 | #endif
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #include
38 |
39 | #include "iapi.h"
40 |
41 | #define gs_error_Quit -101
42 |
43 | //using namespace Napi;
44 | using namespace std;
45 |
46 | #endif //GHOSTSCRIPT4JS_H
47 |
--------------------------------------------------------------------------------
/src/iapi.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Public API for Ghostscript interpreter
3 | * for use both as DLL and for static linking.
4 | *
5 | * Should work for Windows, OS/2, Linux, Mac.
6 | *
7 | * DLL exported functions should be as similar as possible to imain.c
8 | * You will need to include "ierrors.h".
9 | *
10 | * Current problems:
11 | * 1. Ghostscript does not support multiple instances.
12 | * 2. Global variables in gs_main_instance_default()
13 | * and gsapi_instance_counter
14 | */
15 |
16 | /* Exported functions may need different prefix
17 | * GSDLLEXPORT marks functions as exported
18 | * GSDLLAPI is the calling convention used on functions exported
19 | * by Ghostscript
20 | * GSDLLCALL is used on callback functions called by Ghostscript
21 | * When you include this header file in the caller, you may
22 | * need to change the definitions by defining these
23 | * before including this header file.
24 | * Make sure you get the calling convention correct, otherwise your
25 | * program will crash either during callbacks or soon after returning
26 | * due to stack corruption.
27 | */
28 |
29 | #ifndef iapi_INCLUDED
30 | # define iapi_INCLUDED
31 |
32 | #ifdef __cplusplus
33 | extern "C" {
34 | #endif
35 |
36 | #if defined(_WINDOWS_) || defined(__WINDOWS__)
37 | # ifndef _Windows
38 | # define _Windows
39 | # endif
40 | #endif
41 |
42 | #ifdef _Windows
43 | # ifndef GSDLLEXPORT
44 | /* We don't need both the "__declspec(dllexport)" declaration
45 | * and the listing in the .def file - having both results in
46 | * a linker warning on x64 builds (but is incorrect on x86, too)
47 | */
48 | # if 0
49 | # define GSDLLEXPORT __declspec(dllexport)
50 | # else
51 | # define GSDLLEXPORT
52 | # endif
53 | # endif
54 | # ifndef GSDLLAPI
55 | # define GSDLLAPI __stdcall
56 | # endif
57 | # ifndef GSDLLCALL
58 | # define GSDLLCALL __stdcall
59 | # endif
60 | #endif /* _Windows */
61 |
62 | #if defined(OS2) && defined(__IBMC__)
63 | # ifndef GSDLLAPI
64 | # define GSDLLAPI _System
65 | # endif
66 | # ifndef GSDLLCALL
67 | # define GSDLLCALL _System
68 | # endif
69 | #endif /* OS2 && __IBMC */
70 |
71 | #ifdef __MACOS__
72 | # pragma export on
73 | #endif
74 |
75 | #ifndef GSDLLEXPORT
76 | # define GSDLLEXPORT
77 | #endif
78 | #ifndef GSDLLAPI
79 | # define GSDLLAPI
80 | #endif
81 | #ifndef GSDLLCALL
82 | # define GSDLLCALL
83 | #endif
84 |
85 | #if defined(__IBMC__)
86 | # define GSDLLAPIPTR * GSDLLAPI
87 | # define GSDLLCALLPTR * GSDLLCALL
88 | #else
89 | # define GSDLLAPIPTR GSDLLAPI *
90 | # define GSDLLCALLPTR GSDLLCALL *
91 | #endif
92 |
93 | #ifndef display_callback_DEFINED
94 | # define display_callback_DEFINED
95 | typedef struct display_callback_s display_callback;
96 | #endif
97 |
98 | typedef struct gsapi_revision_s {
99 | const char *product;
100 | const char *copyright;
101 | long revision;
102 | long revisiondate;
103 | } gsapi_revision_t;
104 |
105 | /* Get version numbers and strings.
106 | * This is safe to call at any time.
107 | * You should call this first to make sure that the correct version
108 | * of the Ghostscript is being used.
109 | * pr is a pointer to a revision structure.
110 | * len is the size of this structure in bytes.
111 | * Returns 0 if OK, or if len too small (additional parameters
112 | * have been added to the structure) it will return the required
113 | * size of the structure.
114 | */
115 | GSDLLEXPORT int GSDLLAPI
116 | gsapi_revision(gsapi_revision_t *pr, int len);
117 |
118 | /*
119 | * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
120 | * Ghostscript supports only one instance.
121 | * The current implementation uses a global static instance
122 | * counter to make sure that only a single instance is used.
123 | * If you try to create two instances, the second attempt
124 | * will return < 0 and set pinstance to NULL.
125 | * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
126 | */
127 | /* Create a new instance of Ghostscript.
128 | * This instance is passed to most other API functions.
129 | * The caller_handle will be provided to callback functions.
130 | */
131 |
132 | GSDLLEXPORT int GSDLLAPI
133 | gsapi_new_instance(void **pinstance, void *caller_handle);
134 |
135 | /*
136 | * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
137 | * Ghostscript supports only one instance.
138 | * The current implementation uses a global static instance
139 | * counter to make sure that only a single instance is used.
140 | * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
141 | */
142 | /* Destroy an instance of Ghostscript
143 | * Before you call this, Ghostscript must have finished.
144 | * If Ghostscript has been initialised, you must call gsapi_exit()
145 | * before gsapi_delete_instance.
146 | */
147 | GSDLLEXPORT void GSDLLAPI
148 | gsapi_delete_instance(void *instance);
149 |
150 | /* Set the encoding used for the args. By default we assume
151 | * 'local' encoding. For windows this equates to whatever the current
152 | * codepage is. For linux this is utf8.
153 | *
154 | * Use of this API (gsapi) with 'local' encodings (and hence without calling
155 | * this function) is now deprecated!
156 | */
157 | GSDLLEXPORT int GSDLLAPI gsapi_set_arg_encoding(void *instance,
158 | int encoding);
159 |
160 | enum {
161 | GS_ARG_ENCODING_LOCAL = 0,
162 | GS_ARG_ENCODING_UTF8 = 1,
163 | GS_ARG_ENCODING_UTF16LE = 2
164 | };
165 |
166 | /* Initialise the interpreter.
167 | * This calls gs_main_init_with_args() in imainarg.c
168 | * 1. If quit or EOF occur during gsapi_init_with_args(),
169 | * the return value will be gs_error_Quit. This is not an error.
170 | * You must call gsapi_exit() and must not call any other
171 | * gsapi_XXX functions.
172 | * 2. If usage info should be displayed, the return value will be gs_error_Info
173 | * which is not an error. Do not call gsapi_exit().
174 | * 3. Under normal conditions this returns 0. You would then
175 | * call one or more gsapi_run_*() functions and then finish
176 | * with gsapi_exit().
177 | */
178 | GSDLLEXPORT int GSDLLAPI gsapi_init_with_args(void *instance,
179 | int argc, char **argv);
180 |
181 | /* Exit the interpreter.
182 | * This must be called on shutdown if gsapi_init_with_args()
183 | * has been called, and just before gsapi_delete_instance().
184 | */
185 | GSDLLEXPORT int GSDLLAPI
186 | gsapi_exit(void *instance);
187 |
188 | /* function prototypes */
189 | typedef int (GSDLLAPIPTR PFN_gsapi_revision)(
190 | gsapi_revision_t *pr, int len);
191 | typedef int (GSDLLAPIPTR PFN_gsapi_new_instance)(
192 | void **pinstance, void *caller_handle);
193 | typedef void (GSDLLAPIPTR PFN_gsapi_delete_instance)(
194 | void *instance);
195 | typedef int (GSDLLAPIPTR PFN_gsapi_init_with_args)(
196 | void *instance, int argc, char **argv);
197 | typedef int (GSDLLAPIPTR PFN_gsapi_set_arg_encoding)(
198 | void *instance, int encoding);
199 | typedef int (GSDLLAPIPTR PFN_gsapi_exit)(void *instance);
200 |
201 | #ifdef __MACOS__
202 | #pragma export off
203 | #endif
204 |
205 | #ifdef __cplusplus
206 | } /* extern 'C' protection */
207 | #endif
208 |
209 | #endif /* iapi_INCLUDED */
210 |
--------------------------------------------------------------------------------
/test/ghostscript4js.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2017 Nicola Del Gobbo
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 | * use this file except in compliance with the License. You may obtain a copy of
5 | * the license at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
9 | * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | * MERCHANTABLITY OR NON-INFRINGEMENT.
11 | *
12 | * See the Apache Version 2.0 License for specific language governing
13 | * permissions and limitations under the License.
14 | *
15 | * Contributors - initial API implementation:
16 | * Nicola Del Gobbo
17 | * Mauro Doganieri
18 | ******************************************************************************/
19 |
20 | 'use strict';
21 |
22 | /*!
23 | * Module dependencies
24 | */
25 | const gs = require('../')
26 | const fs = require('fs')
27 |
28 | process.chdir(__dirname)
29 |
30 | const pdf = 'node-love-ghostscript.pdf'
31 | // Invalid PDF file by taking a text file with Lorem ipsum text and renaming to have .pdf extension
32 | const pdfInvalid = 'invalid.pdf'
33 | const ps = 'node-love-ghostscript.ps'
34 | const pngSync = 'node-love-ghostscript-sync.png'
35 | const pngAsync = 'node-love-ghostscript-async.png'
36 | const pngSyncArray = 'node love ghostscript sync.png'
37 | const pngAsyncArray = 'node love ghostscript async.png'
38 | const pdfSync = 'node-love-ghostscript-sync.pdf'
39 | const pdfAsync = 'node-love-ghostscript-async.pdf'
40 | const pdfSyncArray = 'node love ghostscript sync.pdf'
41 | const pdfAsyncArray = 'node love ghostscript async.pdf'
42 |
43 | const cmdSyncPng = `-psconv -q -dNOPAUSE -sDEVICE=pngalpha -o ${pngSync} -sDEVICE=pngalpha -r144 ${pdf}`
44 | const cmdAsyncPng = `-psconv -q -dNOPAUSE -sDEVICE=pngalpha -o ${pngAsync} -sDEVICE=pngalpha -r144 ${pdf}`
45 | const cmdSyncPngArray = ['-psconv', '-q', '-dNOPAUSE', '-sDEVICE=pngalpha', '-o', `${pngSyncArray}`, '-sDEVICE=pngalpha', '-r144', `${pdf}`]
46 | const cmdAsyncPngArray = ['-psconv', '-q', '-dNOPAUSE', '-sDEVICE=pngalpha', '-o', `${pngAsyncArray}`, '-sDEVICE=pngalpha', '-r144', `${pdf}`]
47 |
48 | const cmdInvalidPdf = `-q -dNOPAUSE -sDEVICE=jpeg -o test/out-%02d.jpg -r144 ${pdfInvalid}`
49 | const cmdSyncPdf = `-psconv -q -dNOPAUSE -sDEVICE=pdfwrite -o ${pdfSync} -f ${ps}`
50 | const cmdAsyncPdf = `-psconv -q -dNOPAUSE -sDEVICE=pdfwrite -o ${pdfAsync} -f ${ps}`
51 | const cmdSyncPdfArray = ['-psconv', '-q', '-dNOPAUSE', '-sDEVICE=pdfwrite', '-o', `${pdfSyncArray}`, '-f', `${ps}`]
52 | const cmdAsyncPdfArray = ['-psconv', '-q', '-dNOPAUSE', '-sDEVICE=pdfwrite', '-o', `${pdfAsyncArray}`, '-f', `${ps}`]
53 |
54 |
55 | function cleanup() {
56 | console.log('Start cleanup ...')
57 | try {
58 | fs.unlinkSync(pngSync)
59 | fs.unlinkSync(pngAsync)
60 | fs.unlinkSync(pdfSync)
61 | fs.unlinkSync(pdfAsync)
62 | fs.unlinkSync(pngSyncArray)
63 | fs.unlinkSync(pngAsyncArray)
64 | fs.unlinkSync(pdfSyncArray)
65 | fs.unlinkSync(pdfAsyncArray)
66 | console.log('Cleanup competed')
67 | } catch (err) {
68 | console.log('Nothing to clean');
69 | }
70 | }
71 |
72 | describe('Test ghostscript4js', function () {
73 |
74 | beforeAll(cleanup)
75 |
76 | it('Should return the version of Ghoscript', function () {
77 | expect(gs.version).not.toThrow()
78 | const version = gs.version()
79 | expect(version.product).toContain('GPL Ghostscript')
80 | expect(version.copyright).toContain('Copyright (C)')
81 | expect(version.copyright).toContain('Artifex Software, Inc. All rights reserved.')
82 | expect(version.product).not.toBeLessThan(gs.MIN_SUPPORTED_REVISION)
83 | expect(version.product).not.toBeLessThan(20160323)
84 | })
85 |
86 | it('Should execute Ghostscript command synchronous', function () {
87 | const executeSync = async function execute() {
88 | return gs.executeSync(cmdSyncPng)
89 | }
90 | expect(executeSync).not.toThrow()
91 | })
92 |
93 | it('Should execute Ghostscript command synchronous with array based API', function () {
94 | const executeSync = async function execute() {
95 | return gs.executeSync(cmdSyncPngArray)
96 | }
97 | expect(executeSync).not.toThrow()
98 | })
99 |
100 | it('Should execute Ghostscript command synchronous without parameters and fail with error', function () {
101 | expect(gs.executeSync).toThrowError('Sorry method\'s argument should be a string or an array of strings');
102 | })
103 |
104 | it('Should execute Ghostscript command asynchronous', async function () {
105 | const execute = async function execute() {
106 | return gs.execute(cmdAsyncPng)
107 | }
108 | await expectAsync(execute()).not.toBeRejected()
109 | await expectAsync(execute()).toBeResolved()
110 | })
111 |
112 | it('Should execute Ghostscript command asynchronous with array based API', async function () {
113 | const execute = async function execute() {
114 | return gs.execute(cmdAsyncPngArray)
115 | }
116 | await expectAsync(execute()).not.toBeRejected()
117 | await expectAsync(execute()).toBeResolved()
118 | })
119 |
120 | it('Should execute Ghostscript command synchronous', function () {
121 | const executeSync = async function execute() {
122 | return gs.executeSync(cmdSyncPdf)
123 | }
124 | expect(executeSync).not.toThrow()
125 | })
126 |
127 | it('Should execute Ghostscript command synchronous with array based API', function () {
128 | const executeSync = async function execute() {
129 | return gs.executeSync(cmdSyncPdfArray)
130 | }
131 | expect(executeSync).not.toThrow()
132 | })
133 |
134 | it('Should execute Ghostscript command asynchronous', async function () {
135 | const execute = async function execute() {
136 | return gs.execute(cmdAsyncPdf)
137 | }
138 | await expectAsync(execute()).not.toBeRejected()
139 | await expectAsync(execute()).toBeResolved()
140 | })
141 |
142 | it('Should execute Ghostscript command asynchronous with array based API', async function () {
143 | const execute = async function execute() {
144 | return gs.execute(cmdAsyncPdfArray)
145 | }
146 | await expectAsync(execute()).not.toBeRejected()
147 | await expectAsync(execute()).toBeResolved()
148 | })
149 |
150 | it('Should throw an error if ghostscript command returns nonzero exit code', async function () {
151 | const execute = async function execute() {
152 | return gs.execute(cmdInvalidPdf)
153 | }
154 | await expectAsync(execute()).toBeRejected()
155 | await expectAsync(execute()).not.toBeResolved()
156 | await expectAsync(execute()).toBeRejectedWithError('Sorry error happened executing Ghostscript command. Error code: -100')
157 | })
158 |
159 | it('Should execute Ghostscript command asynchronous without parameters and fail', async function () {
160 | const execute = async function execute() {
161 | return gs.execute()
162 | }
163 | await expectAsync(execute()).toBeRejected()
164 | await expectAsync(execute()).not.toBeResolved()
165 | await expectAsync(execute()).toBeRejectedWithError('Sorry method\'s argument should be a string or an array of strings')
166 | })
167 |
168 | afterAll(cleanup)
169 |
170 | })
--------------------------------------------------------------------------------
/test/invalid.pdf:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque ultricies ornare tortor vel imperdiet. Fusce mattis turpis non nisi convallis facilisis. Maecenas mollis mi nec ex tempus, in sollicitudin diam viverra. Praesent sodales consectetur elit a posuere. Sed finibus euismod sem, sed semper purus gravida non. Quisque mattis volutpat tempor. Sed eget ante luctus, finibus magna id, fringilla erat. Mauris faucibus euismod facilisis. Integer mollis ut ex sit amet scelerisque. Fusce hendrerit ultricies congue.
2 |
3 | Nullam ultricies, massa ut placerat sollicitudin, quam ipsum porta erat, ac pulvinar nisl orci quis odio. Phasellus scelerisque auctor neque, sed malesuada neque laoreet et. Etiam a ipsum in turpis tincidunt consectetur. Morbi velit ex, sodales sit amet ornare a, laoreet ac est. Nunc nec ligula a eros gravida tincidunt sit amet egestas eros. Aenean in arcu a neque aliquam consectetur. Maecenas sagittis ligula dolor, et malesuada dui rutrum nec. In sodales sollicitudin aliquet. Nam imperdiet ultricies metus, eget pellentesque quam facilisis vel. Sed tempor eu dolor ac aliquet.
4 |
5 | Maecenas nibh massa, rutrum in nulla in, commodo efficitur nisi. Duis nec odio sapien. Morbi placerat molestie leo, at pretium urna. Nullam ut lacinia felis, eu egestas metus. Pellentesque vitae efficitur arcu, quis sodales ante. In malesuada rhoncus dui vel ornare. Sed ultrices, neque eu laoreet accumsan, urna libero porttitor ante, et tincidunt ipsum ipsum ut elit. Cras volutpat placerat tincidunt. Duis ante tellus, iaculis ut ex quis, bibendum tincidunt libero.
6 |
7 | Praesent dictum ultricies quam, egestas pellentesque purus molestie et. Suspendisse tristique blandit massa, varius laoreet ex elementum ut. Ut nibh nunc, egestas sed dolor ac, tincidunt scelerisque quam. Mauris ultricies libero vitae leo maximus malesuada. Pellentesque orci elit, dignissim sed sagittis at, placerat et augue. Duis a convallis tortor. Duis vulputate facilisis arcu quis finibus. Vestibulum diam lectus, euismod sed tempor nec, rutrum vel risus. Nunc auctor pharetra enim, a viverra lectus mattis a. Aenean vestibulum gravida dictum. Curabitur gravida, magna et tincidunt pellentesque, lectus lectus pharetra lacus, ut fermentum nibh elit eu augue. Vivamus scelerisque velit massa, sit amet ullamcorper nisi posuere id. Vestibulum sapien elit, malesuada sit amet mauris non, rutrum tincidunt metus.
8 |
9 | Vestibulum quis cursus libero, id faucibus odio. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris mollis feugiat enim eu tempus. Sed mattis nibh nec lacus condimentum venenatis. Aenean a molestie risus. Proin varius orci turpis, ac vehicula risus bibendum vel. Suspendisse potenti. Morbi gravida blandit orci nec ullamcorper. Phasellus eu metus vitae lacus bibendum luctus vel cursus sapien. Quisque finibus imperdiet scelerisque. Donec vitae dolor eros. Aliquam erat volutpat.
10 |
--------------------------------------------------------------------------------
/test/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "test",
3 | "spec_files": [
4 | "ghostscript4js.js"
5 | ],
6 | "helpers": []
7 | }
--------------------------------------------------------------------------------
/test/node-love-ghostscript.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickNaso/ghostscript4js/1b06fe0aa2076b1a7ef9765e6d67daa0e4c87634/test/node-love-ghostscript.pdf
--------------------------------------------------------------------------------
/test/node-love-ghostscript.ps:
--------------------------------------------------------------------------------
1 | %!PS-Adobe-2.0
2 | %%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software
3 | %%Title: 26policy.dvi
4 | %%Pages: 2
5 | %%PageOrder: Ascend
6 | %%BoundingBox: 0 0 612 792
7 | %%DocumentPaperSizes: Letter
8 | %%EndComments
9 | %DVIPSCommandLine: dvips -o 26policy.ps 26policy
10 | %DVIPSParameters: dpi=300, comments removed
11 | %DVIPSSource: TeX output 1999.02.24:1138
12 | %%BeginProcSet: tex.pro
13 | /TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N
14 | /X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72
15 | mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1}
16 | ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale
17 | isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div
18 | hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul
19 | TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if}
20 | forall round exch round exch]setmatrix}N /@landscape{/isls true N}B
21 | /@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B
22 | /FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{
23 | /nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N
24 | string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N
25 | end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{
26 | /sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0]
27 | N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup
28 | length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{
29 | 128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub
30 | get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data
31 | dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N
32 | /rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup
33 | /base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx
34 | 0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff
35 | setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff
36 | .1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]}
37 | if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup
38 | length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{
39 | cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin
40 | 0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul
41 | add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict
42 | /eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook
43 | known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X
44 | /IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for
45 | 65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0
46 | 0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V
47 | {}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7
48 | getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false}
49 | ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false
50 | RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1
51 | false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform
52 | round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg
53 | rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail
54 | {dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M}
55 | B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{
56 | 4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{
57 | p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p
58 | a}B /bos{/SS save N}B /eos{SS restore}B end
59 | %%EndProcSet
60 | TeXDict begin 40258431 52099146 1000 300 300 (26policy.dvi)
61 | @start /Fa 22 122 df<78FCFCFCFC780606778518>46 D<000300000780000F80000F
62 | 80000F00001F00001F00003E00003E00003C00007C00007C0000F80000F80000F00001F0
63 | 0001F00003E00003E00007C00007C0000780000F80000F80001F00001F00001E00003E00
64 | 003E00007C00007C0000780000F80000F80000F0000060000011247D9F18>I<78FCFCFC
65 | FC78000000000000000078FCFCFCFC780614779318>58 D<7FFFC0FFFFE0FFFFE07FFFC0
66 | 13047E7F18>95 D<0FF0001FFC003FFE003C1F0018078000038000038000FF800FFF801F
67 | FF807F8380780380F00380E00380E00380F007807C1F803FFFF81FFDF807F0F815147E93
68 | 18>97 D<01FE0007FF001FFF803F07803C0300780000700000F00000E00000E00000E000
69 | 00E00000F000007000007801C03C01C03F07C01FFF8007FF0001FC0012147D9318>99
70 | D<001F80003F80001F8000038000038000038000038000038003F3800FFB801FFF803E1F
71 | 80780F80700780F00780E00380E00380E00380E00380E00380E00780F00780700780780F
72 | 803E3F801FFFF00FFBF803E3F0151C7E9B18>I<03F0000FFC001FFE003E1F0078078070
73 | 0380F003C0E001C0E001C0FFFFC0FFFFC0FFFFC0F000007000007801C03C01C03F07C01F
74 | FF8007FF0001FC0012147D9318>I<001FC0007FE000FFE001F1E001C0C001C00001C000
75 | 01C0007FFFC0FFFFC0FFFFC001C00001C00001C00001C00001C00001C00001C00001C000
76 | 01C00001C00001C00001C00001C00001C0007FFF007FFF007FFF00131C7F9B18>I<7E00
77 | 00FE00007E00000E00000E00000E00000E00000E00000E3F000EFF800FFFC00FE1E00F80
78 | E00F00E00F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00
79 | E07FC7FCFFE7FE7FC7FC171C809B18>104 D<038007C007C007C0038000000000000000
80 | 007FC0FFC07FC001C001C001C001C001C001C001C001C001C001C001C001C001C001C0FF
81 | FFFFFFFFFF101D7C9C18>I<7E0000FE00007E00000E00000E00000E00000E00000E0000
82 | 0E3FF00E3FF00E3FF00E07800E0F000E1E000E3C000E78000EF0000FF8000FFC000F9C00
83 | 0F1E000E0F000E07800E03800E03C07FC7F8FFC7F87FC7F8151C7F9B18>107
84 | DII<01F0000FFE001FFF003E0F803803807001C07001C0
89 | E000E0E000E0E000E0E000E0E000E0F001E07001C07803C03C07803E0F801FFF000FFE00
90 | 01F00013147E9318>111 D<7E3E00FEFF807FFFC00FE3E00F80F00F00700F00780E0038
91 | 0E00380E00380E00380E00380F00380F00780F00700F80F00FC3E00FFFC00EFF800E7E00
92 | 0E00000E00000E00000E00000E00000E00000E00007FC000FFE0007FC000151E809318>
93 | I114
95 | D<0FF7003FFF007FFF00F81F00E00700E00700F007007C00007FF0001FFC0007FE00001F
96 | 00600780E00380F00380F00780FC0F00FFFF00FFFE00E7F80011147D9318>I<01800003
97 | 80000380000380000380007FFFC0FFFFC0FFFFC003800003800003800003800003800003
98 | 80000380000380000380000380400380E00380E00381E003C3C001FFC000FF80007E0013
99 | 197F9818>I<7E07E0FE0FE07E07E00E00E00E00E00E00E00E00E00E00E00E00E00E00E0
100 | 0E00E00E00E00E00E00E00E00E00E00E01E00F07E007FFFC03FFFE01FCFC1714809318>
101 | I119
103 | D<7F8FF0FF8FF87F8FF00E01C00E03800E0380070380070700070700038700038700038E
104 | 0001CE0001CE0001CC0000CC0000DC0000780000780000780000700000700000700000F0
105 | 0000E00079E0007BC0007F80003F00001E0000151E7F9318>121
106 | D E /Fb 75 123 df<001F83E000F06E3001C078780380F8780300F03007007000070070
107 | 000700700007007000070070000700700007007000FFFFFF800700700007007000070070
108 | 000700700007007000070070000700700007007000070070000700700007007000070070
109 | 000700700007007000070070000700700007007000070070003FE3FF001D20809F1B>11
110 | D<003F0000E0C001C0C00381E00701E00701E00700000700000700000700000700000700
111 | 00FFFFE00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700
112 | E00700E00700E00700E00700E00700E00700E00700E03FC3FC1620809F19>I<003FE000
113 | E0E001C1E00381E00700E00700E00700E00700E00700E00700E00700E00700E0FFFFE007
114 | 00E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E007
115 | 00E00700E00700E00700E00700E00700E03FE7FC1620809F19>I<001F81F80000F04F04
116 | 0001C07C06000380F80F000300F00F000700F00F00070070000007007000000700700000
117 | 070070000007007000000700700000FFFFFFFF0007007007000700700700070070070007
118 | 007007000700700700070070070007007007000700700700070070070007007007000700
119 | 700700070070070007007007000700700700070070070007007007000700700700070070
120 | 07003FE3FE3FE02320809F26>I<70F8F8F8F8F8F8F87070707070707070707020202020
121 | 20000000000070F8F8F87005217CA00D>33 D<7038F87CFC7EFC7E743A04020402040208
122 | 04080410081008201040200F0E7F9F17>I<078000180018400038003020003000301800
123 | F000601703E0006008FCC000E00801C000E008038000E008030000E008070000E0080E00
124 | 00E0080C000060081C00006010380000301030000030207000001840E000000780C00000
125 | 0001C078000001818400000383020000070301000006070100000E060100001C0E008000
126 | 180E008000380E008000700E008000600E008000E00E008001C00E008001800601000380
127 | 070100070003010006000302000E000184000C0000780021257EA126>37
128 | D<70F8FCFC74040404080810102040060E7C9F0D>39 D<0040008001000300060004000C
129 | 001800180038003000300070006000600060006000E000E000E000E000E000E000E000E0
130 | 00E000E000E000E00060006000600060007000300030003800180018000C000400060003
131 | 000100008000400A2E7BA112>I<8000400020003000180008000C000600060007000300
132 | 03000380018001800180018001C001C001C001C001C001C001C001C001C001C001C001C0
133 | 01800180018001800380030003000700060006000C000800180030002000400080000A2E
134 | 7EA112>I<70F0F8F878080808101010202040050E7C840D>44 D
135 | I<70F8F8F87005057C840D>I<0000C00000C00001C00001800001800003800003000007
136 | 00000600000600000E00000C00000C00001C000018000038000030000030000070000060
137 | 0000600000E00000C00001C0000180000180000380000300000300000700000600000E00
138 | 000C00000C00001C0000180000180000380000300000700000600000600000E00000C000
139 | 00C00000122D7EA117>I<03F0000E1C001C0E0018060038070070038070038070038070
140 | 0380F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F0
141 | 03C0F003C07003807003807003807807803807001806001C0E000E1C0003F000121F7E9D
142 | 17>I<008003800F80F38003800380038003800380038003800380038003800380038003
143 | 800380038003800380038003800380038003800380038007C0FFFE0F1E7C9D17>I<03F0
144 | 000C1C00100E00200700400780800780F007C0F803C0F803C0F803C02007C00007C00007
145 | 80000780000F00000E00001C0000380000700000600000C0000180000300000600400C00
146 | 401800401000803FFF807FFF80FFFF80121E7E9D17>I<03F0000C1C00100E00200F0078
147 | 0F80780780780780380F80000F80000F00000F00001E00001C0000700007F000003C0000
148 | 0E00000F000007800007800007C02007C0F807C0F807C0F807C0F00780400780400F0020
149 | 0E00183C0007F000121F7E9D17>I<000600000600000E00000E00001E00002E00002E00
150 | 004E00008E00008E00010E00020E00020E00040E00080E00080E00100E00200E00200E00
151 | 400E00C00E00FFFFF0000E00000E00000E00000E00000E00000E00000E0000FFE0141E7F
152 | 9D17>I<1803001FFE001FFC001FF8001FE0001000001000001000001000001000001000
153 | 0011F000161C00180E001007001007800003800003800003C00003C00003C07003C0F003
154 | C0F003C0E00380400380400700200600100C0008380007E000121F7E9D17>I<007C0001
155 | 82000701000E03800C0780180780380300380000780000700000700000F1F000F21C00F4
156 | 0600F80700F80380F80380F003C0F003C0F003C0F003C0F003C07003C07003C070038038
157 | 03803807001807000C0E00061C0001F000121F7E9D17>I<4000007FFFE07FFFC07FFFC0
158 | 400080800100800100800200000400000400000800001000001000002000002000006000
159 | 00600000E00000C00001C00001C00001C00001C00003C00003C00003C00003C00003C000
160 | 03C00003C000018000131F7E9D17>I<03F0000C0C001006003003002001806001806001
161 | 806001807001807803003E03003F06001FC8000FF00003F80007FC000C7E00103F00300F
162 | 806007806001C0C001C0C000C0C000C0C000C0C000806001802001001002000C0C0003F0
163 | 00121F7E9D17>I<03F0000E18001C0C00380600380700700700700380F00380F00380F0
164 | 03C0F003C0F003C0F003C0F003C07007C07007C03807C0180BC00E13C003E3C000038000
165 | 0380000380000700300700780600780E00700C002018001070000FC000121F7E9D17>I<
166 | 70F8F8F8700000000000000000000070F8F8F87005147C930D>I<70F8F8F87000000000
167 | 00000000000070F0F8F878080808101010202040051D7C930D>I<001FE0000060180001
168 | 800600020001000400008008000040100F8020203860102070101040E0080840C0070841
169 | C00708818007048380070483800704838007048380070483800704838007048180070441
170 | C0070440C0070440E00F082070170820386310100F81E008000000040000000200001C01
171 | 8000F000600F80001FF8001E207E9F23>64 D<0001000000038000000380000003800000
172 | 07C0000007C0000007C0000009E0000009E0000009E0000010F0000010F0000010F00000
173 | 207800002078000020780000403C0000403C0000C03E0000801E0000801E0001FFFF0001
174 | 000F0001000F00020007800200078002000780040003C0040003C00C0003C01E0003E0FF
175 | 801FFE1F207F9F22>II<000FE0
179 | 1000381C3000E0027003C00170078000F00F0000701E0000701E0000303C0000303C0000
180 | 107C00001078000010F8000000F8000000F8000000F8000000F8000000F8000000F80000
181 | 00F8000000F8000000780000007C0000103C0000103C0000101E0000201E0000200F0000
182 | 200780004003C0008000E0030000380C00000FF0001C217E9F21>IIII<000FE01000381C3000E002
194 | 7003C00170078000F00F0000701E0000701E0000303C0000303C0000107C000010780000
195 | 10F8000000F8000000F8000000F8000000F8000000F8000000F8000000F8003FFEF80001
196 | F0780000F07C0000F03C0000F03C0000F01E0000F01E0000F00F0000F0078000F003C001
197 | 7000E0023000380C10000FF0001F217E9F24>III<07FFC0003E00001E00001E00001E00001E00001E00001E00001E00001E00001E
204 | 00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E00001E
205 | 00201E00F81E00F81E00F81E00F01C00403C006038001070000FC00012207F9E17>IIII<001FE000
217 | 0070380001C00E0003800700070003800F0003C01E0001E03C0000F03C0000F07C0000F8
218 | 7C0000F878000078F800007CF800007CF800007CF800007CF800007CF800007CF800007C
219 | F800007CF800007C780000787C0000F87C0000F83C0000F03E0001F01E0001E00F0003C0
220 | 070003800380070001E01E0000703800001FE0001E217E9F23>79
221 | DI<001FE0000070380001C00E00
225 | 03800700070003800F0003C01E0001E03E0001F03C0000F07C0000F87C0000F878000078
226 | F800007CF800007CF800007CF800007CF800007CF800007CF800007CF800007CF800007C
227 | 780000787C0000F87C0000F83C0000F03E0781F01E0841E00F1023C00710238003901700
228 | 01D01E0000783804001FF80400001C0400000C0C00000E1C00000FF800000FF8000007F8
229 | 000007F0000001E01E297E9F23>II<03F0400C0CC01803C03001C06000C06000C0E000C0E00040E00040E00040
234 | F00000F800007C00007F80003FF8001FFF0007FF8000FFC0001FE00003E00001E00000F0
235 | 000070800070800070800070800070C00060C000E0E000C0F80180C6030081FC0014217E
236 | 9F19>I<7FFFFFE0780F01E0600F0060400F0020400F0020C00F0030800F0010800F0010
237 | 800F0010800F0010000F0000000F0000000F0000000F0000000F0000000F0000000F0000
238 | 000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000
239 | 000F0000000F0000000F0000001F800003FFFC001C1F7E9E21>II
249 | 87 D89 D<080410082010201040
253 | 204020804080408040B85CFC7EFC7E7C3E381C0F0E7A9F17>92 D<1FE000303000781800
254 | 781C00300E00000E00000E00000E0000FE00078E001E0E00380E00780E00F00E10F00E10
255 | F00E10F01E10781E103867200F83C014147E9317>97 D<1C0000FC00001C00001C00001C
256 | 00001C00001C00001C00001C00001C00001C00001C00001C7C001D87001E01801E00C01C
257 | 00E01C00701C00701C00781C00781C00781C00781C00781C00781C00701C00F01C00E01E
258 | 00C01A0180198700107C0015207E9F19>I<01FC000706001C0F00380F00380600780000
259 | 700000F00000F00000F00000F00000F00000F000007000007800003800803800801C0100
260 | 07060001F80011147F9314>I<0001C0000FC00001C00001C00001C00001C00001C00001
261 | C00001C00001C00001C00001C001F1C0070DC00C03C01801C03801C07801C07001C0F001
262 | C0F001C0F001C0F001C0F001C0F001C07001C07001C03801C01803C00C03C0070DC001F1
263 | F815207F9F19>I<03F0000E1C001C0E00380700380700700700700380F00380F00380FF
264 | FF80F00000F00000F000007000007000003800803800801C010007060001F80011147F93
265 | 14>I<007C01C6030F070F0E060E000E000E000E000E000E000E00FFF00E000E000E000E
266 | 000E000E000E000E000E000E000E000E000E000E000E000E000E000E007FE01020809F0E
267 | >I<0000E003E3300E3C301C1C30380E00780F00780F00780F00780F00780F00380E001C
268 | 1C001E380033E0002000002000003000003000003FFE001FFF801FFFC03001E0600070C0
269 | 0030C00030C00030C000306000603000C01C038003FC00141F7F9417>I<1C0000FC0000
270 | 1C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C7C001C8600
271 | 1D03001E03801E03801C03801C03801C03801C03801C03801C03801C03801C03801C0380
272 | 1C03801C03801C03801C03801C0380FF8FF014207E9F19>I<38007C007C007C00380000
273 | 00000000000000000000001C00FC001C001C001C001C001C001C001C001C001C001C001C
274 | 001C001C001C001C001C001C00FF80091F7F9E0C>I<1C0000FC00001C00001C00001C00
275 | 001C00001C00001C00001C00001C00001C00001C00001C1FE01C07801C06001C04001C08
276 | 001C10001C20001C60001CE0001DF0001E70001C38001C3C001C1C001C0E001C0F001C07
277 | 001C07801C07C0FF9FF014207E9F18>107 D<1C00FC001C001C001C001C001C001C001C
278 | 001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C
279 | 001C001C001C001C00FF8009207F9F0C>I<1C3E03E000FCC30C30001D039038001E01E0
280 | 1C001E01E01C001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C
281 | 001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C001C01C01C00
282 | 1C01C01C00FF8FF8FF8021147E9326>I<1C7C00FC86001D03001E03801E03801C03801C
283 | 03801C03801C03801C03801C03801C03801C03801C03801C03801C03801C03801C03801C
284 | 0380FF8FF014147E9319>I<01F800070E001C03803801C03801C07000E07000E0F000F0
285 | F000F0F000F0F000F0F000F0F000F07000E07000E03801C03801C01C0380070E0001F800
286 | 14147F9317>I<1C7C00FD87001E01801E01C01C00E01C00F01C00701C00781C00781C00
287 | 781C00781C00781C00781C00701C00F01C00E01E01C01E03801D87001C7C001C00001C00
288 | 001C00001C00001C00001C00001C00001C0000FF8000151D7E9319>I<01F040070CC00E
289 | 02C01C03C03801C07801C07001C0F001C0F001C0F001C0F001C0F001C0F001C07001C078
290 | 01C03801C01C03C00C05C00709C001F1C00001C00001C00001C00001C00001C00001C000
291 | 01C00001C0000FF8151D7F9318>I<1CF0FD181E3C1E3C1E181C001C001C001C001C001C
292 | 001C001C001C001C001C001C001C001C00FFC00E147E9312>I<0FC830386018C008C008
293 | C008E0007C003FE01FF007F8003C800E8006C006C006C004E00CD81887E00F147F9312>
294 | I<020002000200060006000E000E003E00FFF80E000E000E000E000E000E000E000E000E
295 | 000E000E000E040E040E040E040E040708030801F00E1C7F9B12>I<1C0380FC1F801C03
296 | 801C03801C03801C03801C03801C03801C03801C03801C03801C03801C03801C03801C03
297 | 801C03801C07800C0780061B8003E3F014147E9319>IIIII<7FFF700E600E401C40384078407000E001E001C00380
307 | 078007010E011E011C0338027006700EFFFE10147F9314>I E /Fc
308 | 36 123 df<000FF01FC000007FF8FFF00000F81FE0780001E03F80F80003E07F80F80007
309 | C07F00F80007C07F00F80007C03F00700007C01F00000007C01F00000007C01F00000007
310 | C01F03FC00FFFFFFFFFC00FFFFFFFFFC0007C01F007C0007C01F007C0007C01F007C0007
311 | C01F007C0007C01F007C0007C01F007C0007C01F007C0007C01F007C0007C01F007C0007
312 | C01F007C0007C01F007C0007C01F007C0007C01F007C0007C01F007C0007C01F007C0007
313 | C01F007C003FF8FFE3FF803FF8FFE3FF802920809F2C>14 D45 D<387CFEFEFE7C38000000000000387CFEFEFE7C3807147C930F>58
315 | D<0000E000000000E000000001F000000001F000000001F000000003F800000003F80000
316 | 0006FC00000006FC0000000EFE0000000C7E0000000C7E000000183F000000183F000000
317 | 303F800000301F800000701FC00000600FC00000600FC00000C007E00000FFFFE00001FF
318 | FFF000018003F000038003F800030001F800030001F800060000FC00060000FC000E0000
319 | FE00FFE00FFFE0FFE00FFFE0231F7E9E28>65 D<0007FC02003FFF0E00FE03DE03F000FE
320 | 07E0003E0FC0001E1F80001E3F00000E3F00000E7F0000067E0000067E000006FE000000
321 | FE000000FE000000FE000000FE000000FE000000FE0000007E0000007E0000067F000006
322 | 3F0000063F00000C1F80000C0FC0001807E0003803F0007000FE01C0003FFF800007FC00
323 | 1F1F7D9E26>67 D69
327 | DI<0007FC0200003FFF0E0000FE
331 | 03DE0003F000FE0007E0003E000FC0001E001F80001E003F00000E003F00000E007F0000
332 | 06007E000006007E00000600FE00000000FE00000000FE00000000FE00000000FE000000
333 | 00FE001FFFE0FE001FFFE07E00007E007E00007E007F00007E003F00007E003F00007E00
334 | 1F80007E000FC0007E0007E0007E0003F000FE0000FE01FE00003FFF8E000007FC060023
335 | 1F7D9E29>III76 D<001FF80000FFFF0001F81F8007E007E00FC003F01F8001F81F0000
346 | F83F0000FC7F0000FE7E00007E7E00007EFE00007FFE00007FFE00007FFE00007FFE0000
347 | 7FFE00007FFE00007FFE00007FFE00007F7E00007E7F0000FE7F0000FE3F0000FC3F8001
348 | FC1F8001F80FC003F007E007E001F81F8000FFFF00001FF800201F7D9E27>79
349 | D<001FF80000FFFF0001F81F8007E007E00FC003F01F8001F81F8001F83F0000FC7F0000
350 | FE7F0000FE7E00007EFE00007FFE00007FFE00007FFE00007FFE00007FFE00007FFE0000
351 | 7FFE00007FFE00007F7E00007E7E00007E7F0000FE3F0000FC3F87C1FC1F8FF1F80FDC3B
352 | F007F83FE001FC1F8000FFFF00001FFE0300000F0300000F8700000FFF00000FFF000007
353 | FE000007FE000003FC000003FC000000F020287D9E27>81 DI<03FC080FFF381E03F83800F8700078700038F00038F00018F00018F800
359 | 00FC00007FC0007FFE003FFF801FFFC00FFFE007FFF000FFF80007F80000FC00007C0000
360 | 3CC0003CC0003CC0003CE00038E00078F80070FE01E0EFFFC081FF00161F7D9E1D>I<7F
361 | FFFFFC7FFFFFFC7C07E07C7007E01C6007E00C6007E00CE007E00EC007E006C007E006C0
362 | 07E006C007E0060007E0000007E0000007E0000007E0000007E0000007E0000007E00000
363 | 07E0000007E0000007E0000007E0000007E0000007E0000007E0000007E0000007E00000
364 | 07E00003FFFFC003FFFFC01F1E7E9D24>I<07FC001FFF803F07C03F03E03F01F03F01F0
365 | 0C01F00001F0003FF007FDF01F81F03E01F07C01F0F801F0F801F0F801F0FC02F07E0CF0
366 | 3FF8FE0FE03E17147F9319>97 DI<01FE0007FF801F0FC03E0FC03E0FC07C0FC07C0300FC0000FC0000
370 | FC0000FC0000FC0000FC00007C00007E00003E00603F00C01F81C007FF0001FC0013147E
371 | 9317>I<0007F80007F80000F80000F80000F80000F80000F80000F80000F80000F80000
372 | F80000F801F8F807FEF81F83F83E01F87E00F87C00F87C00F8FC00F8FC00F8FC00F8FC00
373 | F8FC00F8FC00F87C00F87C00F87E00F83E01F81F07F80FFEFF03F8FF18207E9F1D>I<01
374 | FE0007FF801F83E03F01F07E00F07E00F8FC00F8FC00F8FFFFF8FFFFF8FC0000FC0000FC
375 | 00007C00007E00003E00183F00380F807007FFE000FF8015147F9318>I104 D<1C007F007F007F007F
379 | 007F001C00000000000000000000000000FF00FF001F001F001F001F001F001F001F001F
380 | 001F001F001F001F001F001F001F001F00FFE0FFE00B217EA00E>I107 DIII<01FF0007FFC01F83F03E00F83E00F87C007C
391 | 7C007CFC007EFC007EFC007EFC007EFC007EFC007E7C007C7C007C3E00F83E00F81F83F0
392 | 07FFC001FF0017147F931A>II114
397 | D<0FE63FFE701E600EE006E006F800FFC07FF83FFC1FFE03FE001FC007C007E007F006F8
398 | 1EFFFCC7F010147E9315>I<0300030003000300070007000F000F003F00FFFCFFFC1F00
399 | 1F001F001F001F001F001F001F001F001F001F061F061F061F061F060F8C07F803F00F1D
400 | 7F9C14>II<
402 | FFC7FE1FE0FFC7FE1FE01F00F003001F00F803000F80F806000F80F806000FC1BC0E0007
403 | C1BC0C0007C3BE0C0003E31E180003E31E180003F60F380001F60F300001FE0FB00000FC
404 | 07E00000FC07E00000F803E000007803C000007803C000003001800023147F9326>119
405 | D121 D<3FFFE03FFFE03C0FC0381FC0701F80603F00
409 | 607E0060FE0000FC0001F80003F00007E0600FE0600FC0601F80E03F00C07F01C07E03C0
410 | FFFFC0FFFFC013147F9317>I E /Fd 13 90 df45 D<003F800001FFF00007E0FC000FC07E001F803F001F001F003F00
412 | 1F803E000F807E000FC07E000FC07E000FC07E000FC0FE000FE0FE000FE0FE000FE0FE00
413 | 0FE0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE0FE000FE0FE00
414 | 0FE0FE000FE0FE000FE07E000FC07E000FC07E000FC07E000FC03F001F803F001F801F00
415 | 1F001F803F000FC07E0007E0FC0001FFF000003F80001B277DA622>48
416 | D<00FF800007FFF0000FFFFC001E03FE003800FF807C003F80FE003FC0FF001FC0FF001F
417 | E0FF000FE0FF000FE07E000FE03C001FE000001FE000001FC000001FC000003F8000003F
418 | 0000007E000000FC000000F8000001F0000003E00000078000000F0000001E0000003C00
419 | E0007000E000E000E001C001C0038001C0060001C00FFFFFC01FFFFFC03FFFFFC07FFFFF
420 | C0FFFFFF80FFFFFF80FFFFFF801B277DA622>50 D<00000F0000000F0000001F0000003F
421 | 0000007F000000FF000001FF000001FF000003BF0000073F00000E3F00001C3F00003C3F
422 | 0000383F0000703F0000E03F0001C03F0003803F0007803F0007003F000E003F001C003F
423 | 0038003F0070003F00F0003F00FFFFFFF8FFFFFFF8FFFFFFF800007F0000007F0000007F
424 | 0000007F0000007F0000007F0000007F0000007F00001FFFF8001FFFF8001FFFF81D277E
425 | A622>52 D<0007F800003FFE0000FFFF0001FC078003F00FC007C01FC00F801FC01F801F
426 | C01F001FC03F000F803F0000007E0000007E0000007E000000FE020000FE1FF000FE3FFC
427 | 00FE603E00FE801F00FF801F80FF000FC0FF000FC0FE000FE0FE000FE0FE000FE0FE000F
428 | E07E000FE07E000FE07E000FE07E000FE03E000FE03F000FC01F000FC01F001F800F801F
429 | 0007E07E0003FFFC0001FFF800003FC0001B277DA622>54 D<0000078000000000078000
430 | 0000000FC0000000000FC0000000000FC0000000001FE0000000001FE0000000003FF000
431 | 0000003FF0000000003FF00000000077F80000000077F800000000F7FC00000000E3FC00
432 | 000000E3FC00000001C1FE00000001C1FE00000003C1FF0000000380FF0000000380FF00
433 | 000007007F80000007007F8000000F007FC000000E003FC000000E003FC000001C001FE0
434 | 00001C001FE000003FFFFFF000003FFFFFF000003FFFFFF00000700007F80000700007F8
435 | 0000F00007FC0000E00003FC0001E00003FE0001C00001FE0001C00001FE0003C00001FF
436 | 00FFFE003FFFFCFFFE003FFFFCFFFE003FFFFC2E297EA833>65 D<00007FE0030007FFFC
437 | 07001FFFFF0F007FF00F9F00FF0001FF01FC0000FF03F800007F07F000003F0FE000001F
438 | 1FC000001F1FC000000F3F8000000F3F800000077F800000077F800000077F00000000FF
439 | 00000000FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000FF00
440 | 000000FF000000007F000000007F800000007F800000073F800000073F800000071FC000
441 | 00071FC000000E0FE000000E07F000001C03F800003C01FC00007800FF0001F0007FF007
442 | C0001FFFFF800007FFFE0000007FF00028297CA831>67 D73 D76 D<0000FFC00000000FFFFC0000003F807F000000FE001FC00001F80007
453 | E00003F00003F00007E00001F8000FE00001FC001FC00000FE001FC00000FE003F800000
454 | 7F003F8000007F007F8000007F807F0000003F807F0000003F807F0000003F80FF000000
455 | 3FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF000000
456 | 3FC0FF0000003FC0FF0000003FC0FF0000003FC07F0000003F807F8000007F807F800000
457 | 7F803F8000007F003F8000007F001FC00000FE001FC00000FE000FE00001FC0007F00003
458 | F80003F80007F00001FC000FE00000FE001FC000003FC0FF0000000FFFFC00000000FFC0
459 | 00002A297CA833>79 DI<00FF806003FFF0E00FFFF8E01F80FDE03F001FE03E0007E07C0003E07C00
466 | 03E0FC0001E0FC0001E0FC0000E0FE0000E0FE0000E0FF000000FFC000007FFC00007FFF
467 | E0003FFFF8001FFFFE001FFFFF0007FFFF8003FFFFC000FFFFC0000FFFE000007FE00000
468 | 1FF000000FF0000007F0E00003F0E00003F0E00003F0E00003F0F00003E0F00003E0F800
469 | 07E0FC0007C0FF000F80FFE03F80E3FFFE00E1FFFC00C01FF0001C297CA825>83
470 | D89 D E end
478 | %%EndProlog
479 | %%BeginSetup
480 | %%Feature: *Resolution 300dpi
481 | TeXDict begin
482 | %%PaperSize: Letter
483 |
484 | %%EndSetup
485 | %%Page: 1 1
486 | 1 0 bop 616 199 a Fd(26L-04)22 b(CLASS)h(POLICY)174 338
487 | y Fc(Instructor:)49 b Fb(Laura)15 b(T)l(aalman)403 b
488 | Fc(O\016ce:)49 b Fb(020)14 b(Math/Ph)o(ysics)174 395
489 | y Fc(T)l(elephone:)50 b Fb(660-2829)13 b(\(W\),)h(220-1359)g(\(H\))129
490 | b Fc(E-mail:)51 b Fb(taal@math.duk)o(e.edu)75 568 y(General)13
491 | b(p)q(olicies)j(for)c(26L)h(are)f(found)h(in)h(y)o(our)e(Coursepac)o(k)
492 | h(on)g(pages)g(5-14.)18 b(P)o(olicies)c(sp)q(eci\014c)h(to)d(m)o(y)75
493 | 624 y(section)j(are)f(listed)h(b)q(elo)o(w,)g(and)f(sup)q(ercede)i(an)o
494 | (y)e(p)q(olicies)j(in)e(the)f(coursepac)o(k.)20 b(Y)l(ou)14
495 | b(are)g(exp)q(ected)i(to)75 681 y(understand)c(and)h(agree)e(to)g(all)i
496 | (of)f(these)g(p)q(olicies.)21 b(I)12 b(will)i(b)q(e)e(unimpressed)i(if)
497 | e(I)g(ha)o(v)o(e)g(to)f(answ)o(er)h(lots)f(of)75 737
498 | y(questions)j(throughout)f(the)h(semester)f(whose)h(answ)o(ers)f(can)g
499 | (b)q(e)i(found)f(here)g(or)f(in)h(the)g(Coursepac)o(k.)75
500 | 844 y Fc(Grades)f Fb(Y)l(our)h(grade)g(for)f(this)h(course)g(will)i(b)q
501 | (e)e(determined)h(almost)f(en)o(tirely)h(b)o(y)e(y)o(our)h(p)q
502 | (erformance)75 900 y(on)20 b(quizzes,)i(tests,)f(and)f(the)g(\014nal)h
503 | (exam.)34 b(I)20 b(exp)q(ect)h(the)f(distribution)i(of)e(p)q(oin)o(ts)g
504 | (\(and)g(th)o(us)g(the)75 956 y(corresp)q(onding)c(p)q(ercen)o(tages\))
505 | f(to)g(b)q(e)h(as)e(follo)o(ws:)p 304 1069 1342 2 v 303
506 | 1137 2 68 v 353 1116 a(W)l(eekly)i(Quizzes)p 712 1137
507 | V 99 w(10)f(@)g(25)g(pts)p 1041 1137 V 97 w(250)f(total)g(pts)p
508 | 1391 1137 V 97 w(31.25)g(\045)p 1645 1137 V 303 1205
509 | V 353 1184 a(Lab)i(Rep)q(orts)p 712 1205 V 171 w(2)f(@)h(25)e(pts)p
510 | 1041 1205 V 131 w(50)h(total)f(pts)p 1391 1205 V 120
511 | w(6.25)g(\045)p 1645 1205 V 303 1272 V 353 1252 a(T)l(ests)p
512 | 712 1272 V 305 w(3)h(@)g(100)g(pts)p 1041 1272 V 97 w(300)f(total)g
513 | (pts)p 1391 1272 V 97 w(37.50)g(\045)p 1645 1272 V 303
514 | 1340 V 353 1320 a(Final)i(Exam)p 712 1340 V 174 w(1)f(@)g(200)g(pts)p
515 | 1041 1340 V 97 w(200)f(total)g(pts)p 1391 1340 V 97 w(25.00)g(\045)p
516 | 1645 1340 V 304 1342 1342 2 v 75 1486 a(W)l(eekly)f(quiz)g(scores)f
517 | (can)g(b)q(e)h(mo)q(di\014ed)h(b)o(y)e(y)o(our)g(score)g(on)g
518 | (\\attendance)g(quizzes")h(and)f(y)o(our)g(comple-)75
519 | 1543 y(tion)f(of)e(\\gatew)o(a)o(y)g(homew)o(orks")g(\(where)h
520 | (applicable\).)20 b(T)l(est)11 b(scores)f(can)g(b)q(e)h(increased)h(b)o
521 | (y)e(completion)75 1599 y(of)k(c)o(heat)g(sheets.)20
522 | b(The)15 b(\014nal)g(exam)f(ma)o(y)g(end)h(up)g(coun)o(ting)f(as)g
523 | (more)g(than)h(25)f(\045)g(of)g(y)o(our)g(grade;)g(see)75
524 | 1656 y(page)h(11)g(in)h(y)o(our)e(coursepac)o(k)i(for)e(more)h
525 | (information.)75 1762 y Fc(A)o(ttendance)20 b(and)g(Absences:)j
526 | Fb(It)17 b(is)h(imp)q(erativ)o(e)g(that)f(y)o(ou)g(come)g(to)f(class)i
527 | (eac)o(h)f(da)o(y)g(and)h(tak)o(e)75 1819 y(careful)11
528 | b(notes.)18 b(I)10 b(will)i(tak)o(e)e(random)g(\\attendance)g(quizzes")
529 | h(throughout)e(the)i(semester)f(to)f(k)o(eep)i(trac)o(k)75
530 | 1875 y(of)i(who)g(is)h(attending)f(class.)20 b(Eac)o(h)13
531 | b(of)g(these)g(quizzes)i(will)g(b)q(e)f(w)o(orth)e(t)o(w)o(o)g(extra)g
532 | (p)q(oin)o(ts)i(to)o(w)o(ards)e(that)75 1931 y(w)o(eek's)h(homew)o
533 | (ork/lab)f(quiz)i(\(not)e(to)h(exceed)h(25)e(total)h(p)q(oin)o(ts\);)g
534 | (these)g(quizzes)i(cannot)e(b)q(e)g(made)g(up)75 1988
535 | y(for)i(an)o(y)h(reason.)21 b(If)16 b(y)o(ou)f(do)h(miss)g(class)g(it)g
536 | (is)g(y)o(our)f(resp)q(onsibilit)o(y)j(to)e(\014nd)g(out)f(\(from)g(a)g
537 | (classmate\))75 2044 y(what)j(y)o(ou)h(missed,)h(includin)q(g)h(class)f
538 | (notes,)f(announcemen)o(ts,)h(and)f(w)o(orksheets.)31
539 | b(Absences)20 b(from)75 2101 y(tests)15 b(will)i(b)q(e)g(excused)f
540 | (only)g(for)f(reasons)g(suc)o(h)h(as)g(serious)g(illness)h(or)e
541 | (o\016cial)i(univ)o(ersit)o(y)f(activities.)75 2157 y(In)g(some)g
542 | (cases)g(the)f(studen)o(t)h(can)g(obtain)g(an)g(excuse)g(from)f
543 | (his/her)i(Dean.)k(A)16 b(studen)o(t)g(who)g(misses)75
544 | 2214 y(a)f(test)g(b)q(ecause)h(of)f(illness)j(and)e(cannot)f(obtain)g
545 | (a)g(Dean's)g(excuse)h(should)h(pic)o(k)f(up)g(a)f(departmen)o(tal)75
546 | 2270 y(excuse)d(form)e(from)g(the)h(Mathematics)f(Departmen)o(t)g
547 | (O\016ce,)i(121)e(Ph)o(ysics)h(Bldg.,)h(\014ll)h(it)e(out,)g(and)g(tak)
548 | o(e)75 2327 y(it)i(to)f(Lewis)i(Blak)o(e,)f(the)g(Sup)q(ervisor)g(of)g
549 | (First-Y)l(ear)f(Instruction,)i(118)e(Ph)o(ysics)h(Bldg.)20
550 | b(If)12 b(the)h(absence)75 2383 y(is)j(excused,)g(the)g(studen)o(t's)f
551 | (grade)g(on)h(the)f(missed)i(test)e(will)i(b)q(e)f(determined)h(either)
552 | f(b)o(y)g(assigning)g(a)75 2440 y(score)g(according)h(to)e(his/her)i(p)
553 | q(erformance)f(on)g(the)g(\014nal)h(exam)f(relativ)o(e)h(to)e(other)h
554 | (studen)o(ts)g(in)h(the)75 2496 y(class)f(or)e(b)o(y)h(a)g(mak)o(e-up)h
555 | (test,)e(at)g(m)o(y)h(discretion.)75 2602 y Fc(Homew)o(ork:)k
556 | Fb(Homew)o(ork)c(\(b)q(oth)g(the)h(reading)h(and)f(the)g(exercises\))g
557 | (should)h(b)q(e)f(completed)h(b)o(y)f(the)75 2659 y(next)c(class)h
558 | (after)f(it)g(is)h(assigned.)19 b(Homew)o(ork)12 b(will)i(not)d(b)q(e)i
559 | (collected,)i(although)d(y)o(our)g(understanding)75 2715
560 | y(of)j(it)h(will)h(b)q(e)g(tested)e(in)i(eac)o(h)f(w)o(eekly)g(quiz)g
561 | (and)g(eac)o(h)g(test.)21 b(It)15 b(is)h(y)o(our)g(resp)q(onsibilit)o
562 | (y)i(to)d(seek)h(help)75 2772 y(on)i(all)g(problems)g(that)f(y)o(ou)h
563 | (cannot)f(do.)27 b(Help)19 b(is)f(a)o(v)m(ailable)i(after)c(class,)j
564 | (in)f(the)g(help)h(ro)q(om)e(or)g(b)o(y)75 2828 y(app)q(oin)o(tmen)o(t)
565 | e(with)h(me.)k(I)15 b(will)i(not)e(discuss)h(homew)o(ork)f(problems)g
566 | (in)i(class.)p eop
567 | %%Page: 2 2
568 | 2 1 bop 75 199 a Fc(Quizzes:)29 b Fb(There)20 b(will)h(b)q(e)f(a)f(25)g
569 | (p)q(oin)o(t,)i(25)e(min)o(ute)h(quiz)g(at)f(the)g(b)q(eginning)j(of)d
570 | (eac)o(h)h(lab)g(p)q(erio)q(d)75 256 y(\(except)j(for)e(the)i(\014rst)f
571 | (w)o(eek,)i(and)f(the)f(w)o(eeks)g(where)h(tests)f(o)q(ccur\).)42
572 | b(The)22 b(quiz)i(will)g(co)o(v)o(er)e(the)75 312 y(previous)17
573 | b(w)o(eek's)f(lab)h(\(if)f(there)h(w)o(as)e(one\),)h(and)h(the)f(homew)
574 | o(ork)g(from)g(the)g(last)g(w)o(eek)h(\(sp)q(eci\014cally)l(,)75
575 | 369 y(the)j(W)l(ednesda)o(y)g(and)f(F)l(rida)o(y)h(of)f(the)h(previous)
576 | g(w)o(eek,)g(and)g(the)g(Monda)o(y)f(of)g(the)g(curren)o(t)h(w)o
577 | (eek\).)75 425 y(Keep)c(in)g(mind)g(that)f(four)g(of)f(these)i(homew)o
578 | (ork/lab)e(quizzes)j(are)e(w)o(orth)f(as)h(m)o(uc)o(h)g(as)g(a)g(test!)
579 | 75 531 y Fc(Labs:)j Fb(There)12 b(will)i(b)q(e)e(a)f(lab)i(eac)o(h)e
580 | (Th)o(ursda)o(y)l(,)h(usually)h(b)q(eginning)h(with)e(the)g(homew)o
581 | (ork/lab)f(quiz)i(for)75 588 y(that)g(w)o(eek.)20 b(If)14
582 | b(y)o(ou)g(are)g(late)g(to)g(lab)g(y)o(ou)g(will)i(ha)o(v)o(e)d(less)i
583 | (time)g(to)e(tak)o(e)h(this)g(quiz.)21 b(Y)l(ou)14 b(are)g(exp)q(ected)
584 | 75 644 y(to)d(read)i(through)e(the)i(lab)f(in)h(the)f(Coursepac)o(k)g
585 | (or)g(b)q(o)q(ok)g(b)q(efore)h(coming)f(to)g(lab.)19
586 | b(There)12 b(is)h(no)f(sp)q(eci\014c)75 701 y(calculator)k(required)g
587 | (for)f(this)h(class)g(but)f(y)o(ou)g(should)h(bring)g(some)f(form)g(of)
588 | g(graphing)h(calculator)g(to)75 757 y(class)k(and)g(lab)g(\(see)g
589 | Fa(http://www.math.duke.ed)o(u/first_)o(year/ca)o(lculato)o(r.html)c
590 | Fb(and)k(page)75 814 y(12)15 b(of)g(y)o(our)g(coursepac)o(k\).)21
591 | b(During)16 b(the)g(lab)g(y)o(ou)g(will)h(w)o(ork)e(in)h(pairs)g(\(if)g
592 | (there)g(are)f(an)h(o)q(dd)g(n)o(um)o(b)q(er)75 870 y(of)e(studen)o(ts)
593 | g(there)g(will)i(b)q(e)f(one)p 567 877 69 2 v 14 w(group)f(of)g
594 | (three\);)g(please)h(c)o(ho)q(ose)g(a)f(p)q(ermanen)o(t)g(lab)h
595 | (partner)f(b)o(y)g(the)75 927 y(second)h(lab.)20 b(If)15
596 | b(y)o(ou)f(do)h(not)f(complete)h(the)g(lab)g(during)h(the)e(lab)h(p)q
597 | (erio)q(d)h(\(as)e(is)h(often)g(the)f(case\),)g(y)o(ou)75
598 | 983 y(and)h(y)o(our)g(lab)g(partner)g(are)g(exp)q(ected)h(to)e(\014nd)i
599 | (time)f(to)g(w)o(ork)f(together)g(out)g(of)h(class)g(and)h(\014nish)g
600 | (the)75 1039 y(lab.)29 b(The)18 b(labs)g(will)i(not)d(b)q(e)i
601 | (collected)g(\(although)f(there)g(will)i(b)q(e)e(t)o(w)o(o)f(lab)h(rep)
602 | q(orts\).)28 b(Y)l(ou)18 b(will)h(b)q(e)75 1096 y(tested)14
603 | b(on)g(y)o(our)f(understanding)i(of)f(the)g(lab)g(material)h(on)e(the)h
604 | (quizzes,)i(tests,)d(and)h(the)g(\014nal)h(exam.)75 1202
605 | y Fc(T)l(ests)j(and)h(Cheat)g(Sheets:)i Fb(There)c(will)g(b)q(e)g
606 | (three)f(tests)g(in)h(this)f(course,)g(eac)o(h)g(taking)g(an)h(en)o
607 | (tire)75 1259 y(lab)f(p)q(erio)q(d.)23 b(Please)16 b(see)g(\\Absences")
608 | g(ab)q(o)o(v)o(e)g(for)f(related)h(information.)22 b(I)16
609 | b(do)f(not)h(allo)o(w)g(the)f(use)h(of)75 1315 y(\\c)o(heat)d(sheets")h
610 | (during)g(the)g(exams.)19 b(Ho)o(w)o(ev)o(er,)12 b(since)j(some)e
611 | (other)g(sections)i(do)e(allo)o(w)h(c)o(heat)f(sheets,)75
612 | 1372 y(and)g(y)o(ou)g(will)i(b)q(e)f(allo)o(w)o(ed)f(to)g(use)g(a)g(c)o
613 | (heat)g(sheet)g(during)h(the)g(\014nal)g(exam,)e(I)i(encourage)f(y)o
614 | (ou)g(to)f(mak)o(e)75 1428 y(a)17 b(one-page,)g(t)o(w)o(o-sided)g(\\c)o
615 | (heat)g(sheet")f(for)h(eac)o(h)g(test.)25 b(I)17 b(will)i(collect)f
616 | (these)f(c)o(heat)g(sheets)g(\(b)q(efore)p 1754 1435
617 | 122 2 v 75 1484 a(eac)o(h)e(test,)g(of)g(course\).)20
618 | b(Y)l(ou)15 b(can)h(earn)f(up)h(to)f(three)g(extra)g(p)q(oin)o(ts)h(on)
619 | f(the)g(test)g(\(not)g(to)f(exceed)j(100)75 1541 y(total)h(p)q(oin)o
620 | (ts\))g(for)g(handing)h(in)h(a)e(complete)h(c)o(heat)f(sheet.)30
621 | b(It)18 b(should)h(b)q(e)h(m)o(uc)o(h)e(easier)h(for)f(y)o(ou)g(to)75
622 | 1597 y(mak)o(e)d(y)o(our)f(\014nal)i(exam)f(c)o(heat)g(sheet)h(if)f(y)o
623 | (ou)g(ha)o(v)o(e)g(already)g(made)h(one)f(for)g(eac)o(h)g(test.)75
624 | 1704 y Fc(The)i(Final:)j Fb(The)15 b(\014nal)g(exam)e(for)h(this)h
625 | (course)f(is)g(a)g(\\blo)q(c)o(k")h(\014nal,)f(meaning)h(all)g
626 | (sections)g(will)h(tak)o(e)75 1760 y(the)k(same)f(exam;)i(the)f
627 | (\014nal)g(will)h(b)q(e)g(giv)o(en)f(on)f(T)l(uesda)o(y)l(,)i(Ma)o(y)d
628 | (4,)i(1999)f(at)g(7)g(pm)h(-)f(10)g(pm.)33 b(See)75 1817
629 | y(h)o(ttp://registrar.duk)o(e.edu/registrar/exams99)o(.h)o(tm)10
630 | b(and)k(page)g(11)g(in)g(y)o(our)g(Coursepac)o(k)f(for)g(more)75
631 | 1873 y(information.)75 1979 y Fc(The)j(Gatew)o(a)o(y:)i
632 | Fb(Y)l(ou)c(will)h(ha)o(v)o(e)d(to)h(pass)g(a)g(di\013eren)o(tiation)h
633 | (gatew)o(a)o(y)e(to)h(get)f(credit)i(for)f(this)h(course)75
634 | 2036 y(\(see)19 b(page)g(12)f(in)i(y)o(our)e(coursepac)o(k\).)31
635 | b(An)o(y)o(one)19 b(who)f(do)q(es)i(not)e(pass)h(the)g(gatew)o(a)o(y)e
636 | (the)i(\014rst)g(time)75 2092 y(will)i(ha)o(v)o(e)e(to)g(hand)h(in)g(a)
637 | f(\\gatew)o(a)o(y)f(homew)o(ork")g(in)i(class)g(eac)o(h)f(F)l(rida)o(y)
638 | h(un)o(til)g(they)g(ha)o(v)o(e)f(passed)75 2149 y(the)14
639 | b(gatew)o(a)o(y)l(.)k(Unsatisfactory)13 b(p)q(erformance)h(on)g(this)h
640 | (homew)o(ork)e(will)j(result)e(in)h(a)f(deduction)h(of)e(up)75
641 | 2205 y(to)i(\014v)o(e)h(p)q(oin)o(ts)g(\(not)f(to)g(b)q(e)i(lo)o(w)o
642 | (er)e(than)h(0)f(total)g(p)q(oin)o(ts\))h(from)f(y)o(our)g(previous)i
643 | (homew)o(ork/lab)e(quiz)75 2262 y(score.)75 2368 y Fc(Help)k(Ro)q(om:)k
644 | Fb(I)16 b(strongly)g(suggest)g(that)g(y)o(ou)g(visit)h(the)f(help)i(ro)
645 | q(om)e(often,)g(esp)q(ecially)j(during)e(the)75 2424
646 | y(hours)g(that)g(I)h(will)h(b)q(e)f(w)o(orking)f(there)h(\(to)e(b)q(e)i
647 | (announced\),)g(and)g(while)h(other)e(26L)g(instructors)g(or)75
648 | 2481 y(lab)g(T)l(As)f(are)h(there.)23 b(The)17 b(help)h(ro)q(om)e(is)g
649 | (in)i(08)e(W)l(est)g(Duk)o(e)g(\(in)h(the)g(basemen)o(t\))f(and)g(is)h
650 | (op)q(en)g(1:00)75 2537 y(pm)g(-)h(10:00)d(pm)j(Monda)o(y)e(-)i(Th)o
651 | (ursda)o(y)f(and)g(6:00)f(pm)h(-)h(10:00)e(pm)h(Sunda)o(y)l(.)27
652 | b(The)17 b(help)i(ro)q(om)d(will)75 2594 y(b)q(egin)f(on)f(Sunda)o(y)l
653 | (,)g(Jan)o(uary)f(17,)g(1999,)g(and)h(op)q(erate)f(through)h(Sunda)o(y)
654 | l(,)g(Ma)o(y)f(2,)g(except)h(for)f(Martin)75 2650 y(Luther)23
655 | b(King's)f(birthda)o(y)h(on)f(Monda)o(y)l(,)h(Jan)o(uary)f(18,)h(and)f
656 | (from)g(Sunda)o(y)l(,)i(Marc)o(h)d(14,)i(through)75 2707
657 | y(Sunda)o(y)l(,)17 b(Marc)o(h)f(21,)g(for)h(spring)g(break.)24
658 | b(The)17 b(help)h(ro)q(om)e(is)h(discussed)i(brie\015y)e(on)g(page)f
659 | (12)h(of)f(the)75 2763 y(Coursepac)o(k.)28 b(F)l(ollo)o(w)18
660 | b(the)g(link)h(on)f Fa(http://www.math.duke.edu/)o(first_y)o(ear/help)o
661 | (.html)d Fb(for)75 2819 y(more)g(information.)p eop
662 | %%Trailer
663 | end
664 | userdict /end-hook known{end-hook}if
665 | %%EOF
666 |
--------------------------------------------------------------------------------