]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Merged revisions 687576,687657,687786,688078,688087,688139,688508,688633,688652-68865...
authorAdrian Cumiskey <acumiskey@apache.org>
Tue, 26 Aug 2008 09:10:19 +0000 (09:10 +0000)
committerAdrian Cumiskey <acumiskey@apache.org>
Tue, 26 Aug 2008 09:10:19 +0000 (09:10 +0000)
https://svn.eu.apache.org/repos/asf/xmlgraphics/fop/trunk

........
  r687576 | maxberger | 2008-08-21 07:25:40 +0100 (Thu, 21 Aug 2008) | 1 line

  Included patched retroweaver which does not modify Boolean.valueOf
........
  r687657 | jeremias | 2008-08-21 09:51:50 +0100 (Thu, 21 Aug 2008) | 1 line

  Added an FAQ entry about the element mismatch error message.
........
  r687786 | jeremias | 2008-08-21 16:49:13 +0100 (Thu, 21 Aug 2008) | 1 line

  Added some performance statistics to MemoryEater.
........
  r688078 | jeremias | 2008-08-22 14:02:37 +0100 (Fri, 22 Aug 2008) | 1 line

  Final statistics output after the test with average speed indication.
........
  r688087 | jeremias | 2008-08-22 15:16:58 +0100 (Fri, 22 Aug 2008) | 2 lines

  Merge from branch https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_95:
  Fixed text stroking in SVG when the stroke-width is zero.
........
  r688139 | maxberger | 2008-08-22 19:08:36 +0100 (Fri, 22 Aug 2008) | 1 line

  minor spelling mistakes
........
  r688508 | maxberger | 2008-08-24 14:12:02 +0100 (Sun, 24 Aug 2008) | 2 lines

  Moved DataURIResolver from FOP to commons; use new URIResolver registry
........
  r688633 | jeremias | 2008-08-25 07:42:44 +0100 (Mon, 25 Aug 2008) | 2 lines

  Fixed memory leak in property cache (not cleaning stale PropertyCache$CacheEntry instances).
  Special thanks to Andreas Delmelle for his help!
........
  r688652 | maxberger | 2008-08-25 09:19:13 +0100 (Mon, 25 Aug 2008) | 1 line

  Re-added moved class as deprecated
........
  r688653 | jeremias | 2008-08-25 09:23:31 +0100 (Mon, 25 Aug 2008) | 1 line

  Added a page on metadata (partly ported from the FOP Wiki).
........
  r688660 | jeremias | 2008-08-25 09:41:29 +0100 (Mon, 25 Aug 2008) | 2 lines

  Fixed example.
  Thanks for noticing, Pascal Sancho!
........
  r688664 | jeremias | 2008-08-25 09:59:27 +0100 (Mon, 25 Aug 2008) | 1 line

  Minor documentation improvements, most notably a comment about keep-together="always".
........
  r688666 | maxberger | 2008-08-25 10:00:27 +0100 (Mon, 25 Aug 2008) | 1 line

  CommonURIResolver is no longer a singleton
........
  r688674 | jeremias | 2008-08-25 10:15:22 +0100 (Mon, 25 Aug 2008) | 1 line

  Hmm, I missed the redirects for the 0.95 release.
........
  r688698 | jeremias | 2008-08-25 12:24:15 +0100 (Mon, 25 Aug 2008) | 2 lines

  Merge from 0.95 branch:
  Fixed jar-sources target.
........
  r688994 | acumiskey | 2008-08-26 09:34:45 +0100 (Tue, 26 Aug 2008) | 1 line

  Deprecate UnitConv now that it resides only in xmlgraphics commons.
........
  r689000 | acumiskey | 2008-08-26 09:59:31 +0100 (Tue, 26 Aug 2008) | 1 line

  Forgot to add deprecated public statics.
........

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@689005 13f79535-47bb-0310-9956-ffa450edef68

26 files changed:
build.xml
lib/build/retroweaver-2.0.5.jar [deleted file]
lib/build/retroweaver-2.0.6-patched.jar [new file with mode: 0644]
lib/build/retroweaver-rt-2.0.5.jar [deleted file]
lib/build/retroweaver-rt-2.0.6-patched.jar [new file with mode: 0644]
lib/xmlgraphics-commons-1.4svn.jar
src/documentation/content/.htaccess
src/documentation/content/xdocs/0.95/metadata.xml [new file with mode: 0644]
src/documentation/content/xdocs/0.95/pdfa.xml
src/documentation/content/xdocs/faq.xml
src/documentation/content/xdocs/site.xml
src/documentation/content/xdocs/trunk/metadata.xml [new file with mode: 0644]
src/documentation/content/xdocs/trunk/pdfa.xml
src/java/org/apache/fop/apps/FOURIResolver.java
src/java/org/apache/fop/fo/properties/PropertyCache.java
src/java/org/apache/fop/svg/PDFGraphics2D.java
src/java/org/apache/fop/svg/PDFTextPainter.java
src/java/org/apache/fop/util/DataURIResolver.java
src/java/org/apache/fop/util/DataURLUtil.java
src/java/org/apache/fop/util/UnitConv.java [new file with mode: 0644]
src/java/org/apache/fop/util/WriterOutputStream.java
status.xml
test/java/org/apache/fop/UtilityCodeTestSuite.java
test/java/org/apache/fop/memory/MemoryEater.java
test/java/org/apache/fop/memory/Stats.java [new file with mode: 0644]
test/java/org/apache/fop/util/DataURIResolverTestCase.java [deleted file]

index 46135624243d316201af1e6f15febd8a9ba62e9c..32b27c82b97063d2fbafec97d52fd4ab002803e7 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -474,7 +474,6 @@ list of possible build targets.
       <pathelement location="${java14.jce.lib}"/>
       <pathelement location="${ant.home}/lib/ant.jar"/>
       <path refid="libs-build-classpath"/>
-      <path refid="libs-build-tools-classpath"/>
     </path>
     <!-- If we decide to use retroweaver for the actual weaving, the mkdir and
          destdir= will have to be removed. Also, the weaving task would additionally
@@ -555,9 +554,6 @@ list of possible build targets.
       <fileset dir="${src.java.dir}">
         <patternset refid="java-only"/>
       </fileset>
-      <fileset dir="${src.java.version.dir}">
-        <patternset refid="java-only"/>
-      </fileset>
       <fileset dir="${basedir}">
         <include name="LICENSE"/>
         <include name="NOTICE"/>
diff --git a/lib/build/retroweaver-2.0.5.jar b/lib/build/retroweaver-2.0.5.jar
deleted file mode 100644 (file)
index 69d4880..0000000
Binary files a/lib/build/retroweaver-2.0.5.jar and /dev/null differ
diff --git a/lib/build/retroweaver-2.0.6-patched.jar b/lib/build/retroweaver-2.0.6-patched.jar
new file mode 100644 (file)
index 0000000..94b3b73
Binary files /dev/null and b/lib/build/retroweaver-2.0.6-patched.jar differ
diff --git a/lib/build/retroweaver-rt-2.0.5.jar b/lib/build/retroweaver-rt-2.0.5.jar
deleted file mode 100644 (file)
index 3edaa91..0000000
Binary files a/lib/build/retroweaver-rt-2.0.5.jar and /dev/null differ
diff --git a/lib/build/retroweaver-rt-2.0.6-patched.jar b/lib/build/retroweaver-rt-2.0.6-patched.jar
new file mode 100644 (file)
index 0000000..e6b8483
Binary files /dev/null and b/lib/build/retroweaver-rt-2.0.6-patched.jar differ
index 4317a42a66e367718fce6fc1e00e2992560cf4fd..6d8181de890296759488e9d3ba8e28652f749eb5 100644 (file)
Binary files a/lib/xmlgraphics-commons-1.4svn.jar and b/lib/xmlgraphics-commons-1.4svn.jar differ
index 561900fdee7fa6669da4fb0efa5c524efd42bbc7..5203ea63ee2b05914564f52a93bf0071695759f9 100644 (file)
@@ -1,28 +1,38 @@
 # redirect moved files
