From 0c441b2478b19491cca214575ae7c3584f4ec6fb Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Thu, 24 Aug 2017 12:43:57 -0700 Subject: [PATCH] fix transformation composition & annotations --- pitfall/pdfkit/lib/mixins/annotations.coffee | 1 + pitfall/pdfkit/lib/mixins/text.coffee | 2 +- pitfall/pdfkit/lib/mixins/vector.js | 265 ------------------- pitfall/pitfall/annotations.rkt | 12 +- pitfall/pitfall/test/test11.coffee | 5 + pitfall/pitfall/test/test11.pdf | 132 +++++++++ pitfall/pitfall/test/test11.rkt | 1 + pitfall/pitfall/test/test11c.pdf | 12 +- pitfall/pitfall/test/test11crkt copy.pdf | 18 +- pitfall/pitfall/test/test11crkt.pdf | 18 +- pitfall/pitfall/test/test11rkt copy.pdf | 15 +- pitfall/pitfall/test/test11rkt.pdf | 15 +- pitfall/pitfall/vector.rkt | 29 +- 13 files changed, 203 insertions(+), 322 deletions(-) delete mode 100644 pitfall/pdfkit/lib/mixins/vector.js create mode 100644 pitfall/pitfall/test/test11.pdf diff --git a/pitfall/pdfkit/lib/mixins/annotations.coffee b/pitfall/pdfkit/lib/mixins/annotations.coffee index 482f15d6..e3347df0 100644 --- a/pitfall/pdfkit/lib/mixins/annotations.coffee +++ b/pitfall/pdfkit/lib/mixins/annotations.coffee @@ -1,5 +1,6 @@ module.exports = annotate: (x, y, w, h, options) -> + #console.log(@_ctm) options.Type = 'Annot' options.Rect = @_convertRect x, y, w, h options.Border = [0, 0, 0] diff --git a/pitfall/pdfkit/lib/mixins/text.coffee b/pitfall/pdfkit/lib/mixins/text.coffee index 48c7fc21..136f2d94 100644 --- a/pitfall/pdfkit/lib/mixins/text.coffee +++ b/pitfall/pdfkit/lib/mixins/text.coffee @@ -205,7 +205,7 @@ module.exports = # create underline or strikethrough line if options.underline or options.strike - console.log("enter underline") + #console.log("enter underline") @save() @strokeColor @_fillColor... unless options.stroke diff --git a/pitfall/pdfkit/lib/mixins/vector.js b/pitfall/pdfkit/lib/mixins/vector.js deleted file mode 100644 index a7beed7e..00000000 --- a/pitfall/pdfkit/lib/mixins/vector.js +++ /dev/null @@ -1,265 +0,0 @@ -// Generated by CoffeeScript 1.12.5 -(function() { - var KAPPA, SVGPath, number, - slice = [].slice; - - SVGPath = require('../path'); - - number = require('../object').number; - - KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0); - - module.exports = { - initVector: function() { - this._ctm = [1, 0, 0, 1, 0, 0]; - return this._ctmStack = []; - }, - save: function() { - this._ctmStack.push(this._ctm.slice()); - return this.addContent('q'); - }, - restore: function() { - this._ctm = this._ctmStack.pop() || [1, 0, 0, 1, 0, 0]; - return this.addContent('Q'); - }, - closePath: function() { - return this.addContent('h'); - }, - lineWidth: function(w) { - return this.addContent((number(w)) + " w"); - }, - _CAP_STYLES: { - BUTT: 0, - ROUND: 1, - SQUARE: 2 - }, - lineCap: function(c) { - if (typeof c === 'string') { - c = this._CAP_STYLES[c.toUpperCase()]; - } - return this.addContent(c + " J"); - }, - _JOIN_STYLES: { - MITER: 0, - ROUND: 1, - BEVEL: 2 - }, - lineJoin: function(j) { - if (typeof j === 'string') { - j = this._JOIN_STYLES[j.toUpperCase()]; - } - return this.addContent(j + " j"); - }, - miterLimit: function(m) { - return this.addContent((number(m)) + " M"); - }, - dash: function(length, options) { - var phase, ref, space, v; - if (options == null) { - options = {}; - } - if (length == null) { - return this; - } - if (Array.isArray(length)) { - length = ((function() { - var i, len, results; - results = []; - for (i = 0, len = length.length; i < len; i++) { - v = length[i]; - results.push(number(v)); - } - return results; - })()).join(' '); - phase = options.phase || 0; - return this.addContent("[" + length + "] " + (number(phase)) + " d"); - } else { - space = (ref = options.space) != null ? ref : length; - phase = options.phase || 0; - return this.addContent("[" + (number(length)) + " " + (number(space)) + "] " + (number(phase)) + " d"); - } - }, - undash: function() { - return this.addContent("[] 0 d"); - }, - moveTo: function(x, y) { - return this.addContent((number(x)) + " " + (number(y)) + " m"); - }, - lineTo: function(x, y) { - return this.addContent((number(x)) + " " + (number(y)) + " l"); - }, - bezierCurveTo: function(cp1x, cp1y, cp2x, cp2y, x, y) { - return this.addContent((number(cp1x)) + " " + (number(cp1y)) + " " + (number(cp2x)) + " " + (number(cp2y)) + " " + (number(x)) + " " + (number(y)) + " c"); - }, - quadraticCurveTo: function(cpx, cpy, x, y) { - return this.addContent((number(cpx)) + " " + (number(cpy)) + " " + (number(x)) + " " + (number(y)) + " v"); - }, - rect: function(x, y, w, h) { - return this.addContent((number(x)) + " " + (number(y)) + " " + (number(w)) + " " + (number(h)) + " re"); - }, - roundedRect: function(x, y, w, h, r) { - var c; - if (r == null) { - r = 0; - } - r = Math.min(r, 0.5 * w, 0.5 * h); - c = r * (1.0 - KAPPA); - this.moveTo(x + r, y); - this.lineTo(x + w - r, y); - this.bezierCurveTo(x + w - c, y, x + w, y + c, x + w, y + r); - this.lineTo(x + w, y + h - r); - this.bezierCurveTo(x + w, y + h - c, x + w - c, y + h, x + w - r, y + h); - this.lineTo(x + r, y + h); - this.bezierCurveTo(x + c, y + h, x, y + h - c, x, y + h - r); - this.lineTo(x, y + r); - this.bezierCurveTo(x, y + c, x + c, y, x + r, y); - return this.closePath(); - }, - ellipse: function(x, y, r1, r2) { - var ox, oy, xe, xm, ye, ym; - if (r2 == null) { - r2 = r1; - } - x -= r1; - y -= r2; - ox = r1 * KAPPA; - oy = r2 * KAPPA; - xe = x + r1 * 2; - ye = y + r2 * 2; - xm = x + r1; - ym = y + r2; - this.moveTo(x, ym); - this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - return this.closePath(); - }, - circle: function(x, y, radius) { - return this.ellipse(x, y, radius); - }, - polygon: function() { - var i, len, point, points; - points = 1 <= arguments.length ? slice.call(arguments, 0) : []; - this.moveTo.apply(this, points.shift()); - for (i = 0, len = points.length; i < len; i++) { - point = points[i]; - this.lineTo.apply(this, point); - } - return this.closePath(); - }, - path: function(path) { - SVGPath.apply(this, path); - return this; - }, - _windingRule: function(rule) { - if (/even-?odd/.test(rule)) { - return '*'; - } - return ''; - }, - fill: function(color, rule) { - if (/(even-?odd)|(non-?zero)/.test(color)) { - rule = color; - color = null; - } - if (color) { - this.fillColor(color); - } - return this.addContent('f' + this._windingRule(rule)); - }, - stroke: function(color) { - if (color) { - this.strokeColor(color); - } - return this.addContent('S'); - }, - fillAndStroke: function(fillColor, strokeColor, rule) { - var isFillRule; - if (strokeColor == null) { - strokeColor = fillColor; - } - isFillRule = /(even-?odd)|(non-?zero)/; - if (isFillRule.test(fillColor)) { - rule = fillColor; - fillColor = null; - } - if (isFillRule.test(strokeColor)) { - rule = strokeColor; - strokeColor = fillColor; - } - if (fillColor) { - this.fillColor(fillColor); - this.strokeColor(strokeColor); - } - return this.addContent('B' + this._windingRule(rule)); - }, - clip: function(rule) { - return this.addContent('W' + this._windingRule(rule) + ' n'); - }, - transform: function(m11, m12, m21, m22, dx, dy) { - var m, m0, m1, m2, m3, m4, m5, v, values; - m = this._ctm; - m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], m4 = m[4], m5 = m[5]; - m[0] = m0 * m11 + m2 * m12; - m[1] = m1 * m11 + m3 * m12; - m[2] = m0 * m21 + m2 * m22; - m[3] = m1 * m21 + m3 * m22; - m[4] = m0 * dx + m2 * dy + m4; - m[5] = m1 * dx + m3 * dy + m5; - values = ((function() { - var i, len, ref, results; - ref = [m11, m12, m21, m22, dx, dy]; - results = []; - for (i = 0, len = ref.length; i < len; i++) { - v = ref[i]; - results.push(number(v)); - } - return results; - })()).join(' '); - return this.addContent(values + " cm"); - }, - translate: function(x, y) { - return this.transform(1, 0, 0, 1, x, y); - }, - rotate: function(angle, options) { - var cos, rad, ref, sin, x, x1, y, y1; - if (options == null) { - options = {}; - } - rad = angle * Math.PI / 180; - cos = Math.cos(rad); - sin = Math.sin(rad); - x = y = 0; - if (options.origin != null) { - ref = options.origin, x = ref[0], y = ref[1]; - x1 = x * cos - y * sin; - y1 = x * sin + y * cos; - x -= x1; - y -= y1; - } - return this.transform(cos, sin, -sin, cos, x, y); - }, - scale: function(xFactor, yFactor, options) { - var ref, x, y; - if (yFactor == null) { - yFactor = xFactor; - } - if (options == null) { - options = {}; - } - if (arguments.length === 2) { - yFactor = xFactor; - options = yFactor; - } - x = y = 0; - if (options.origin != null) { - ref = options.origin, x = ref[0], y = ref[1]; - x -= xFactor * x; - y -= yFactor * y; - } - return this.transform(xFactor, 0, 0, yFactor, x, y); - } - }; - -}).call(this); diff --git a/pitfall/pitfall/annotations.rkt b/pitfall/pitfall/annotations.rkt index 47963286..87013585 100644 --- a/pitfall/pitfall/annotations.rkt +++ b/pitfall/pitfall/annotations.rkt @@ -50,10 +50,8 @@ [y1 (+ y1 h)] [x2 (+ x1 w)]) (match-define (list m0 m1 m2 m3 m4 m5) (· this _ctm)) - ;; original code mutates x1 and y1 during transformation - ;; I think this is wrong - (let* ([x1a (+ (* x1 m0) (* y1 m2) m4)] - [y1a (+ (* x1 m1) (* y1 m3) m5)] - [x2a (+ (* x2 m0) (* y2 m2) m4)] - [y2a (+ (* x2 m1) (* y2 m3) m5)]) - (list x1a y1a x2a y2a)))) \ No newline at end of file + (let* ([x1 (+ (* x1 m0) (* y1 m2) m4)] + [y1 (+ (* x1 m1) (* y1 m3) m5)] + [x2 (+ (* x2 m0) (* y2 m2) m4)] + [y2 (+ (* x2 m1) (* y2 m3) m5)]) + (list x1 y1 x2 y2)))) \ No newline at end of file diff --git a/pitfall/pitfall/test/test11.coffee b/pitfall/pitfall/test/test11.coffee index 8116f820..067d5f3e 100644 --- a/pitfall/pitfall/test/test11.coffee +++ b/pitfall/pitfall/test/test11.coffee @@ -4,11 +4,16 @@ fs = require 'fs' make = (doc) -> # Add some text with annotations doc.fillColor("blue") + .translate(50,50) .font('Helvetica', 30) .text('Here is a link!', 100, 100, { link: 'http://google.com/', underline: true, width: false}) doc.end() +doc = new PDFDocument({compress: no}) +doc.pipe(fs.createWriteStream('test11.pdf')) +make doc + doc = new PDFDocument({compress: yes}) doc.pipe(fs.createWriteStream('test11c.pdf')) make doc \ No newline at end of file diff --git a/pitfall/pitfall/test/test11.pdf b/pitfall/pitfall/test/test11.pdf new file mode 100644 index 00000000..b8f6a40d --- /dev/null +++ b/pitfall/pitfall/test/test11.pdf @@ -0,0 +1,132 @@ +%PDF-1.3 +% +6 0 obj +<< +/Type /ExtGState +/ca 1 +>> +endobj +7 0 obj +<< +/S /URI +/URI (http://google.com/) +>> +endobj +8 0 obj +<< +/Subtype /Link +/A 7 0 R +/Type /Annot +/Rect [150 614.25 331.71 642] +/Border [0 0 0] +>> +endobj +9 0 obj +<< +/Type /ExtGState +/CA 1 +>> +endobj +5 0 obj +<< +/Type /Page +/Parent 1 0 R +/MediaBox [0 0 612 792] +/Contents 3 0 R +/Resources 4 0 R +/Annots [8 0 R] +>> +endobj +4 0 obj +<< +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +/ExtGState << +/Gs1 6 0 R +/Gs2 9 0 R +>> +/Font << +/F1 10 0 R +>> +>> +endobj +3 0 obj +<< +/Length 238 +>> +stream +1 0 0 -1 0 792 cm +/DeviceRGB cs +0 0 1 scn +/Gs1 gs +1 0 0 1 50 50 cm +q +/DeviceRGB CS +0 0 1 SCN +/Gs2 gs +3 w +100 124.75 m +281.71 124.75 l +S +Q +q +1 0 0 -1 0 792 cm +BT +1 0 0 1 100 670.46 Tm +/F1 30 Tf +[<486572652069732061206c696e6b21> 0] TJ +ET +Q + +endstream +endobj +11 0 obj +<< +/Producer (PDFKit) +/Creator (PDFKit) +/CreationDate (D:20170824194220Z) +>> +endobj +10 0 obj +<< +/Type /Font +/BaseFont /Helvetica +/Subtype /Type1 +/Encoding /WinAnsiEncoding +>> +endobj +2 0 obj +<< +/Type /Catalog +/Pages 1 0 R +>> +endobj +1 0 obj +<< +/Type /Pages +/Count 1 +/Kids [5 0 R] +>> +endobj +xref +0 12 +0000000000 65535 f +0000001040 00000 n +0000000991 00000 n +0000000511 00000 n +0000000382 00000 n +0000000262 00000 n +0000000015 00000 n +0000000059 00000 n +0000000114 00000 n +0000000218 00000 n +0000000893 00000 n +0000000800 00000 n +trailer +<< +/Size 12 +/Root 2 0 R +/Info 11 0 R +>> +startxref +1097 +%%EOF diff --git a/pitfall/pitfall/test/test11.rkt b/pitfall/pitfall/test/test11.rkt index f26267fc..9f8f0b4e 100644 --- a/pitfall/pitfall/test/test11.rkt +++ b/pitfall/pitfall/test/test11.rkt @@ -4,6 +4,7 @@ (send* doc [fillColor "blue"] [font "Helvetica" 30] + [translate 50 50] [text "Here is a link!" 100 100 (hash 'link "http://google.com/" 'underline #t diff --git a/pitfall/pitfall/test/test11c.pdf b/pitfall/pitfall/test/test11c.pdf index 65107fb7..de5c92c1 100644 --- a/pitfall/pitfall/test/test11c.pdf +++ b/pitfall/pitfall/test/test11c.pdf @@ -17,7 +17,7 @@ endobj /Subtype /Link /A 7 0 R /Type /Annot -/Rect [100 664.25 281.71 692] +/Rect [150 614.25 331.71 642] /Border [0 0 0] >> endobj @@ -53,7 +53,7 @@ endobj << /Producer (PDFKit) /Creator (PDFKit) -/CreationDate (D:20170529031624Z) +/CreationDate (D:20170824194220Z) >> endobj 10 0 obj @@ -79,12 +79,12 @@ endobj endobj 3 0 obj << -/Length 161 +/Length 167 /Filter /FlateDecode >> stream -xe -0 y[aS]oee)AB~H%ƂT|Gc[cL0M S|@&k/t35( d6G2O Yan*Mf%, Y|JQ*gZ9c&'0P +xe +@ Em2dZZp!hg'nV}3@< 72Ƅ`!s]!B2p/RJnHۿ]'$0jYT9agK/RЫ%cA菰XgY+H- ϐW 3v endstream endobj xref @@ -108,5 +108,5 @@ trailer /Info 11 0 R >> startxref -1041 +1047 %%EOF diff --git a/pitfall/pitfall/test/test11crkt copy.pdf b/pitfall/pitfall/test/test11crkt copy.pdf index a26229c2..36edf7a2 100644 --- a/pitfall/pitfall/test/test11crkt copy.pdf +++ b/pitfall/pitfall/test/test11crkt copy.pdf @@ -17,7 +17,7 @@ endobj /A 7 0 R /Border [0 0 0] /Subtype /Link -/Rect [100 664.25 281.71 692] +/Rect [150 614.25 331.71 642] /Type /Annot >> endobj @@ -51,12 +51,12 @@ endobj endobj 3 0 obj << -/Length 161 +/Length 167 /Filter /FlateDecode >> stream -xe -0 y[aS]oee)AB~H%ƂT|Gc[cL0M S|@&k/t35( d6G2O Yan*Mf%, Y|JQ*gZ9c&'0P +xe +@ Em2dZZp!hg'nV}3@< 72Ƅ`!s]!B2p/RJnHۿ]'$0jYT9agK/RЫ%cA菰XgY+H- ϐW 3v endstream endobj 11 0 obj @@ -90,8 +90,8 @@ endobj xref 0 12 0000000000 65535 f -0000000984 00000 n -0000000935 00000 n +0000000990 00000 n +0000000941 00000 n 0000000511 00000 n 0000000382 00000 n 0000000262 00000 n @@ -99,8 +99,8 @@ xref 0000000059 00000 n 0000000114 00000 n 0000000218 00000 n -0000000837 00000 n -0000000744 00000 n +0000000843 00000 n +0000000750 00000 n trailer << /Info 11 0 R @@ -108,5 +108,5 @@ trailer /Size 12 >> startxref -1041 +1047 %%EOF diff --git a/pitfall/pitfall/test/test11crkt.pdf b/pitfall/pitfall/test/test11crkt.pdf index a26229c2..36edf7a2 100644 --- a/pitfall/pitfall/test/test11crkt.pdf +++ b/pitfall/pitfall/test/test11crkt.pdf @@ -17,7 +17,7 @@ endobj /A 7 0 R /Border [0 0 0] /Subtype /Link -/Rect [100 664.25 281.71 692] +/Rect [150 614.25 331.71 642] /Type /Annot >> endobj @@ -51,12 +51,12 @@ endobj endobj 3 0 obj << -/Length 161 +/Length 167 /Filter /FlateDecode >> stream -xe -0 y[aS]oee)AB~H%ƂT|Gc[cL0M S|@&k/t35( d6G2O Yan*Mf%, Y|JQ*gZ9c&'0P +xe +@ Em2dZZp!hg'nV}3@< 72Ƅ`!s]!B2p/RJnHۿ]'$0jYT9agK/RЫ%cA菰XgY+H- ϐW 3v endstream endobj 11 0 obj @@ -90,8 +90,8 @@ endobj xref 0 12 0000000000 65535 f -0000000984 00000 n -0000000935 00000 n +0000000990 00000 n +0000000941 00000 n 0000000511 00000 n 0000000382 00000 n 0000000262 00000 n @@ -99,8 +99,8 @@ xref 0000000059 00000 n 0000000114 00000 n 0000000218 00000 n -0000000837 00000 n -0000000744 00000 n +0000000843 00000 n +0000000750 00000 n trailer << /Info 11 0 R @@ -108,5 +108,5 @@ trailer /Size 12 >> startxref -1041 +1047 %%EOF diff --git a/pitfall/pitfall/test/test11rkt copy.pdf b/pitfall/pitfall/test/test11rkt copy.pdf index a34b1f05..5a604346 100644 --- a/pitfall/pitfall/test/test11rkt copy.pdf +++ b/pitfall/pitfall/test/test11rkt copy.pdf @@ -17,7 +17,7 @@ endobj /A 7 0 R /Border [0 0 0] /Subtype /Link -/Rect [100 664.25 281.71 692] +/Rect [150 614.25 331.71 642] /Type /Annot >> endobj @@ -51,13 +51,14 @@ endobj endobj 3 0 obj << -/Length 221 +/Length 238 >> stream 1 0 0 -1 0 792 cm /DeviceRGB cs 0 0 1 scn /Gs1 gs +1 0 0 1 50 50 cm q /DeviceRGB CS 0 0 1 SCN @@ -109,8 +110,8 @@ endobj xref 0 12 0000000000 65535 f -0000001023 00000 n -0000000974 00000 n +0000001040 00000 n +0000000991 00000 n 0000000511 00000 n 0000000382 00000 n 0000000262 00000 n @@ -118,8 +119,8 @@ xref 0000000059 00000 n 0000000114 00000 n 0000000218 00000 n -0000000876 00000 n -0000000783 00000 n +0000000893 00000 n +0000000800 00000 n trailer << /Info 11 0 R @@ -127,5 +128,5 @@ trailer /Size 12 >> startxref -1080 +1097 %%EOF diff --git a/pitfall/pitfall/test/test11rkt.pdf b/pitfall/pitfall/test/test11rkt.pdf index a34b1f05..5a604346 100644 --- a/pitfall/pitfall/test/test11rkt.pdf +++ b/pitfall/pitfall/test/test11rkt.pdf @@ -17,7 +17,7 @@ endobj /A 7 0 R /Border [0 0 0] /Subtype /Link -/Rect [100 664.25 281.71 692] +/Rect [150 614.25 331.71 642] /Type /Annot >> endobj @@ -51,13 +51,14 @@ endobj endobj 3 0 obj << -/Length 221 +/Length 238 >> stream 1 0 0 -1 0 792 cm /DeviceRGB cs 0 0 1 scn /Gs1 gs +1 0 0 1 50 50 cm q /DeviceRGB CS 0 0 1 SCN @@ -109,8 +110,8 @@ endobj xref 0 12 0000000000 65535 f -0000001023 00000 n -0000000974 00000 n +0000001040 00000 n +0000000991 00000 n 0000000511 00000 n 0000000382 00000 n 0000000262 00000 n @@ -118,8 +119,8 @@ xref 0000000059 00000 n 0000000114 00000 n 0000000218 00000 n -0000000876 00000 n -0000000783 00000 n +0000000893 00000 n +0000000800 00000 n trailer << /Info 11 0 R @@ -127,5 +128,5 @@ trailer /Size 12 >> startxref -1080 +1097 %%EOF diff --git a/pitfall/pitfall/vector.rkt b/pitfall/pitfall/vector.rkt index c418d750..62aba42c 100644 --- a/pitfall/pitfall/vector.rkt +++ b/pitfall/pitfall/vector.rkt @@ -160,7 +160,7 @@ [(pair? points) (apply moveTo this (car points)) (for ([pt (in-list (cdr points))]) - (apply lineTo this pt)) + (apply lineTo this pt)) (closePath this)] [else this])) @@ -200,16 +200,16 @@ (format "~a cm" (string-join (map number ctm) " "))) -(define/contract (combine-transforms m-transform n-transform) +(define/contract (combine-transforms m new-ctm) (tm/c tm/c . -> . tm/c) - (match-define (list m11 m12 m21 m22 mdx mdy) m-transform) - (match-define (list n11 n12 n21 n22 ndx ndy) n-transform) - (list (+ (* n11 m11) (* n21 m12)) - (+ (* n12 m11) (* n22 m12)) - (+ (* n11 m21) (* n21 m22)) - (+ (* n12 m21) (* n22 m22)) - (+ (* n11 mdx) (* n21 mdy) ndx) - (+ (* n12 mdx) (* n22 mdy) ndy))) + (match-define (list m0 m1 m2 m3 m4 m5) m) + (match-define (list m11 m12 m21 m22 dx dy) new-ctm) + (list (+ (* m0 m11) (* m2 m12)) + (+ (* m1 m11) (* m3 m12)) + (+ (* m0 m21) (* m2 m22)) + (+ (* m1 m21) (* m3 m22)) + (+ (* m0 dx) (* m2 dy) m4) + (+ (* m1 dx) (* m3 dy) m5))) (define/contract (clip this [rule #f]) @@ -261,4 +261,11 @@ (set! ctm (combine-transforms ctm ctm2)) (check-equal? ctm '(7 10 15 22 28 40)) (set! ctm (combine-transforms ctm ctm2)) - (check-equal? ctm '(37 54 81 118 153 222))) \ No newline at end of file + (check-equal? ctm '(37 54 81 118 153 222)) + + (check-equal? (combine-transforms '(1 0 0 -1 0 792.0) '(1 0 0 1 50 50)) + '(1 0 0 -1 50 742.0)) + + (check-equal? (combine-transforms '(1 0 0 -1 50 742.0) '(1 0 0 -1 0 792)) + '(1 0 0 1 50 -50.0)) + ) \ No newline at end of file