successful png test in test5

main
Matthew Butterick 8 years ago
parent f5e2b33bd8
commit aad217a55e

@ -3,10 +3,15 @@ PNG = require 'png-js'
class PNGImage
constructor: (data, @label) ->
console.log("raw data")
console.log(data.slice(0, 20))
@image = new PNG(data)
@width = @image.width
@height = @image.height
@imgData = @image.imgData
console.log("result from png-js")
console.log(@imgData.slice(0, 20))
console.log(@image)
@obj = null
embed: (@document) ->
@ -43,12 +48,14 @@ class PNGImage
# For PNG color types 0, 2 and 3, the transparency data is stored in
# a dedicated PNG chunk.
if @image.transparency.grayscale
console.log("transparency.grayscale")
# Use Color Key Masking (spec section 4.8.5)
# An array with N elements, where N is two times the number of color components.
val = @image.transparency.greyscale
@obj.data['Mask'] = [val, val]
else if @image.transparency.rgb
console.log("transparency.rgb")
# Use Color Key Masking (spec section 4.8.5)
# An array with N elements, where N is two times the number of color components.
rgb = @image.transparency.rgb
@ -59,11 +66,13 @@ class PNGImage
@obj.data['Mask'] = mask
else if @image.transparency.indexed
console.log("transparency.indexed")
# Create a transparency SMask for the image based on the data
# in the PLTE and tRNS sections. See below for details on SMasks.
@loadIndexedAlphaChannel()
else if @image.hasAlphaChannel
console.log("alphachannel")
# For PNG color types 4 and 6, the transparency data is stored as a alpha
# channel mixed in with the main image data. Separate this data out into an
# SMask object and store it separately in the PDF.
@ -88,6 +97,7 @@ class PNGImage
@obj.data['SMask'] = sMask
# add the actual image data
console.log(@imgData)
@obj.end @imgData
# free memory