-RedirectMatch Permanent ^/fop/anttask(.*) http://xmlgraphics.apache.org/fop/0.94/anttask$1
-RedirectMatch Permanent ^/fop/compiling(.*) http://xmlgraphics.apache.org/fop/0.94/compiling$1
-RedirectMatch Permanent ^/fop/configuration(.*) http://xmlgraphics.apache.org/fop/0.94/configuration$1
-RedirectMatch Permanent ^/fop/embedding(.*) http://xmlgraphics.apache.org/fop/0.94/embedding$1
-RedirectMatch Permanent ^/fop/extensions(.*) http://xmlgraphics.apache.org/fop/0.94/extensions$1
-RedirectMatch Permanent ^/fop/fonts(.*) http://xmlgraphics.apache.org/fop/0.94/fonts$1
-RedirectMatch Permanent ^/fop/graphics(.*) http://xmlgraphics.apache.org/fop/0.94/graphics$1
-RedirectMatch Permanent ^/fop/hyphenation(.*) http://xmlgraphics.apache.org/fop/0.94/hyphenation$1
-RedirectMatch Permanent ^/fop/intermediate(.*) http://xmlgraphics.apache.org/fop/0.94/intermediate$1
-RedirectMatch Permanent ^/fop/output(.*) http://xmlgraphics.apache.org/fop/0.94/output$1
-RedirectMatch Permanent ^/fop/pdfa(.*) http://xmlgraphics.apache.org/fop/0.94/pdfa$1
-RedirectMatch Permanent ^/fop/pdfencryption(.*) http://xmlgraphics.apache.org/fop/0.94/pdfencryption$1
-RedirectMatch Permanent ^/fop/pdfx(.*) http://xmlgraphics.apache.org/fop/0.94/pdfx$1
-RedirectMatch Permanent ^/fop/running(.*) http://xmlgraphics.apache.org/fop/0.94/running$1
-RedirectMatch Permanent ^/fop/servlets(.*) http://xmlgraphics.apache.org/fop/0.94/servlets$1
-RedirectMatch Permanent ^/fop/upgrading(.*) http://xmlgraphics.apache.org/fop/0.94/upgrading$1
+RedirectMatch Permanent ^/fop/anttask(.*) http://xmlgraphics.apache.org/fop/0.95/anttask$1
+RedirectMatch Permanent ^/fop/compiling(.*) http://xmlgraphics.apache.org/fop/0.95/compiling$1
+RedirectMatch Permanent ^/fop/configuration(.*) http://xmlgraphics.apache.org/fop/0.95/configuration$1
+RedirectMatch Permanent ^/fop/embedding(.*) http://xmlgraphics.apache.org/fop/0.95/embedding$1
+RedirectMatch Permanent ^/fop/extensions(.*) http://xmlgraphics.apache.org/fop/0.95/extensions$1
+RedirectMatch Permanent ^/fop/fonts(.*) http://xmlgraphics.apache.org/fop/0.95/fonts$1
+RedirectMatch Permanent ^/fop/graphics(.*) http://xmlgraphics.apache.org/fop/0.95/graphics$1
+RedirectMatch Permanent ^/fop/hyphenation(.*) http://xmlgraphics.apache.org/fop/0.95/hyphenation$1
+RedirectMatch Permanent ^/fop/intermediate(.*) http://xmlgraphics.apache.org/fop/0.95/intermediate$1
+RedirectMatch Permanent ^/fop/output(.*) http://xmlgraphics.apache.org/fop/0.95/output$1
+RedirectMatch Permanent ^/fop/pdfa(.*) http://xmlgraphics.apache.org/fop/0.95/pdfa$1
+RedirectMatch Permanent ^/fop/pdfencryption(.*) http://xmlgraphics.apache.org/fop/0.95/pdfencryption$1
+RedirectMatch Permanent ^/fop/pdfx(.*) http://xmlgraphics.apache.org/fop/0.95/pdfx$1
+RedirectMatch Permanent ^/fop/running(.*) http://xmlgraphics.apache.org/fop/0.95/running$1
+RedirectMatch Permanent ^/fop/servlets(.*) http://xmlgraphics.apache.org/fop/0.95/servlets$1
+RedirectMatch Permanent ^/fop/upgrading(.*) http://xmlgraphics.apache.org/fop/0.95/upgrading$1
 
 # redirect to versioned documentation
-Redirect Temp /fop/stable http://xmlgraphics.apache.org/fop/0.94
+# Current stable release
+Redirect Temp /fop/stable http://xmlgraphics.apache.org/fop/0.95
+
+# Current unstable release (or trunk if no beta is the latest release)
+Redirect Temp /fop/unstable http://xmlgraphics.apache.org/fop/trunk
+
+# Latest release
 Redirect Temp /fop/current http://xmlgraphics.apache.org/fop/0.95
