From ad60d7e0a361c58fc9872753cfb872c3cc54b82f Mon Sep 17 00:00:00 2001 From: Matthias Kramm Date: Fri, 21 Aug 2009 21:15:37 +0200 Subject: [PATCH] added test+fix for transparency group stacking --- lib/devices/ops.c | 2 +- lib/pdf/GFXOutputDev.cc | 13 ++++--- lib/pdf/xpdf-changes.patch | 18 +++++++++ spec/transpstack.pdf | 90 ++++++++++++++++++++++++++++++++++++++++++++ spec/transpstack.py | 58 ++++++++++++++++++++++++++++ spec/transpstack.spec.rb | 13 +++++++ 6 files changed, 188 insertions(+), 6 deletions(-) create mode 100644 spec/transpstack.pdf create mode 100644 spec/transpstack.py create mode 100644 spec/transpstack.spec.rb diff --git a/lib/devices/ops.c b/lib/devices/ops.c index 7b5f1c7..bda4742 100644 --- a/lib/devices/ops.c +++ b/lib/devices/ops.c @@ -66,7 +66,7 @@ inline gfxcolor_t transform_color(internal_t*i, gfxcolor_t*col) col2.r = col->r; col2.g = col->g; col2.b = col->b; - col2.a = (col->a * i->alpha)>>8; + col2.a = (col->a * i->alpha)/255; return col2; } diff --git a/lib/pdf/GFXOutputDev.cc b/lib/pdf/GFXOutputDev.cc index 2c90c92..2f4a2cf 100644 --- a/lib/pdf/GFXOutputDev.cc +++ b/lib/pdf/GFXOutputDev.cc @@ -1877,6 +1877,13 @@ void GFXOutputDev::restoreState(GfxState *state) { } if(states[statepos].state!=state) { msg(" bad state nesting"); + if(verbose) { + int t; + for(t=0;t<=statepos;t++) { + printf("%08x ", states[t].state); + } + printf("\n"); + } exit(1); } states[statepos].state=0; @@ -2654,11 +2661,7 @@ void GFXOutputDev::endTransparencyGroup(GfxState *state) this->device = states[statepos].olddevice; if(!this->device) { - msg(" Bad state nesting in transparency group"); - msg(" Notice: this is a known problem, which will be fixed in 0.9.1"); - msg(" In the meantime, please convert the file with -s poly2bitmap"); - restoreState(state); - this->device = states[statepos].olddevice; + msg(" Invalid state nesting"); } states[statepos].olddevice = 0; diff --git a/lib/pdf/xpdf-changes.patch b/lib/pdf/xpdf-changes.patch index 83adec3..234952d 100644 --- a/lib/pdf/xpdf-changes.patch +++ b/lib/pdf/xpdf-changes.patch @@ -992,3 +992,21 @@ diff -u -r1.5 -r1.6 } dx *= state->getHorizScaling(); dy *= state->getFontSize(); +@@ -3824,6 +3833,7 @@ + out->beginTransparencyGroup(state, bbox, blendingColorSpace, + isolated, knockout, softMask); + } ++ GfxState*old_state = state; + + // set new base matrix + for (i = 0; i < 6; ++i) { +@@ -3835,6 +3845,9 @@ + display(str, gFalse); + + if (softMask || transpGroup) { ++ // restore graphics state ++ while(state != old_state) ++ restoreState(); + out->endTransparencyGroup(state); + } + diff --git a/spec/transpstack.pdf b/spec/transpstack.pdf new file mode 100644 index 0000000..f0682c6 --- /dev/null +++ b/spec/transpstack.pdf @@ -0,0 +1,90 @@ +%PDF-1.4 +%ê~ +1 0 obj << +/Type /Catalog +/Pages 4 0 R +>> endobj +2 0 obj << +/Contents 3 0 R +/Parent 4 0 R +/Type /Page +/Resources 7 0 R +/MediaBox [0 0 612 100] +>> endobj +3 0 obj << +/Length 107 +>> stream +q + +1.0 0.0 0.0 rg + +0 40 m 612 40 l 612 60 l 0 60 l 0 40 l f +q /gs0 gs 1.0 0 0 1.0 0 0 cm /mygroup Do Q + +Qendstream +endobj +4 0 obj << +/Kids [2 0 R] +/Type /Pages +/Count 1 +>> endobj +5 0 obj << +/Length 337 +/Type /XObject +/BBox [0 0 100 100] +/Group << +/K true +/CS /DeviceRGB +/S /Transparency +/I true +>> +/Subtype /Form +>> stream + +0.0 1.0 0.0 rg +0.0 0.0 0.0 RG +10 10 m 70 10 l 70 70 l 10 70 l 10 10 l f +10 10 m 70 10 l 70 70 l 10 70 l 10 10 l s +0.0 0.0 1.0 rg +0.0 0.0 0.0 RG +30 30 m 90 30 l 90 90 l 30 90 l 30 30 l f +30 30 m 90 30 l 90 90 l 30 90 l 30 30 l s +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +endstream +endobj +6 0 obj << +/CA 1.0 +/ca 1.0 +/Type /ExtGState +/BM /Normal +>> endobj +7 0 obj << +/XObject << +/mygroup 5 0 R +>> +/Type /Resources +/ExtGState << +/gs0 6 0 R +>> +>> endobj +xref +0 8 +0000000000 65535 f +0000000013 00000 n +0000000062 00000 n +0000000166 00000 n +0000000323 00000 n +0000000380 00000 n +0000000878 00000 n +0000000944 00000 n +trailer +<< +/Size 8 +/Root 1 0 R +>> +startxref +1040 +%%EOF \ No newline at end of file diff --git a/spec/transpstack.py b/spec/transpstack.py new file mode 100644 index 0000000..6bc151c --- /dev/null +++ b/spec/transpstack.py @@ -0,0 +1,58 @@ +#!/usr/bin/python +import sys +sys.path += ["../scripts/"] +import pdf + +# a test for transparency groups: +# form xobjects used for doing transparency groups can do savestate (q) +# without ever needing to do a corresponding restorestate (Q) because +# their content stream is self-contained. +# +# Test that this doesn't confuse the pdf reader. + +file = pdf.PDF() + +page = file.add_page(612,100) + +group1 = file.create_object("/XObject", "/Form") +group1.stream = """ +0.0 1.0 0.0 rg +0.0 0.0 0.0 RG +10 10 m 70 10 l 70 70 l 10 70 l 10 10 l f +10 10 m 70 10 l 70 70 l 10 70 l 10 10 l s +0.0 0.0 1.0 rg +0.0 0.0 0.0 RG +30 30 m 90 30 l 90 90 l 30 90 l 30 30 l f +30 30 m 90 30 l 90 90 l 30 90 l 30 30 l s +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +""" +isolated = "true" +knockout = "true" +group1["/Group"] = pdf.PDFDict({"/S": "/Transparency", "/CS": "/DeviceRGB", "/I": isolated, "/K": knockout}) +group1["/BBox"] = pdf.PDFArray([0, 0, 100, 100]) + +gs = file.create_object("/ExtGState") +gs["/BM"] = "/Normal" +gs["/CA"] = "1.0" # stroke alpha +gs["/ca"] = "1.0" # fill alpha + +resources = file.create_object("/Resources") +resources["/XObject"] = pdf.PDFDict({"/mygroup": group1}) +resources["/ExtGState"] = pdf.PDFDict({"/gs0": gs}) + +page.header["/Resources"] = resources + +page.stream = """q + +1.0 0.0 0.0 rg + +0 40 m 612 40 l 612 60 l 0 60 l 0 40 l f +q /gs0 gs 1.0 0 0 1.0 0 0 cm /mygroup Do Q + +Q""" + +file.write("transpstack.pdf") + diff --git a/spec/transpstack.spec.rb b/spec/transpstack.spec.rb new file mode 100644 index 0000000..8f6226f --- /dev/null +++ b/spec/transpstack.spec.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + convert_file "transpstack.pdf" do + pixel_at(15,15).should_be_of_color 0xffffff + pixel_at(4,50).should_be_of_color 0xff0000 + pixel_at(21,52).should_be_of_color 0x00ff00 + pixel_at(49,51).should_be_of_color 0x0000ff + pixel_at(80,49).should_be_of_color 0x0000ff + pixel_at(23,77).should_be_of_color 0x00ff00 + pixel_at(70,20).should_be_of_color 0x0000ff + end +end -- 1.7.10.4