@ -56,6 +56,8 @@
this.text = {};
while (true) {
chunkSize = this.readUInt32();
console.log("chunkSize")
console.log(chunkSize)
section = ((function() {
var _i, _results;
_results = [];
@ -64,6 +66,8 @@
}
return _results;
}).call(this)).join('');
console.log("section")
console.log(section)
switch (section) {
case 'IHDR':
this.width = this.readUInt32();

@ -145,6 +145,8 @@ class PNG
when 1 then 'DeviceGray'
when 3 then 'DeviceRGB'
console.log("imgdata")
console.log(@imgData)
@imgData = new Uint8Array @imgData
return
@ -156,6 +158,8 @@ class PNG
if @pos > @data.length
throw new Error "Incomplete or corrupt PNG file"
console.log("done parsing PNG")
return

@ -1,458 +0,0 @@
// Generated by CoffeeScript 1.4.0
/*
# MIT LICENSE
# Copyright (c) 2011 Devon Govett
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
# to whom the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or
# substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
(function() {
var PNG;
PNG = (function() {
var APNG_BLEND_OP_OVER, APNG_BLEND_OP_SOURCE, APNG_DISPOSE_OP_BACKGROUND, APNG_DISPOSE_OP_NONE, APNG_DISPOSE_OP_PREVIOUS, makeImage, scratchCanvas, scratchCtx;
PNG.load = function(url, canvas, callback) {
var xhr,
_this = this;
if (typeof canvas === 'function') {
callback = canvas;
}
xhr = new XMLHttpRequest;
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.onload = function() {
var data, png;
data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
png = new PNG(data);
if (typeof (canvas != null ? canvas.getContext : void 0) === 'function') {
png.render(canvas);
}
return typeof callback === "function" ? callback(png) : void 0;
};
return xhr.send(null);
};
APNG_DISPOSE_OP_NONE = 0;
APNG_DISPOSE_OP_BACKGROUND = 1;
APNG_DISPOSE_OP_PREVIOUS = 2;
APNG_BLEND_OP_SOURCE = 0;
APNG_BLEND_OP_OVER = 1;
function PNG(data) {
var chunkSize, colors, delayDen, delayNum, frame, i, index, key, section, short, text, _i, _j, _ref;
this.data = data;
this.pos = 8;
this.palette = [];
this.imgData = [];
this.transparency = {};
this.animation = null;
this.text = {};
frame = null;
while (true) {
chunkSize = this.readUInt32();
section = ((function() {
var _i, _results;
_results = [];
for (i = _i = 0; _i < 4; i = ++_i) {
_results.push(String.fromCharCode(this.data[this.pos++]));
}
return _results;
}).call(this)).join('');
switch (section) {
case 'IHDR':
this.width = this.readUInt32();
this.height = this.readUInt32();
this.bits = this.data[this.pos++];
this.colorType = this.data[this.pos++];
this.compressionMethod = this.data[this.pos++];
this.filterMethod = this.data[this.pos++];
this.interlaceMethod = this.data[this.pos++];
break;
case 'acTL':
this.animation = {
numFrames: this.readUInt32(),
numPlays: this.readUInt32() || Infinity,
frames: []
};
break;
case 'PLTE':
this.palette = this.read(chunkSize);
break;
case 'fcTL':
if (frame) {
this.animation.frames.push(frame);
}
this.pos += 4;
frame = {
width: this.readUInt32(),
height: this.readUInt32(),
xOffset: this.readUInt32(),
yOffset: this.readUInt32()
};
delayNum = this.readUInt16();
delayDen = this.readUInt16() || 100;
frame.delay = 1000 * delayNum / delayDen;
frame.disposeOp = this.data[this.pos++];
frame.blendOp = this.data[this.pos++];
frame.data = [];
break;
case 'IDAT':
case 'fdAT':
if (section === 'fdAT') {
this.pos += 4;
chunkSize -= 4;
}
data = (frame != null ? frame.data : void 0) || this.imgData;
for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) {
data.push(this.data[this.pos++]);
}
break;
case 'tRNS':
this.transparency = {};
switch (this.colorType) {
case 3:
this.transparency.indexed = this.read(chunkSize);
short = 255 - this.transparency.indexed.length;
if (short > 0) {
for (i = _j = 0; 0 <= short ? _j < short : _j > short; i = 0 <= short ? ++_j : --_j) {
this.transparency.indexed.push(255);
}
}
break;
case 0:
this.transparency.grayscale = this.read(chunkSize)[0];
break;
case 2:
this.transparency.rgb = this.read(chunkSize);
}
break;
case 'tEXt':
text = this.read(chunkSize);
index = text.indexOf(0);
key = String.fromCharCode.apply(String, text.slice(0, index));
this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1));
break;
case 'IEND':
if (frame) {
this.animation.frames.push(frame);
}
this.colors = (function() {
switch (this.colorType) {
case 0:
case 3:
case 4:
return 1;
case 2:
case 6:
return 3;
}
}).call(this);
this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6;
colors = this.colors + (this.hasAlphaChannel ? 1 : 0);
this.pixelBitlength = this.bits * colors;
this.colorSpace = (function() {
switch (this.colors) {
case 1:
return 'DeviceGray';
case 3:
return 'DeviceRGB';
}
}).call(this);
this.imgData = new Uint8Array(this.imgData);
return;
default:
this.pos += chunkSize;
}
this.pos += 4;
if (this.pos > this.data.length) {
throw new Error("Incomplete or corrupt PNG file");
}
}
return;
}
PNG.prototype.read = function(bytes) {
var i, _i, _results;
_results = [];
for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
_results.push(this.data[this.pos++]);
}
return _results;
};
PNG.prototype.readUInt32 = function() {
var b1, b2, b3, b4;
b1 = this.data[this.pos++] << 24;
b2 = this.data[this.pos++] << 16;
b3 = this.data[this.pos++] << 8;
b4 = this.data[this.pos++];
return b1 | b2 | b3 | b4;
};
PNG.prototype.readUInt16 = function() {
var b1, b2;
b1 = this.data[this.pos++] << 8;
b2 = this.data[this.pos++];
return b1 | b2;
};
PNG.prototype.decodePixels = function(data) {
var byte, c, col, i, left, length, p, pa, paeth, pb, pc, pixelBytes, pixels, pos, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m;
if (data == null) {
data = this.imgData;
}
if (data.length === 0) {
return new Uint8Array(0);
}
data = new FlateStream(data);
data = data.getBytes();
pixelBytes = this.pixelBitlength / 8;
scanlineLength = pixelBytes * this.width;
pixels = new Uint8Array(scanlineLength * this.height);
length = data.length;
row = 0;
pos = 0;
c = 0;
while (pos < length) {
switch (data[pos++]) {
case 0:
for (i = _i = 0; _i < scanlineLength; i = _i += 1) {
pixels[c++] = data[pos++];
}
break;
case 1:
for (i = _j = 0; _j < scanlineLength; i = _j += 1) {
byte = data[pos++];
left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
pixels[c++] = (byte + left) % 256;
}
break;
case 2:
for (i = _k = 0; _k < scanlineLength; i = _k += 1) {
byte = data[pos++];
col = (i - (i % pixelBytes)) / pixelBytes;
upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
pixels[c++] = (upper + byte) % 256;
}
break;
case 3:
for (i = _l = 0; _l < scanlineLength; i = _l += 1) {
byte = data[pos++];
col = (i - (i % pixelBytes)) / pixelBytes;
left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
pixels[c++] = (byte + Math.floor((left + upper) / 2)) % 256;
}
break;
case 4:
for (i = _m = 0; _m < scanlineLength; i = _m += 1) {
byte = data[pos++];
col = (i - (i % pixelBytes)) / pixelBytes;
left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
if (row === 0) {
upper = upperLeft = 0;
} else {
upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + (i % pixelBytes)];
}
p = left + upper - upperLeft;
pa = Math.abs(p - left);
pb = Math.abs(p - upper);
pc = Math.abs(p - upperLeft);
if (pa <= pb && pa <= pc) {
paeth = left;
} else if (pb <= pc) {
paeth = upper;
} else {
paeth = upperLeft;
}
pixels[c++] = (byte + paeth) % 256;
}
break;
default:
throw new Error("Invalid filter algorithm: " + data[pos - 1]);
}
row++;
}
return pixels;
};
PNG.prototype.decodePalette = function() {
var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1;
palette = this.palette;
transparency = this.transparency.indexed || [];
ret = new Uint8Array((transparency.length || 0) + palette.length);
pos = 0;
length = palette.length;
c = 0;
for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) {
ret[pos++] = palette[i];
ret[pos++] = palette[i + 1];
ret[pos++] = palette[i + 2];
ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255;
}
return ret;
};
PNG.prototype.copyToImageData = function(imageData, pixels) {
var alpha, colors, data, i, input, j, k, length, palette, v, _ref;
colors = this.colors;
palette = null;
alpha = this.hasAlphaChannel;
if (this.palette.length) {
palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette();
colors = 4;
alpha = true;
}
data = imageData.data;
length = data.length;
input = palette || pixels;
i = j = 0;
if (colors === 1) {
while (i < length) {
k = palette ? pixels[i / 4] * 4 : j;
v = input[k++];
data[i++] = v;
data[i++] = v;
data[i++] = v;
data[i++] = alpha ? input[k++] : 255;
j = k;
}
} else {
while (i < length) {
k = palette ? pixels[i / 4] * 4 : j;
data[i++] = input[k++];
data[i++] = input[k++];
data[i++] = input[k++];
data[i++] = alpha ? input[k++] : 255;
j = k;
}
}
};
PNG.prototype.decode = function() {
var ret;
ret = new Uint8Array(this.width * this.height * 4);
this.copyToImageData(ret, this.decodePixels());
return ret;
};
scratchCanvas = document.createElement('canvas');
scratchCtx = scratchCanvas.getContext('2d');
makeImage = function(imageData) {
var img;
scratchCtx.width = imageData.width;
scratchCtx.height = imageData.height;
scratchCtx.clearRect(0, 0, imageData.width, imageData.height);
scratchCtx.putImageData(imageData, 0, 0);
img = new Image;
img.src = scratchCanvas.toDataURL();
return img;
};
PNG.prototype.decodeFrames = function(ctx) {
var frame, i, imageData, pixels, _i, _len, _ref, _results;
if (!this.animation) {
return;
}
_ref = this.animation.frames;
_results = [];
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
frame = _ref[i];
imageData = ctx.createImageData(frame.width, frame.height);
pixels = this.decodePixels(new Uint8Array(frame.data));
this.copyToImageData(imageData, pixels);
frame.imageData = imageData;
_results.push(frame.image = makeImage(imageData));
}
return _results;
};
PNG.prototype.renderFrame = function(ctx, number) {
var frame, frames, prev;
frames = this.animation.frames;
frame = frames[number];
prev = frames[number - 1];
if (number === 0) {
ctx.clearRect(0, 0, this.width, this.height);
}
if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND) {
ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height);
} else if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS) {
ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset);
}
if (frame.blendOp === APNG_BLEND_OP_SOURCE) {
ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height);
}
return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset);
};
PNG.prototype.animate = function(ctx) {
var doFrame, frameNumber, frames, numFrames, numPlays, _ref,
_this = this;
frameNumber = 0;
_ref = this.animation, numFrames = _ref.numFrames, frames = _ref.frames, numPlays = _ref.numPlays;
return (doFrame = function() {
var f, frame;
f = frameNumber++ % numFrames;
frame = frames[f];
_this.renderFrame(ctx, f);
if (numFrames > 1 && frameNumber / numFrames < numPlays) {
return _this.animation._timeout = setTimeout(doFrame, frame.delay);
}
})();
};
PNG.prototype.stopAnimation = function() {
var _ref;
return clearTimeout((_ref = this.animation) != null ? _ref._timeout : void 0);
};
PNG.prototype.render = function(canvas) {
var ctx, data;
if (canvas._png) {
canvas._png.stopAnimation();
}
canvas._png = this;
canvas.width = this.width;
canvas.height = this.height;
ctx = canvas.getContext("2d");
if (this.animation) {
this.decodeFrames(ctx);
return this.animate(ctx);
} else {
data = ctx.createImageData(this.width, this.height);
this.copyToImageData(data, this.decodePixels());
return ctx.putImageData(data, 0, 0);
}
};
return PNG;
})();
window.PNG = PNG;
}).call(this);

@ -127,7 +127,7 @@
(define/contract (_refEnd this ref)
((is-a?/c PDFReference) . ->m . void?)
(report* (· ref id) (· this _offsets))
#;(report* (· ref id) (· this _offsets))
(hash-set! (· this _offsets) (· ref id) (· ref offset)))
@ -138,8 +138,8 @@
(define/contract (end this) ; called from source file to finish doc
(->m void?)
(report* 'start-end)
(report* (· this _offsets))
#;(report* 'start-end)
#;(report* (· this _offsets))
(flushPages this)
(define _info (ref this))
@ -147,18 +147,19 @@
;; upgrade string literal to String struct
(hash-set! (· _info payload) key (if (string? val) (String val) val)))
(report* (· this _offsets))
#;(report* (· this _offsets))
(· _info end)
(for ([font (in-hash-values (· this _fontFamilies))])
(· font finalize))
(report* (· this _offsets))
#;(report* (· this _offsets))
(· this _root end)
(report* (· this _offsets))
#;(report* (· this _offsets))
(· this _root payload Pages end)
(report* (· this _offsets))
#;(report* (· this _offsets))
;; generate xref
(define xref-offset (· this _offset))

@ -1,5 +1,5 @@
#lang racket/base
(require (for-syntax racket/base racket/syntax) racket/class sugar/list racket/list (only-in br/list push! pop!) racket/string)
(require (for-syntax racket/base racket/syntax) racket/class sugar/list racket/list (only-in br/list push! pop!) racket/string racket/format)
(provide (all-defined-out) push! pop!)
(define-syntax (· stx)
@ -168,4 +168,11 @@
(define-syntax-rule (define-subclass CLASS-ID (SUBCLASS-ID INIT-FIELD ...) . EXPRS)
(define SUBCLASS-ID
(class CLASS-ID
(init-field INIT-FIELD ...) . EXPRS)))
(init-field INIT-FIELD ...) . EXPRS)))
(define (bytes->hex bstr)
(map (λ (b) (string->symbol (string-append (if (< b 16)
"x0" "x") (~r b #:base 16)))) (bytes->list bstr)))
(module+ test
(check-equal? (bytes->hex #"PNG") '(x50 x4e x47)))

@ -0,0 +1,55 @@
#lang pitfall/racket
(provide read-png)
#|
Grab key chunks from PNG. Doesn't require heavy lifting from libpng.
|#
(define/contract (read-png ip-or-bytes)
((or/c input-port? bytes?) . -> . hash?)
(define png (make-hasheq))
(parameterize ([current-input-port (if (input-port? ip-or-bytes)
ip-or-bytes
(open-input-bytes ip-or-bytes))])
(define header (read-bytes 8))
(let loop ()
(cond
[(eof-object? (peek-byte)) png]
[else
(define chunk-size (readUInt32))
(define chunk-name (read-bytes 4))
(case chunk-name
[(#"IHDR") (hash-set*! png 'width (readUInt32)
'height (readUInt32)
'bits (read-byte)
'colorType (read-byte)
'compressionMethod (read-byte)
'filterMethod (read-byte)
'interlaceMethod (read-byte))]
[(#"PLTE") (hash-set*! png 'palette (read-bytes chunk-size))]
[(#"IDAT") (hash-set*! png 'imgData (read-bytes chunk-size))]
[(#"tRNS") (read-bytes chunk-size)]
[(#"tEXt") (read-bytes chunk-size)]
[(#"IEND") (hash-set! png 'colors
(case (hash-ref png 'colorType)
[(0 3 4) 1]
[(2 6) 3]))
(hash-set! png 'hasAlphaChannel (member (hash-ref png 'colorType) '(4 6)))
(define colors (+ (hash-ref png 'colors) (if (hash-ref png 'hasAlphaChannel) 1 0)))
(hash-set! png 'pixelBitlength (* (hash-ref png 'bits) colors))
(hash-set! png 'colorSpace
(case (hash-ref png 'colors)
[(1) "DeviceGray"]
[(3) "DeviceRGB"]))]
[else (read-bytes chunk-size)])
(read-bytes 4) ; skip crc
(loop)]))))
(define (readUInt32)
(integer-bytes->integer (read-bytes 4) #t #t))
(module+ test
(require rackunit)
(check-equal?
(read-png (open-input-file "test/assets/test.png"))
(read-png (file->bytes "test/assets/test.png"))))

@ -1,24 +1,20 @@
#lang pitfall/racket
(require racket/draw/unsafe/png racket/draw/private/bitmap)
(require "png-reader.rkt")
(provide PNG)
(define-subclass object% (PNG data label)
(super-new)
(field [image (make-object bitmap% (open-input-bytes data) 'png)]
[width (· image get-width)]
[height (· image get-height)]
[imgData data]
(field [image (read-png data)]
[width (· image width)]
[height (· image height)]
[imgData (· image imgData)]
[obj #f]
[document #f]) ; for `embed`
[document #f])
(as-methods
embed
finalize))
embed))
(define png-grayscale 1)
(define png-color 3)
(define/contract (embed this doc-in)
(object? . ->m . void?)
(set-field! document this doc-in)
@ -28,34 +24,34 @@
(send (· this document) ref
(mhash 'Type "XObject"
'Subtype "Image"
'BitsPerComponent (· this image get-depth)
'BitsPerComponent (· this image bits)
'Width (· this width)
'Height (· this height)
'Filter "FlateDecode")))
(define params (mhash))
(unless (· this image has-alpha-channel?)
(set! params (send (· this document) ref (mhash 'Predictor 15
'Colors (if (· this image is-color?)
png-color
png-grayscale)
'BitsPerComponent (· this image get-depth)
'Columns (· this width)))))
(unless (· this image hasAlphaChannel)
(define params (send (· this document) ref (mhash 'Predictor 15
'Colors (· this image colors)
'BitsPerComponent (· this image bits)
'Columns (· this width))))
(hash-set! (· this obj payload) 'DecodeParms params)
(send params end))
(hash-set! (· this obj payload) 'DecodeParms params)
(send params end)
(cond
[(hash-ref (· this image) 'palette #f)
;; embed the color palette in the PDF as an object stream
(define palette-ref (· this document ref))
(send palette-ref end (· this image palette))
(send this finalize)
;; build the color space array for the image
(hash-set! (· this object payload) 'Colorspace
(list "Indexed" "DeviceRGB" (sub1 (bytes-length (· this image palette))) palette-ref))]
[else (hash-set! (· this obj payload) 'ColorSpace "DeviceRGB")])
#;(error 'stop-in-png:embed)))
(define (finalize this)
;; add the actual image data
(send (· this obj) end (· this imgData)))
;; todo: transparency & alpha channel shit
#;(module+ test
(define data (file->bytes "test/assets/test.png"))
(define bm (make-object bitmap% (open-input-bytes data) 'png))
bm)
;; embed the actual image data
(send (· this obj) end (· this imgData))))

@ -26,11 +26,11 @@
(when chunk
(send this write chunk))
(report* 'end! (· this id))
#;(report* 'end! (· this id))
(define bstrs-to-write
(let ([current-bstrs (reverse (· this byte-strings))])
(if (and (or (compress-streams?)
(equal? (hash-ref (· this payload) 'Filter #f) "FlateDecode"))
(if (and (compress-streams?)
(not (hash-ref (· this payload) 'Filter #f))
(got-byte-strings? current-bstrs))
(let ([deflated-chunk (deflate (apply bytes-append current-bstrs))])
(hash-set! (· this payload) 'Filter "FlateDecode")
@ -53,7 +53,7 @@
(doc_write "\nendstream"))
(doc_write "endobj"))
(report (· this id))
#;(report (· this id))
(send this-doc _refEnd this))

@ -5,7 +5,7 @@ make = (doc) ->
# Set the font, draw some text, and embed an image
doc.font('Times-Italic')
.fontSize(25)
.text('Some text with an embedded font!', 100, 100, lineBreak: no)
.text('Some fantastic text!', 100, 100, lineBreak: no)
.image('death.png', 100, 160, width: 412)
doc.end()
@ -14,7 +14,7 @@ doc = new PDFDocument({compress: no})
doc.pipe(fs.createWriteStream('test5.pdf'))
make doc
#doc = new PDFDocument({compress: yes})
#doc.pipe(fs.createWriteStream('test5c.pdf'))
#make doc
doc = new PDFDocument({compress: yes})
doc.pipe(fs.createWriteStream('test5c.pdf'))
make doc

Binary file not shown.

@ -4,13 +4,11 @@
(send* doc
[font "Times-Italic"]
[fontSize 25]
[text "Some text with an embedded font!" 100 100 (hash 'lineBreak #f)]
[image "death.png" 100 160 (hash 'width 412)]
#;[image "assets/test.jpeg" 190 400 (hash 'height 300)]))
[text "Some fantastic text!" 100 100 (hash 'lineBreak #f)]
[image "death.png" 100 160 (hash 'width 412)]))
(define-runtime-path this "test5rkt.pdf")
(make-doc this #f proc #:test #f)
#;(define-runtime-path that "test5crkt.pdf")
#;(make-doc that #t proc)
(make-doc this #f proc #:test #t)
(define-runtime-path that "test5crkt.pdf")
(make-doc that #t proc)

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save