-Redirect Temp /fop/unstable http://xmlgraphics.apache.org/fop/0.95
-Redirect Temp /fop/latest http://xmlgraphics.apache.org/fop/trunk
-Redirect Temp /fop/maintenance http://xmlgraphics.apache.org/fop/0.93
-Redirect Temp /fop/previous http://xmlgraphics.apache.org/fop/0.93
-Redirect Temp /fop/0.90alpha1 http://xmlgraphics.apache.org/fop/0.93
-Redirect Temp /fop/0.91beta http://xmlgraphics.apache.org/fop/0.93
-Redirect Temp /fop/0.92beta http://xmlgraphics.apache.org/fop/0.93
+Redirect Temp /fop/latest http://xmlgraphics.apache.org/fop/0.95
+
+# Previous stable release
+Redirect Temp /fop/previous http://xmlgraphics.apache.org/fop/0.94
+
+# Old releases
+Redirect Temp /fop/maintenance http://xmlgraphics.apache.org/fop/0.94
+Redirect Temp /fop/0.90alpha1 http://xmlgraphics.apache.org/fop/0.94
+Redirect Temp /fop/0.91beta http://xmlgraphics.apache.org/fop/0.94
+Redirect Temp /fop/0.92beta http://xmlgraphics.apache.org/fop/0.94
+Redirect Temp /fop/0.93 http://xmlgraphics.apache.org/fop/0.94
diff --git a/src/documentation/content/xdocs/0.95/metadata.xml b/src/documentation/content/xdocs/0.95/metadata.xml
new file mode 100644 (file)
index 0000000..8c273ff
--- /dev/null
@@ -0,0 +1,243 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "document-v20.dtd">
+<document>
+  <header>
+    <title>Metadata</title>
+  </header>
+  <body>
+    <section id="overview">
+      <title>Overview</title>
+      <p>
+        Document metadata is an important tool for categorizing and finding documents.
+        Various formats support different kinds of metadata representation and to
+        different levels. One of the more popular and flexible means of representing
+        document or object metadata is
+        <a href="http://www.adobe.com/products/xmp/">XMP (eXtensible Metadata Platform, specified by Adobe)</a>.
+        PDF 1.4 introduced the use of XMP. The XMP specification lists recommendation for
+        embedding XMP metdata in other document and image formats. Given its flexibility it makes
+        sense to make use this approach in the XSL-FO context. Unfortunately, unlike SVG which
+        also refers to XMP, XSL-FO doesn't recommend a preferred way of specifying document and
+        object metadata. Therefore, there's no portable way to represent metadata in XSL-FO
+        documents. Each implementation does it differently.
+      </p>
+    </section>
+    <section id="xmp-in-fo">
+      <title>Embedding XMP in an XSL-FO document</title>
+      <p>
+        As noted above, there's no officially recommended way to embed metadata in XSL-FO.
+        Apache FOP supports embedding XMP in XSL-FO. Currently, only support for document-level
+        metadata is implemented. Object-level metadata will be implemented when there's
+        interest.
+      </p>
+      <p>
+        Document-level metadata can be specified in the <code>fo:declarations</code> element.
+        XMP specification recommends to use <code>x:xmpmeta</code>, <code>rdf:RDF</code>, and
+        <code>rdf:Description</code> elements as shown in example below. Both
+        <code>x:xmpmeta</code> and <code>rdf:RDF</code> elements are recognized as the top-level
+        element introducing an XMP fragment (as per the XMP specification).
+      </p>
+      <section id="xmp-example">
+        <title>Example</title>
+        <source><![CDATA[[..]
+</fo:layout-master-set>
+<fo:declarations>
+  <x:xmpmeta xmlns:x="adobe:ns:meta/">
+    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+      <rdf:Description rdf:about=""
+          xmlns:dc="http://purl.org/dc/elements/1.1/">
+        <!-- Dublin Core properties go here -->
+        <dc:title>Document title</dc:title>
+        <dc:creator>Document author</dc:creator>
+        <dc:description>Document subject</dc:description>
+      </rdf:Description>
+      <rdf:Description rdf:about=""
+          xmlns:xmp="http://ns.adobe.com/xap/1.0/">
+        <!-- XMP properties go here -->
+        <xmp:CreatorTool>Tool used to make the PDF</xmp:CreatorTool>
+      </rdf:Description>
+    </rdf:RDF>
+  </x:xmpmeta>
+</fo:declarations>
+<fo:page-sequence ...
+[..]]]></source>
+        <note>
+          <code>fo:declarations</code> <strong>must</strong> be declared after
+          <code>fo:layout-master-set</code> and before the first <code>page-sequence</code>.
+        </note>
+      </section>
+    </section>
+    <section id="xmp-impl-in-fop">
+      <title>Implementation in Apache FOP</title>
+      <p>
+        Currently, XMP support is only available for PDF output.
+      </p>
+      <p>
+        Originally, you could set some metadata information through FOP's FOUserAgent by
+        using its set*() methods (like setTitle(String) or setAuthor(String). These values are
+        directly used to set value in the PDF Info object. Since PDF 1.4, adding metadata as an
+        XMP document to a PDF is possible. That means that there are now two mechanisms in PDF
+        that hold metadata.
+      </p>
+      <p>
+        Apache FOP now synchronizes the Info and the Metadata object in PDF, i.e. when you
+        set the title and the author through the FOUserAgent, the two values will end up in
+        the (old) Info object and in the new Metadata object as XMP content. If instead of
+        FOUserAgent, you embed XMP metadata in the XSL-FO document (as shown above), the
+        XMP metadata will be used as-is in the PDF Metadata object and some values from the
+        XMP metadata will be copied to the Info object to maintain backwards-compatibility
+        for PDF readers that don't support XMP metadata.
+      </p>
+      <p>
+        The mapping between the Info and the Metadata object used by Apache FOP comes from
+        the <a href="http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=38920">PDF/A-1 specification</a>.
+        For convenience, here's the mapping table:
+      </p>
+      <table>
+        <tr>
+          <th colspan="2">Document information dictionary</th>
+          <th colspan="3">XMP</th>
+        </tr>
+        <tr>
+          <th>Entry</th>
+          <th>PDF type</th>
+          <th>Property</th>
+          <th>XMP type</th>
+          <th>Category</th>
+        </tr>
+        <tr>
+          <td>Title</td>
+          <td>text string</td>
+          <td>dc:title</td>
+          <td>Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Author</td>
+          <td>text string</td>
+          <td>dc:creator</td>
+          <td>seq Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Subject</td>
+          <td>text string</td>
+          <td>dc:description["x-default"]</td>
+          <td>Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Keywords</td>
+          <td>text string</td>
+          <td>pdf:Keywords</td>
+          <td>Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Creator</td>
+          <td>text string</td>
+          <td>xmp:CreatorTool</td>
+          <td>Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Producer</td>
+          <td>text string</td>
+          <td>pdf:Producer</td>
+          <td>Text</td>
+          <td>Internal</td>
+        </tr>
+        <tr>
+          <td>CreationDate</td>
+          <td>date</td>
+          <td>xmp:CreationDate</td>
+          <td>Date</td>
+          <td>Internal</td>
+        </tr>
+        <tr>
+          <td>ModDate</td>
+          <td>date</td>
+          <td>xmp:ModifyDate</td>
+          <td>Date</td>
+          <td>Internal</td>
+        </tr>
+      </table>
+      <note>
+        "Internal" in the Category column means that the user should not set this value.
+        It is set by the application. 
+      </note>
+      <note>
+        The "Subject" used to be mapped to <code>dc:subject</code> in the initial publication of
+        PDF/A-1 (ISO 19005-1). In the
+        <a href="http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=45613">Technical Corrigendum 1</a>
+        this was changed to map to <code>dc:description["x-default"]</code>. 
+      </note>
+      <section id="namespaces">
+        <title>Namespaces</title>
+        <p>
+          Metadata is made of property sets where each property set uses a different namespace URI.
+        </p>
+        <p>
+          The following is a listing of namespaces that Apache FOP recognizes and acts upon,
+          mostly to synchronize the XMP metadata with the PDF Info dictionary: 
+        </p>
+        <table>
+          <tr>
+            <th>Set/Schema</th>
+            <th>Namespace Prefix</th>
+            <th>Namespace URI</th>
+          </tr>
+          <tr>
+            <td>Dublin Core</td>
+            <td>dc</td>
+            <td>http://purl.org/dc/elements/1.1/</td>
+          </tr>
+          <tr>
+            <td>XMP Basic</td>
+            <td>xmp</td>
+            <td>http://ns.adobe.com/xap/1.0/</td>
+          </tr>
+          <tr>
+            <td>Adobe PDF Schema</td>
+            <td>pdf</td>
+            <td>http://ns.adobe.com/pdf/1.3/</td>
+          </tr>
+        </table>
+        <p>
+          Please refer to the <a href="http://partners.adobe.com/public/developer/en/xmp/sdk/XMPspecification.pdf">XMP Specification</a>
+          for information on other metadata namespaces.
+        </p>
+        <p>
+          Property sets (Namespaces) not listed here are simply passed through to the final
+          document (if supported). That is useful if you want to specify a custom metadata
+          schema.
+        </p>
+      </section>
+    </section>
+    <section id="links">
+      <title>Links</title>
+      <ul>
+        <li><a href="http://www.adobe.com/products/xmp/">Adobe's Extensible Metadata Platform (XMP) website</a></li>
+        <li><a href="http://partners.adobe.com/public/developer/en/xmp/sdk/XMPspecification.pdf">Adobe XMP Specification</a></li>
+        <li><a href="http://partners.adobe.com/public/developer/en/xmp/sdk/XMPspecification.pdf">Adobe XMP Specification</a></li>
+        <li><a href="http://dublincore.org/">http://dublincore.org/</a></li>
+      </ul>
+    </section>
+  </body>
+</document>
index 1b3b75561c397c94f7c805819443b90e83397673..bfa1ae33e3296a042ad6279d248f22f513365b74 100644 (file)
@@ -28,9 +28,6 @@
   <body>
     <section id="overview">
       <title>Overview</title>
-      <warning>
-        Support for PDF/A is available beginning with version 0.92.
-      </warning>
       <p>
         PDF/A is a standard which turns PDF into an "electronic document file 
         format for long-term preservation". PDF/A-1 is the first part of the 
index a75cd41e05cc77f86e5195122a2d68e3bacc77cf..ac2693d8b64abf8645158ee9bf57250a20263fe1 100644 (file)
         </p>
       </answer>
     </faq>
+    <faq id="saxexception-mismatch">
+      <question>I get a SAXException: Mismatch: page-sequence vs. root
+        (or similar).</question>
+      <answer>
+        <p>
+          The full exception usually looks similar to this:
+        </p>
+        <source>Mismatch: page-sequence (http://www.w3.org/1999/XSL/Format) vs. root
+        (http://www.w3.org/1999/XSL/Format)</source>
+        <p>
+          This exception is usually a follow-up error after another exception. Sometimes
+          the original exception gets swallowed by Xalan's default <code>ErrorListener</code>
+          (should be fixed in the latest Xalan release).
+        </p>
+        <p>
+          The work-around is to set an explicit <code>ErrorListener</code> on the
+          <code>Transformer</code>. The <code>ErrorListener</code> can be as simple as this:
+        </p>
+        <source><![CDATA[
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.TransformerException;
+
+public class DefaultErrorListener implements ErrorListener {
+    
+    public void warning(TransformerException exc) {
+        System.err.println(exc.toString());
+    }
+
+    public void error(TransformerException exc)
+            throws TransformerException {
+        throw exc;
+    }
+
+    public void fatalError(TransformerException exc)
+            throws TransformerException {
+        throw exc;
+    }
+
+}]]></source>
+      </answer>
+    </faq>
   </part>
   <part id="part-output">
     <title>Problems with FOP output</title>
@@ -551,8 +592,10 @@ Check the following:</p>
         text flows into adjacent cells/block, obscuring stuff there.</question>
       <answer>
         <p>
-          Clipping as specified by the <code>overflow="hidden"</code> is not yet
-          implemented.  If you have long words overflowing table cells, try to
+          Since the <code>overflow</code> property doesn't apply to table-cell, you
+          can wrap the cell content in a block-container and specify
+          <code>overflow="hidden"</code> there. Alternatively,
+          if you have long words overflowing table cells, try to
           get them hyphenated. Artificial names like product identifications or
           long numbers usually aren't hyphenated. You can try special processing
           at XSLT level, like
@@ -574,6 +617,15 @@ Check the following:</p>
           <link href="http://www.mulberrytech.com/xsl/xsl-list/">XSL list
           archive</link> for how to perform these tasks.
         </p>
+        <p>
+          If your text is not hyphenated at all and overflows the cell, please check
+          if you've specified <code>keep-together="always"</code> on the table-cell
+          or one of its parent elements. <code>keep-together="always"</code> implicitely
+          also sets <code>keep-together.within-line="always"</code> which forbids FOP
+          to break the text into multiple lines. This is important as FOP supports inline-level
+          keeps since version 0.94. It's a good idea not to use the shorthand
+          <code>keep-together="always"</code> at all!
+        </p>
       </answer>
     </faq>
     <faq id="row-height-constraint">
index 5ebdef32262ca660ae8246354997070cae1288f3..d87b68aabe5378aac34a3bef8f8b19d2478c2634 100644 (file)
       <fonts label="Fonts" href="fonts.html"/>
       <hyphenation label="Hyphenation" href="hyphenation.html"/>    
       <extensions label="Extensions" href="extensions.html"/>
+      <metadata label="Metadata" href="metadata.html"/>
     </features>
     
   </trunk>
       <hyphenation label="Hyphenation" href="hyphenation.html"/>    
       <extensions label="Extensions" href="extensions.html"/>
       <events label="Events" href="events.html"/>
+      <metadata label="Metadata" href="metadata.html"/>
     </features>
     
   </trunk>
diff --git a/src/documentation/content/xdocs/trunk/metadata.xml b/src/documentation/content/xdocs/trunk/metadata.xml
new file mode 100644 (file)
index 0000000..8c273ff
--- /dev/null
@@ -0,0 +1,243 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "document-v20.dtd">
+<document>
+  <header>
+    <title>Metadata</title>
+  </header>
+  <body>
+    <section id="overview">
+      <title>Overview</title>
+      <p>
+        Document metadata is an important tool for categorizing and finding documents.
+        Various formats support different kinds of metadata representation and to
+        different levels. One of the more popular and flexible means of representing
+        document or object metadata is
+        <a href="http://www.adobe.com/products/xmp/">XMP (eXtensible Metadata Platform, specified by Adobe)</a>.
+        PDF 1.4 introduced the use of XMP. The XMP specification lists recommendation for
+        embedding XMP metdata in other document and image formats. Given its flexibility it makes
+        sense to make use this approach in the XSL-FO context. Unfortunately, unlike SVG which
+        also refers to XMP, XSL-FO doesn't recommend a preferred way of specifying document and
+        object metadata. Therefore, there's no portable way to represent metadata in XSL-FO
+        documents. Each implementation does it differently.
+      </p>
+    </section>
+    <section id="xmp-in-fo">
+      <title>Embedding XMP in an XSL-FO document</title>
+      <p>
+        As noted above, there's no officially recommended way to embed metadata in XSL-FO.
+        Apache FOP supports embedding XMP in XSL-FO. Currently, only support for document-level
+        metadata is implemented. Object-level metadata will be implemented when there's
+        interest.
+      </p>
+      <p>
+        Document-level metadata can be specified in the <code>fo:declarations</code> element.
+        XMP specification recommends to use <code>x:xmpmeta</code>, <code>rdf:RDF</code>, and
+        <code>rdf:Description</code> elements as shown in example below. Both
+        <code>x:xmpmeta</code> and <code>rdf:RDF</code> elements are recognized as the top-level
+        element introducing an XMP fragment (as per the XMP specification).
+      </p>
+      <section id="xmp-example">
+        <title>Example</title>
+        <source><![CDATA[[..]
+</fo:layout-master-set>
+<fo:declarations>
+  <x:xmpmeta xmlns:x="adobe:ns:meta/">
+    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+      <rdf:Description rdf:about=""
+          xmlns:dc="http://purl.org/dc/elements/1.1/">
+        <!-- Dublin Core properties go here -->
+        <dc:title>Document title</dc:title>
+        <dc:creator>Document author</dc:creator>
+        <dc:description>Document subject</dc:description>
+      </rdf:Description>
+      <rdf:Description rdf:about=""
+          xmlns:xmp="http://ns.adobe.com/xap/1.0/">
+        <!-- XMP properties go here -->
+        <xmp:CreatorTool>Tool used to make the PDF</xmp:CreatorTool>
+      </rdf:Description>
+    </rdf:RDF>
+  </x:xmpmeta>
+</fo:declarations>
+<fo:page-sequence ...
+[..]]]></source>
+        <note>
+          <code>fo:declarations</code> <strong>must</strong> be declared after
+          <code>fo:layout-master-set</code> and before the first <code>page-sequence</code>.
+        </note>
+      </section>
+    </section>
+    <section id="xmp-impl-in-fop">
+      <title>Implementation in Apache FOP</title>
+      <p>
+        Currently, XMP support is only available for PDF output.
+      </p>
+      <p>
+        Originally, you could set some metadata information through FOP's FOUserAgent by
+        using its set*() methods (like setTitle(String) or setAuthor(String). These values are
+        directly used to set value in the PDF Info object. Since PDF 1.4, adding metadata as an
+        XMP document to a PDF is possible. That means that there are now two mechanisms in PDF
+        that hold metadata.
+      </p>
+      <p>
+        Apache FOP now synchronizes the Info and the Metadata object in PDF, i.e. when you
+        set the title and the author through the FOUserAgent, the two values will end up in
+        the (old) Info object and in the new Metadata object as XMP content. If instead of
+        FOUserAgent, you embed XMP metadata in the XSL-FO document (as shown above), the
+        XMP metadata will be used as-is in the PDF Metadata object and some values from the
+        XMP metadata will be copied to the Info object to maintain backwards-compatibility
+        for PDF readers that don't support XMP metadata.
+      </p>
+      <p>
+        The mapping between the Info and the Metadata object used by Apache FOP comes from
+        the <a href="http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=38920">PDF/A-1 specification</a>.
+        For convenience, here's the mapping table:
+      </p>
+      <table>
+        <tr>
+          <th colspan="2">Document information dictionary</th>
+          <th colspan="3">XMP</th>
+        </tr>
+        <tr>
+          <th>Entry</th>
+          <th>PDF type</th>
+          <th>Property</th>
+          <th>XMP type</th>
+          <th>Category</th>
+        </tr>
+        <tr>
+          <td>Title</td>
+          <td>text string</td>
+          <td>dc:title</td>
+          <td>Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Author</td>
+          <td>text string</td>
+          <td>dc:creator</td>
+          <td>seq Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Subject</td>
+          <td>text string</td>
+          <td>dc:description["x-default"]</td>
+          <td>Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Keywords</td>
+          <td>text string</td>
+          <td>pdf:Keywords</td>
+          <td>Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Creator</td>
+          <td>text string</td>
+          <td>xmp:CreatorTool</td>
+          <td>Text</td>
+          <td>External</td>
+        </tr>
+        <tr>
+          <td>Producer</td>
+          <td>text string</td>
+          <td>pdf:Producer</td>
+          <td>Text</td>
+          <td>Internal</td>
+        </tr>
+        <tr>
+          <td>CreationDate</td>
+          <td>date</td>
+          <td>xmp:CreationDate</td>
+          <td>Date</td>
+          <td>Internal</td>
+        </tr>
+        <tr>
+          <td>ModDate</td>
+          <td>date</td>
+          <td>xmp:ModifyDate</td>
+          <td>Date</td>
+          <td>Internal</td>
+        </tr>
+      </table>
+      <note>
+        "Internal" in the Category column means that the user should not set this value.
+        It is set by the application. 
+      </note>
+      <note>
+        The "Subject" used to be mapped to <code>dc:subject</code> in the initial publication of
+        PDF/A-1 (ISO 19005-1). In the
+        <a href="http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=45613">Technical Corrigendum 1</a>
+        this was changed to map to <code>dc:description["x-default"]</code>. 
+      </note>
+      <section id="namespaces">
+        <title>Namespaces</title>
+        <p>
+          Metadata is made of property sets where each property set uses a different namespace URI.
+        </p>
+        <p>
+          The following is a listing of namespaces that Apache FOP recognizes and acts upon,
+          mostly to synchronize the XMP metadata with the PDF Info dictionary: 
+        </p>
+        <table>
+          <tr>
+            <th>Set/Schema</th>
+            <th>Namespace Prefix</th>
+            <th>Namespace URI</th>
+          </tr>
+          <tr>
+            <td>Dublin Core</td>
+            <td>dc</td>
+            <td>http://purl.org/dc/elements/1.1/</td>
+          </tr>
+          <tr>
+            <td>XMP Basic</td>
+            <td>xmp</td>
+            <td>http://ns.adobe.com/xap/1.0/</td>
+          </tr>
+          <tr>
+            <td>Adobe PDF Schema</td>
+            <td>pdf</td>
+            <td>http://ns.adobe.com/pdf/1.3/</td>
+          </tr>
+        </table>
+        <p>
+          Please refer to the <a href="http://partners.adobe.com/public/developer/en/xmp/sdk/XMPspecification.pdf">XMP Specification</a>
+          for information on other metadata namespaces.
+        </p>
+        <p>
+          Property sets (Namespaces) not listed here are simply passed through to the final
+          document (if supported). That is useful if you want to specify a custom metadata
+          schema.
+        </p>
+      </section>
+    </section>
+    <section id="links">
+      <title>Links</title>
+      <ul>
+        <li><a href="http://www.adobe.com/products/xmp/">Adobe's Extensible Metadata Platform (XMP) website</a></li>
+        <li><a href="http://partners.adobe.com/public/developer/en/xmp/sdk/XMPspecification.pdf">Adobe XMP Specification</a></li>
+        <li><a href="http://partners.adobe.com/public/developer/en/xmp/sdk/XMPspecification.pdf">Adobe XMP Specification</a></li>
+        <li><a href="http://dublincore.org/">http://dublincore.org/</a></li>
+      </ul>
+    </section>
+  </body>
+</document>
index 1b3b75561c397c94f7c805819443b90e83397673..bfa1ae33e3296a042ad6279d248f22f513365b74 100644 (file)
@@ -28,9 +28,6 @@
   <body>
     <section id="overview">
       <title>Overview</title>
-      <warning>
-        Support for PDF/A is available beginning with version 0.92.
-      </warning>
       <p>
         PDF/A is a standard which turns PDF into an "electronic document file 
         format for long-term preservation". PDF/A-1 is the first part of the 
index 1f4425a9516cb62300d108b2902a1807357bfa04..58ae6e8e6fdf158a69772b9a5f78d4e36c7450b7 100644 (file)
@@ -34,14 +34,12 @@ import javax.xml.transform.stream.StreamSource;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
 import org.apache.xmlgraphics.util.io.Base64EncodeStream;
-
-import org.apache.fop.util.DataURIResolver;
+import org.apache.xmlgraphics.util.uri.CommonURIResolver;
 
 /**
  * Provides FOP specific URI resolution. This is the default URIResolver
- * {@link FOUserAgent} will use unless overidden.
+ * {@link FOUserAgent} will use unless overridden.
  *
  * @see javax.xml.transform.URIResolver
  */
@@ -50,8 +48,8 @@ public class FOURIResolver implements javax.xml.transform.URIResolver {
     // log
     private Log log = LogFactory.getLog("FOP");
 
-    /** URIResolver for RFC 2397 data URLs */
-    private URIResolver dataURIResolver = new DataURIResolver();
+    /** Common URIResolver */
+    private CommonURIResolver commonURIResolver = new CommonURIResolver();
 
     /** A user settable URI Resolver */
     private URIResolver uriResolver = null;
@@ -152,7 +150,7 @@ public class FOURIResolver implements javax.xml.transform.URIResolver {
 
         // data URLs can be quite long so evaluate early and don't try to build a File
         // (can lead to problems)
-        source = dataURIResolver.resolve(href, base);
+        source = commonURIResolver.resolve(href, base);
 
         // Custom uri resolution
         if (source == null && uriResolver != null) {
index f834a78aeed454f3c448a8de17f4c0570a086687..d472b574c5ca7f24d1ca2fbd886aa1f2000597c7 100644 (file)
@@ -33,9 +33,12 @@ import java.lang.ref.WeakReference;
  */
 public final class PropertyCache {
 
+    private static final int SEGMENT_COUNT = 32; //0x20
+    private static final int INITIAL_BUCKET_COUNT = SEGMENT_COUNT;
+
     /** bitmask to apply to the hash to get to the
      *  corresponding cache segment */
-    private static final int SEGMENT_MASK = 0x1F;
+    private static final int SEGMENT_MASK = SEGMENT_COUNT - 1; //0x1F
     /**
      * Indicates whether the cache should be used at all
      * Can be controlled by the system property:
@@ -44,13 +47,13 @@ public final class PropertyCache {
     private final boolean useCache;
 
     /** the segments array (length = 32) */
-    private CacheSegment[] segments = new CacheSegment[SEGMENT_MASK + 1];
+    private CacheSegment[] segments = new CacheSegment[SEGMENT_COUNT];
     /** the table of hash-buckets */
-    private CacheEntry[] table = new CacheEntry[8];
+    private CacheEntry[] table = new CacheEntry[INITIAL_BUCKET_COUNT];
 
     private Class runtimeType;
 
-    final boolean[] votesForRehash = new boolean[SEGMENT_MASK + 1];
+    private boolean[] votesForRehash = new boolean[SEGMENT_COUNT];
 
     /* same hash function as used by java.util.HashMap */
     private static int hash(Object x) {
@@ -72,53 +75,61 @@ public final class PropertyCache {
     }
 
     /* Class modeling a cached entry */
-    private final class CacheEntry extends WeakReference {
-        volatile CacheEntry nextEntry;
-        final int hash;
+    private static class CacheEntry extends WeakReference {
+        private volatile CacheEntry nextEntry;
+        private final int hash;
 
         /* main constructor */
         public CacheEntry(Object p, CacheEntry nextEntry, ReferenceQueue refQueue) {
             super(p, refQueue);
             this.nextEntry = nextEntry;
-            this.hash = p.hashCode();
+            this.hash = hash(p);
+        }
+
+        /* main constructor */
+        public CacheEntry(Object p, CacheEntry nextEntry) {
+            super(p);
+            this.nextEntry = nextEntry;
+            this.hash = hash(p);
         }
 
     }
 
     /* Wrapper objects to synchronize on */
-    private final class CacheSegment {
+    private static class CacheSegment {
         private int count = 0;
-        private volatile ReferenceQueue staleEntries = new ReferenceQueue();
     }
 
     private void cleanSegment(int segmentIndex) {
-        CacheEntry entry;
         CacheSegment segment = segments[segmentIndex];
-        int bucketIndex;
+
         int oldCount = segment.count;
 
-        while ((entry = (CacheEntry) segment.staleEntries.poll()) != null) {
-            bucketIndex = hash(entry.hash) & (table.length - 1);
-            /* remove obsolete entry */
-            /* 1. move to the corresponding entry */
+        /* clean all buckets in this segment */
+        for (int bucketIndex = segmentIndex;
+                    bucketIndex < table.length;
+                    bucketIndex += SEGMENT_COUNT) {
             CacheEntry prev = null;
-            CacheEntry e = table[bucketIndex];
-            while (e != null
-                    && e.nextEntry != null
-                    && e.hash != entry.hash) {
-                prev = e;
-                e = e.nextEntry;
+            CacheEntry entry = table[bucketIndex];
+            if (entry == null) {
+                continue;
             }
-            if (e != null) {
-                /* 2. remove reference from the chain */
-                if (prev == null) {
-                    table[bucketIndex] = e.nextEntry;
+            do {
+                if (entry.get() == null) {
+                    if (prev == null) {
+                        table[bucketIndex] = entry.nextEntry;
+                    } else {
+                        prev.nextEntry = entry.nextEntry;
+                    }
+                    segment.count--;
+                    assert segment.count >= 0;
                 } else {
-                    prev.nextEntry = e.nextEntry;
+                    prev = entry;
                 }
-                segment.count--;
-            }
+                entry = entry.nextEntry;
+            } while (entry != null);
         }
+
         synchronized (votesForRehash) {
             if (oldCount > segment.count) {
                 votesForRehash[segmentIndex] = false;
@@ -129,7 +140,7 @@ public final class PropertyCache {
                 /* first time for this segment */
                 votesForRehash[segmentIndex] = true;
                 int voteCount = 0;
-                for (int i = SEGMENT_MASK + 1; --i >= 0; ) {
+                for (int i = SEGMENT_MASK + 1; --i >= 0;) {
                     if (votesForRehash[i]) {
                         voteCount++;
                     }
@@ -156,14 +167,15 @@ public final class PropertyCache {
     private void put(Object o) {
 
         int hash = hash(o);
-        CacheSegment segment = segments[hash & SEGMENT_MASK];
+        int segmentIndex = hash & SEGMENT_MASK;
+        CacheSegment segment = segments[segmentIndex];
 
         synchronized (segment) {
             int index = hash & (table.length - 1);
             CacheEntry entry = table[index];
 
             if (entry == null) {
-                entry = new CacheEntry(o, null, segment.staleEntries);
+                entry = new CacheEntry(o, null);
                 table[index] = entry;
                 segment.count++;
             } else {
@@ -171,14 +183,14 @@ public final class PropertyCache {
                 if (eq(p, o)) {
                     return;
                 } else {
-                    CacheEntry newEntry = new CacheEntry(o, entry, segment.staleEntries);
+                    CacheEntry newEntry = new CacheEntry(o, entry);
                     table[index] = newEntry;
                     segment.count++;
                 }
             }
 
             if (segment.count > (2 * table.length)) {
-                cleanSegment(hash & SEGMENT_MASK);
+                  cleanSegment(segmentIndex);
             }
         }
     }
@@ -195,7 +207,7 @@ public final class PropertyCache {
 
         /* try non-synched first */
         for (CacheEntry e = entry; e != null; e = e.nextEntry) {
-            if (e.hash == o.hashCode()
+            if (e.hash == hash
                     && (q = e.get()) != null
                     &&  eq(q, o)) {
                 return q;
@@ -209,7 +221,7 @@ public final class PropertyCache {
         synchronized (segment) {
             entry = table[index];
             for (CacheEntry e = entry; e != null; e = e.nextEntry) {
-                if (e.hash == o.hashCode()
+                if (e.hash == hash
                         && (q = e.get()) != null
                         &&  eq(q, o)) {
                     return q;
@@ -235,7 +247,7 @@ public final class PropertyCache {
                 /* double the amount of buckets */
                 int newLength = table.length << 1;
                 if (newLength > 0) { //no overflow?
-                    /* reset segmentcounts */
+                    /* reset segment counts */
                     for (int i = segments.length; --i >= 0;) {
                         segments[i].count = 0;
                     }
@@ -250,8 +262,7 @@ public final class PropertyCache {
                             if ((o = c.get()) != null) {
                                 hash = c.hash;
                                 idx = hash & newLength;
-                                newTable[idx] = new CacheEntry(o, newTable[idx],
-                                        segments[hash & SEGMENT_MASK].staleEntries);
+                                newTable[idx] = new CacheEntry(o, newTable[idx]);
                                 segments[hash & SEGMENT_MASK].count++;
                             }
                         }
@@ -313,7 +324,7 @@ public final class PropertyCache {
      *  @param prop the Property instance to check for
      *  @return the cached instance
      */
-    public final Property fetch(Property prop) {
+    public Property fetch(Property prop) {
 
         return (Property) fetch((Object) prop);
     }
@@ -326,7 +337,7 @@ public final class PropertyCache {
      *  @param chy the CommonHyphenation instance to check for
      *  @return the cached instance
      */
-    public final CommonHyphenation fetch(CommonHyphenation chy) {
+    public CommonHyphenation fetch(CommonHyphenation chy) {
 
         return (CommonHyphenation) fetch((Object) chy);
     }
@@ -339,7 +350,7 @@ public final class PropertyCache {
      *  @param cf the CommonFont instance to check for
      *  @return the cached instance
      */
-    public final CommonFont fetch(CommonFont cf) {
+    public CommonFont fetch(CommonFont cf) {
 
         return (CommonFont) fetch((Object) cf);
     }
@@ -352,21 +363,21 @@ public final class PropertyCache {
      *  @param cbpb the CommonBorderPaddingBackground instance to check for
      *  @return the cached instance
      */
-    public final CommonBorderPaddingBackground fetch(CommonBorderPaddingBackground cbpb) {
+    public CommonBorderPaddingBackground fetch(CommonBorderPaddingBackground cbpb) {
 
         return (CommonBorderPaddingBackground) fetch((Object) cbpb);
     }
 
     /**
-     *  Checks if the given {@link CommonBorderPaddingBackground.BorderInfo} is present in the cache -
-     *  if so, returns a reference to the cached instance.
+     *  Checks if the given {@link CommonBorderPaddingBackground.BorderInfo} is present
+     *  in the cache - if so, returns a reference to the cached instance.
      *  Otherwise the given object is added to the cache and returned.
      *
      *  @param bi the BorderInfo instance to check for
      *  @return the cached instance
      */
-    public final CommonBorderPaddingBackground.BorderInfo fetch(CommonBorderPaddingBackground.BorderInfo bi) {
-
+    public CommonBorderPaddingBackground.BorderInfo fetch(
+            CommonBorderPaddingBackground.BorderInfo bi) {
         return (CommonBorderPaddingBackground.BorderInfo) fetch((Object) bi);
     }
 
index ca2245a12ff9f09691ece165d88da8b57542c265..cd0a4133b8c2d330fbc1888a68a2c097162f8c11 100644 (file)
@@ -285,7 +285,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
 
     /**
      * Get the string containing all the commands written into this
-     * Grpahics.
+     * Graphics.
      * @return the string containing the PDF markup
      */
     public String getString() {
@@ -294,7 +294,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
 
     /**
      * Get the string buffer from the currentStream, containing all
-     * the commands written into this Grpahics so far.
+     * the commands written into this Graphics so far.
      * @return the StringBuffer containing the PDF markup
      */
     public StringBuffer getBuffer() {
@@ -872,7 +872,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
         if (paint instanceof RadialGradientPaint) {
             RadialGradientPaint rgp = (RadialGradientPaint)paint;
 
-            // There is essentially no way to support repeate
+            // There is essentially no way to support repeats
             // in PDF for radial gradients (the one option would
             // be to 'grow' the outer circle until it fully covered
             // the bounds and then grow the stops accordingly, the
index d8123c4fb8b9c7e46c4f7e7b5d1801738f6131d5..06fea54cc0f80be96d5c9a6281ac4b4137f83702 100644 (file)
@@ -147,7 +147,9 @@ public class PDFTextPainter extends StrokingTextPainter {
 
             textUtil.beginTextObject();
             textUtil.setFonts(fonts);
-            textUtil.setTextRenderingMode(tpi.fillPaint != null, tpi.strokePaint != null, false);
+            boolean stroke = (tpi.strokePaint != null)
+                && (tpi.strokeStroke != null);
+            textUtil.setTextRenderingMode(tpi.fillPaint != null, stroke, false);
 
             AffineTransform localTransform = new AffineTransform();
             Point2D prevPos = null;
index 89db6dc9db6fa22a89679ccec23e8fc9959c1860..99a8318c8863c14830321bc24e7b7b77822042f7 100644 (file)
 
 package org.apache.fop.util;
 
-import java.io.ByteArrayInputStream;
-
 import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.URIResolver;
-import javax.xml.transform.stream.StreamSource;
-
-// base64 support for "data" urls
-import org.apache.xmlgraphics.util.io.Base64DecodeStream;
 
 /**
- * Resolves data URLs (described in RFC 2397) returning its data as a StreamSource.
- *
- * @see javax.xml.transform.URIResolver
- * @see <a href="http://www.ietf.org/rfc/rfc2397">RFC 2397</a>
+ * @deprecated
+ * @see org.apache.xmlgraphics.util.uri.DataURIResolver
  */
 public class DataURIResolver implements URIResolver {
 
-    /**
-     * {@inheritDoc}
-     */
-    public Source resolve(String href, String base) throws TransformerException {
-        if (href.startsWith("data:")) {
-            return parseDataURI(href);
-        } else {
-            return null;
-        }
-    }
+    private final URIResolver newResolver = new org.apache.xmlgraphics.util.uri.DataURIResolver();
 
     /**
-     * Parses inline data URIs as generated by MS Word's XML export and FO
-     * stylesheet.
-     *
-     * @see <a href="http://www.ietf.org/rfc/rfc2397">RFC 2397</a>
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.uri.DataURIResolver#resolve(String,
+     *      String)
      */
-    private Source parseDataURI(String href) {
-        int commaPos = href.indexOf(',');
-        // header is of the form data:[<mediatype>][;base64]
-        String header = href.substring(0, commaPos);
-        String data = href.substring(commaPos + 1);
-        if (header.endsWith(";base64")) {
-            byte[] bytes = data.getBytes();
-            ByteArrayInputStream encodedStream = new ByteArrayInputStream(bytes);
-            Base64DecodeStream decodedStream = new Base64DecodeStream(
-                    encodedStream);
-            return new StreamSource(decodedStream);
-        } else {
-            // Note that this is not quite the full story here. But since we are
-            // only interested
-            // in base64-encoded binary data, the next line will probably never
-            // be called.
-            //TODO Handle un-escaping of special URL chars like %20
-            return new StreamSource(new java.io.StringReader(data));
-        }
+    public Source resolve(String href, String base) throws TransformerException {
+        return newResolver.resolve(href, base);
     }
 
 }
index d8f7f17bfabc96911a129368e1f84b33a4e3b633..8568df2740f6db1a216c8e5664f0b6d25efe7026 100644 (file)
@@ -21,47 +21,33 @@ package org.apache.fop.util;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.StringWriter;
 import java.io.Writer;
 
-import org.apache.commons.io.IOUtils;
-import org.apache.xmlgraphics.util.io.Base64EncodeStream;
-
 /**
- * Utility classes for generating RFC 2397 data URLs.
+ * @deprecated
+ * @see org.apache.xmlgraphics.util.uri.DataURLUtil
  */
 public class DataURLUtil {
 
     /**
-     * Creates a new data URL and returns it as a String.
-     * @param in the InputStream to read the data from
-     * @param mediatype the MIME type of the content, or null
-     * @return the newly created data URL
-     * @throws IOException if an I/O error occurs
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.uri.DataURLUtil#createDataURL(InputStream,
+     *      String)
      */
-    public static String createDataURL(InputStream in, String mediatype) throws IOException {
-        StringWriter writer = new StringWriter();
-        writeDataURL(in, mediatype, writer);
-        return writer.toString();
+    public static String createDataURL(InputStream in, String mediatype)
+            throws IOException {
+        return org.apache.xmlgraphics.util.uri.DataURLUtil.createDataURL(in,
+                mediatype);
     }
 
     /**
-     * Generates a data URL and writes it to a Writer.
-     * @param in the InputStream to read the data from
-     * @param mediatype the MIME type of the content, or null
-     * @param writer the Writer to write to
-     * @throws IOException if an I/O error occurs
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.uri.DataURLUtil#writeDataURL(InputStream,
+     *      String, Writer)
      */
-    public static void writeDataURL(InputStream in, String mediatype, Writer writer)
-            throws IOException {
-        writer.write("data:");
-        if (mediatype != null) {
-            writer.write(mediatype);
-        }
-        writer.write(";base64,");
-        Base64EncodeStream out = new Base64EncodeStream(
-                new WriterOutputStream(writer, "US-ASCII"));
-        IOUtils.copy(in, out);
-        out.flush();
+    public static void writeDataURL(InputStream in, String mediatype,
+            Writer writer) throws IOException {
+        org.apache.xmlgraphics.util.uri.DataURLUtil.writeDataURL(in, mediatype,
+                writer);
     }
 }
diff --git a/src/java/org/apache/fop/util/UnitConv.java b/src/java/org/apache/fop/util/UnitConv.java
new file mode 100644 (file)
index 0000000..cf59971
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.util;
+
+import java.awt.geom.AffineTransform;
+
+/**
+ * Utility class for unit conversions.
+ * @deprecated use org.apache.xmlgraphics.util.UnitConv instead.
+ */
+public final class UnitConv {
+
+    /**
+     * conversion factory from millimeters to inches.
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.IN2MM instead.
+     */
+    public static final float IN2MM = org.apache.xmlgraphics.util.UnitConv.IN2MM;
+
+    /**
+     * conversion factory from centimeters to inches.
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.IN2CM instead.
+     */
+    public static final float IN2CM = org.apache.xmlgraphics.util.UnitConv.IN2CM;
+
+    /**
+     * conversion factory from inches to points.
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.IN2PT instead.
+     */
+    public static final int IN2PT = org.apache.xmlgraphics.util.UnitConv.IN2PT;
+
+    /**
+     * Converts millimeters (mm) to points (pt)
+     * @param mm the value in mm
+     * @return the value in pt
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.mm2pt(mm) instead.
+     */
+    public static double mm2pt(double mm) {
+        return org.apache.xmlgraphics.util.UnitConv.mm2pt(mm);
+    }
+
+    /**
+     * Converts millimeters (mm) to millipoints (mpt)
+     * @param mm the value in mm
+     * @return the value in mpt
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.mm2mpt(mm) instead.
+     */
+    public static double mm2mpt(double mm) {
+        return org.apache.xmlgraphics.util.UnitConv.mm2mpt(mm);
+    }
+
+    /**
+     * Converts points (pt) to millimeters (mm)
+     * @param pt the value in pt
+     * @return the value in mm
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.pt2mm(pt) instead.
+     */
+    public static double pt2mm(double pt) {
+        return org.apache.xmlgraphics.util.UnitConv.pt2mm(pt);
+    }
+
+    /**
+     * Converts millimeters (mm) to inches (in)
+     * @param mm the value in mm
+     * @return the value in inches
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.pt2mm(pt) instead.
+     */
+    public static double mm2in(double mm) {
+        return org.apache.xmlgraphics.util.UnitConv.mm2in(mm);
+    }
+
+    /**
+     * Converts inches (in) to millimeters (mm)
+     * @param in the value in inches
+     * @return the value in mm
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.in2mm(in) instead.
+     */
+    public static double in2mm(double in) {
+        return org.apache.xmlgraphics.util.UnitConv.in2mm(in);
+    }
+
+    /**
+     * Converts inches (in) to millipoints (mpt)
+     * @param in the value in inches
+     * @return the value in mpt
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.in2mpt(in) instead.
+     */
+    public static double in2mpt(double in) {
+        return org.apache.xmlgraphics.util.UnitConv.in2mpt(in);
+    }
+
+    /**
+     * Converts inches (in) to points (pt)
+     * @param in the value in inches
+     * @return the value in pt
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.in2pt(in) instead.
+     */
+    public static double in2pt(double in) {
+        return org.apache.xmlgraphics.util.UnitConv.in2pt(in);
+    }
+
+    /**
+     * Converts millipoints (mpt) to inches (in)
+     * @param mpt the value in mpt
+     * @return the value in inches
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.mpt2in(mpt) instead.
+     */
+    public static double mpt2in(double mpt) {
+        return org.apache.xmlgraphics.util.UnitConv.mpt2in(mpt);
+    }
+
+    /**
+     * Converts millimeters (mm) to pixels (px)
+     * @param mm the value in mm
+     * @param resolution the resolution in dpi (dots per inch)
+     * @return the value in pixels
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.mm2px(mm, resolution) instead.
+     */
+    public static double mm2px(double mm, int resolution) {
+        return org.apache.xmlgraphics.util.UnitConv.mm2px(mm, resolution);
+    }
+
+    /**
+     * Converts millipoints (mpt) to pixels (px)
+     * @param mpt the value in mpt
+     * @param resolution the resolution in dpi (dots per inch)
+     * @return the value in pixels
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.mpt2px(mpt, resolution) instead.
+     */
+    public static double mpt2px(double mpt, int resolution) {
+        return org.apache.xmlgraphics.util.UnitConv.mpt2px(mpt, resolution);
+    }
+
+    /**
+     * Converts a millipoint-based transformation matrix to points.
+     * @param at a millipoint-based transformation matrix
+     * @return a point-based transformation matrix
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.mptToPt(at) instead.
+     */
+    public static AffineTransform mptToPt(AffineTransform at) {
+        return org.apache.xmlgraphics.util.UnitConv.mptToPt(at);
+    }
+
+    /**
+     * Converts a point-based transformation matrix to millipoints.
+     * @param at a point-based transformation matrix
+     * @return a millipoint-based transformation matrix
+     * @deprecated use org.apache.xmlgraphics.util.UnitConv.ptToMpt(at) instead.
+     */
+    public static AffineTransform ptToMpt(AffineTransform at) {
+        return org.apache.xmlgraphics.util.UnitConv.ptToMpt(at);
+    }
+
+}
index fb68754989ed129760a687059ec657f47abdd767..e08109ab0d0b5cbdf12d1c0cc927bb4a654ee77c 100644 (file)
@@ -24,68 +24,72 @@ import java.io.OutputStream;
 import java.io.Writer;
 
 /**
- * An OutputStream wrapper for a Writer.
+ * @deprecated
+ * @see org.apache.xmlgraphics.util.WriterOutputStream
  */
 public class WriterOutputStream extends OutputStream {
 
-    private Writer writer;
-    private String encoding;
+    private final org.apache.xmlgraphics.util.WriterOutputStream writerOutputStream;
 
     /**
-     * Creates a new WriterOutputStream.
-     * @param writer the Writer to write to
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.WriterOutputStream#WriterOutputStream(Writer)
+     *      String)
      */
     public WriterOutputStream(Writer writer) {
-        this(writer, null);
+        writerOutputStream = new org.apache.xmlgraphics.util.WriterOutputStream(
+                writer);
     }
 
     /**
-     * Creates a new WriterOutputStream.
-     * @param writer the Writer to write to
-     * @param encoding the encoding to use, or null if the default encoding should be used
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.WriterOutputStream#WriterOutputStream(Writer,
+     *      String) String)
      */
     public WriterOutputStream(Writer writer, String encoding) {
-        this.writer = writer;
-        this.encoding = encoding;
+        writerOutputStream = new org.apache.xmlgraphics.util.WriterOutputStream(
+                writer, encoding);
     }
 
     /**
-     * {@inheritDoc}
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.WriterOutputStream#close()
      */
     public void close() throws IOException {
-        writer.close();
+        writerOutputStream.close();
     }
 
     /**
-     * {@inheritDoc}
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.WriterOutputStream#flush()
      */
     public void flush() throws IOException {
-        writer.flush();
+        writerOutputStream.flush();
     }
 
     /**
-     * {@inheritDoc}
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.WriterOutputStream#write(byte[], int,
+     *      int)
      */
     public void write(byte[] buf, int offset, int length) throws IOException {
-        if (encoding != null) {
-            writer.write(new String(buf, offset, length, encoding));
-        } else {
-            writer.write(new String(buf, offset, length));
-        }
+        writerOutputStream.write(buf, offset, length);
     }
 
     /**
-     * {@inheritDoc}
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.WriterOutputStream#write(byte[])
      */
     public void write(byte[] buf) throws IOException {
-        write(buf, 0, buf.length);
+        writerOutputStream.write(buf);
     }
 
     /**
-     * {@inheritDoc}
+     * @deprecated
+     * @see org.apache.xmlgraphics.util.WriterOutputStream#write(int)
      */
     public void write(int b) throws IOException {
-        write(new byte[] {(byte)b});
+        writerOutputStream.write(b);
     }
 
 }
index 1cde45913adfe2705c6978b275b839d9035fe917..02edefb4e25b0b210cb4f5f34c19bc2bb96fd0fb 100644 (file)
 
   <changes>
     <release version="FOP Trunk" date="TBD">
+      <action context="Code" dev="JM" type="fix" importance="high">
+        Fixed memory leak in property cache (not cleaning stale PropertyCache$CacheEntry instances).
+      </action>
+      <action context="Renderers" dev="JM" type="fix">
+        Fixed text stroking in SVG when the stroke-width is zero.
+      </action>
       <action context="Layout" dev="JM" type="fix">
         Fixed the source for a division by zero when the content of an fo:leader with
         leader-pattern="use-content" collapses to zero width during layout.
         Fixed a ClassCastException when using an fo:wrapper as a child
         of an fo:block-container.
       </action>
-      <action context="Fonts" dev="AC" type="add">
+      <action context="Fonts" dev="AC" type="add" importance="high">
         Add support for font substitution.
       </action>
       <action context="Renderers" dev="JM" type="fix" fixes-bug="43650">
         Add partial support for the "show-destination" property on fo:basic-link
         (PDF output only; see limitations on the compliance page)
       </action>
-      <action context="Layout" dev="JM" type="add">
+      <action context="Layout" dev="JM" type="add" importance="high">
         Added minimal support for integer keep values on the various keep properties on block-level
         FOs. For now, all integer values are treated the same (i.e. without strength distinction).
         Using integers allows to avoid overflows that can happen when "always" is used extensively.
         When a JPEG image is embedded, an optionally embedded color profile is filtered out
         as it's already embedded separately in the PDF file.
       </action>
-      <action context="Fonts" dev="JM" type="add">
+      <action context="Fonts" dev="JM" type="add" importance="high">
         Added support for addressing all glyphs available in a Type 1 font, not just the ones
         in the font's primary encoding.
       </action>
       <action context="Code" dev="JM" type="fix">
         AFP Renderer: Bugfix for 1 bit images where the width is not a multiple of 8.
       </action>
-      <action context="Code" dev="MM" type="add">
+      <action context="Code" dev="MM" type="add" importance="high">
         Support for keep-together.within-line="always".
       </action>
       <action context="Code" dev="MM" type="fix">
index 6611f532e7b16dae2425b5cfb0bcbb2a2316dac1..a073c4988efaa6ab0de247231de2dad0c2515ef5 100644 (file)
@@ -26,7 +26,6 @@ import org.apache.fop.events.BasicEventTestCase;
 import org.apache.fop.pdf.PDFObjectTestCase;
 import org.apache.fop.traits.BorderPropsTestCase;
 import org.apache.fop.util.ColorUtilTestCase;
-import org.apache.fop.util.DataURIResolverTestCase;
 import org.apache.fop.util.ElementListUtilsTestCase;
 import org.apache.fop.util.PDFNumberTestCase;
 import org.apache.fop.util.XMLResourceBundleTestCase;
@@ -49,7 +48,6 @@ public class UtilityCodeTestSuite {
         suite.addTest(new TestSuite(ColorUtilTestCase.class));
         suite.addTest(new TestSuite(BorderPropsTestCase.class));
         suite.addTest(new TestSuite(ElementListUtilsTestCase.class));
-        suite.addTest(new TestSuite(DataURIResolverTestCase.class));
         suite.addTest(new TestSuite(BasicEventTestCase.class));
         suite.addTest(new TestSuite(XMLResourceBundleTestCase.class));
         //$JUnit-END$
index bdbd47897c90a06d186df36bd4a35f57a601855f..a665580ae06feddd4a2779bb9f92e728cb37f390 100644 (file)
@@ -34,6 +34,7 @@ import javax.xml.transform.sax.SAXResult;
 import javax.xml.transform.sax.SAXTransformerFactory;
 import javax.xml.transform.stream.StreamSource;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.NullOutputStream;
 
 import org.apache.fop.apps.FOUserAgent;
@@ -51,28 +52,48 @@ public class MemoryEater {
     private FopFactory fopFactory = FopFactory.newInstance();
     private Templates replicatorTemplates;
 
+    private Stats stats;
+
     public MemoryEater() throws TransformerConfigurationException, MalformedURLException {
         File xsltFile = new File("test/xsl/fo-replicator.xsl");
         Source xslt = new StreamSource(xsltFile);
         replicatorTemplates = tFactory.newTemplates(xslt);
     }
 
-    private void eatMemory(File foFile, int replicatorRepeats) throws Exception {
+    private void eatMemory(File foFile, int runRepeats, int replicatorRepeats) throws Exception {
+        stats = new Stats();
+        for (int i = 0; i < runRepeats; i++) {
+            eatMemory(i, foFile, replicatorRepeats);
+            stats.progress(i, runRepeats);
+        }
+        stats.dumpFinalStats();
+        System.out.println(stats.getGoogleChartURL());
+    }
+
+    private void eatMemory(int callIndex, File foFile, int replicatorRepeats) throws Exception {
         Source src = new StreamSource(foFile);
 
         Transformer transformer = replicatorTemplates.newTransformer();
         transformer.setParameter("repeats", new Integer(replicatorRepeats));
 
         OutputStream out = new NullOutputStream(); //write to /dev/nul
-        FOUserAgent userAgent = fopFactory.newFOUserAgent();
-        userAgent.setBaseURL(foFile.getParentFile().toURL().toExternalForm());
-        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
-        Result res = new SAXResult(fop.getDefaultHandler());
-
-        transformer.transform(src, res);
+        try {
+            FOUserAgent userAgent = fopFactory.newFOUserAgent();
+            userAgent.setBaseURL(foFile.getParentFile().toURL().toExternalForm());
+            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
+            Result res = new SAXResult(fop.getDefaultHandler());
 
-        System.out.println("Generated " + fop.getResults().getPageCount() + " pages.");
+            transformer.transform(src, res);
 
+            stats.notifyPagesProduced(fop.getResults().getPageCount());
+            if (callIndex == 0) {
+                System.out.println(foFile.getName() + " generates "
+                        + fop.getResults().getPageCount() + " pages.");
+            }
+            stats.checkStats();
+        } finally {
+            IOUtils.closeQuietly(out);
+        }
     }
 
     private static void prompt() throws IOException {
@@ -108,9 +129,7 @@ public class MemoryEater {
             long start = System.currentTimeMillis();
 
             MemoryEater app = new MemoryEater();
-            for (int i = 0; i < runRepeats; i++) {
-                app.eatMemory(testFile, replicatorRepeats);
-            }
+            app.eatMemory(testFile, runRepeats, replicatorRepeats);
 
             long duration = System.currentTimeMillis() - start;
             System.out.println("Success! Job took " + duration + " ms");
diff --git a/test/java/org/apache/fop/memory/Stats.java b/test/java/org/apache/fop/memory/Stats.java
new file mode 100644 (file)
index 0000000..9e37125
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.memory;
+
+import java.util.Iterator;
+import java.util.List;
+
+class Stats {
+
+    private static final int INTERVAL = 2000;
+
+    private long startTime = System.currentTimeMillis();
+    private long lastProgressDump = startTime;
+    private int pagesProduced;
+
+    private int totalPagesProduced;
+
+    private int step;
+    private int stepCount;
+
+    private List samples = new java.util.LinkedList();
+
+    public void checkStats() {
+        long now = System.currentTimeMillis();
+        if (now > lastProgressDump + INTERVAL) {
+            dumpStats();
+            reset();
+        }
+    }
+
+    public void notifyPagesProduced(int count) {
+        pagesProduced += count;
+        totalPagesProduced += count;
+    }
+
+    public void reset() {
+        pagesProduced = 0;
+        lastProgressDump = System.currentTimeMillis();
+    }
+
+    public void dumpStats() {
+        long duration = System.currentTimeMillis() - lastProgressDump;
+
+        if (stepCount != 0) {
+            int progress = 100 * step / stepCount;
+            System.out.println("Progress: " + progress + "%, " + (stepCount - step) + " left");
+        }
+
+        long ppm = 60000 * pagesProduced / duration;
+        System.out.println("Speed: " + ppm + "ppm");
+        samples.add(new Sample((int)ppm));
+    }
+
+    public void dumpFinalStats() {
+        long duration = System.currentTimeMillis() - startTime;
+        System.out.println("Final statistics");
+        System.out.println("Pages produced: " +totalPagesProduced);
+        long ppm = 60000 * totalPagesProduced / duration;
+        System.out.println("Average speed: " + ppm + "ppm");
+    }
+
+    public String getGoogleChartURL() {
+        StringBuffer sb = new StringBuffer("http://chart.apis.google.com/chart?");
+        //http://chart.apis.google.com/chart?cht=ls&chd=t:60,40&chs=250x100&chl=Hello|World
+        sb.append("cht=ls");
+        sb.append("&chd=t:");
+        boolean first = true;
+        int maxY = 0;
+        Iterator iter = samples.iterator();
+        while (iter.hasNext()) {
+            Sample sample = (Sample)iter.next();
+            if (first) {
+                first = false;
+            } else {
+                sb.append(',');
+            }
+            sb.append(sample.ppm);
+            maxY = Math.max(maxY, sample.ppm);
+        }
+        int ceilY = ((maxY / 1000) + 1) * 1000;
+        sb.append("&chs=1000x300"); //image size
+        sb.append("&chds=0,").append(ceilY); //data scale
+        sb.append("&chg=0,20"); //scale steps
+        sb.append("&chxt=y");
+        sb.append("&chxl=0:|0|" + ceilY);
+        return sb.toString();
+    }
+
+    private static class Sample {
+
+        private int ppm;
+
+        public Sample(int ppm) {
+            this.ppm = ppm;
+        }
+    }
+
+    public void progress(int step, int stepCount) {
+        this.step = step;
+        this.stepCount = stepCount;
+
+    }
+
+}
diff --git a/test/java/org/apache/fop/util/DataURIResolverTestCase.java b/test/java/org/apache/fop/util/DataURIResolverTestCase.java
deleted file mode 100644 (file)
index 631b8da..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.util;
-
-import java.io.ByteArrayInputStream;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.URIResolver;
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.commons.io.IOUtils;
-
-import junit.framework.TestCase;
-
-/**
- * Test case for the RFC 2397 data URL/URI resolver.
- */
-public class DataURIResolverTestCase extends TestCase {
-
-    private static final byte[] TESTDATA = new byte[] {0, 1, 2, 3, 4, 5};
-
-    /**
-     * Tests DataURLUtil.
-     * @throws Exception if an error occurs
-     */
-    public void testRFC2397Generator() throws Exception {
-        String url = DataURLUtil.createDataURL(new ByteArrayInputStream(TESTDATA), null);
-        assertEquals("Generated data URL is wrong", "data:;base64,AAECAwQF", url);
-
-        url = DataURLUtil.createDataURL(new ByteArrayInputStream(TESTDATA), "application/pdf");
-        assertEquals("Generated data URL is wrong", "data:application/pdf;base64,AAECAwQF", url);
-    }
-
-    /**
-     * Test the URIResolver contract if the protocol doesn't match. Resolver must return null
-     * in this case.
-     * @throws Exception if an error occurs
-     */
-    public void testNonMatchingContract() throws Exception {
-        URIResolver resolver = new DataURIResolver();
-        Source src;
-
-        src = resolver.resolve("http://xmlgraphics.apache.org/fop/index.html", null);
-        assertNull(src);
-
-        src = resolver.resolve("index.html", "http://xmlgraphics.apache.org/fop/");
-        assertNull(src);
-    }
-
-    private static boolean byteCmp(byte[] src, int srcOffset, byte[] cmp) {
-        for (int i = 0, c = cmp.length; i < c; i++) {
-            if (src[srcOffset + i] != cmp[i]) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Test the DataURIResolver with correct values.
-     * @throws Exception if an error occurs
-     */
-    public void testDataURLHandling() throws Exception {
-        URIResolver resolver = new DataURIResolver();
-        Source src;
-
-        src = resolver.resolve("data:;base64,AAECAwQF", null);
-        assertNotNull(src);
-        StreamSource streamSource = (StreamSource)src;
-        byte[] data = IOUtils.toByteArray(streamSource.getInputStream());
-        assertTrue("Decoded data doesn't match the test data", byteCmp(TESTDATA, 0, data));
-
-        src = resolver.resolve(
-                "data:application/octet-stream;interpreter=fop;base64,AAECAwQF", null);
-        assertNotNull(src);
-        streamSource = (StreamSource)src;
-        assertNotNull(streamSource.getInputStream());
-        assertNull(streamSource.getReader());
-        data = IOUtils.toByteArray(streamSource.getInputStream());
-        assertTrue("Decoded data doesn't match the test data", byteCmp(TESTDATA, 0, data));
-
-        src = resolver.resolve("data:,FOP", null);
-        assertNotNull(src);
-        streamSource = (StreamSource)src;
-        assertNull(streamSource.getInputStream());
-        assertNotNull(streamSource.getReader());
-        String text = IOUtils.toString(streamSource.getReader());
-        assertEquals("FOP", text);
-
-        /* TODO Un-escaping of special URL chars like %20 hasn't been implemented, yet.
-        src = resolver.resolve("data:,A%20brief%20note", null);
-        assertNotNull(src);
-        streamSource = (StreamSource)src;
-        text = IOUtils.toString(streamSource.getReader());
-        assertEquals("A brief note", text);
-        */
-    }
-
-}